@nestia/sdk 2.0.0-dev.20230991 → 2.0.1
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/assets/bundle/api/utils/NestiaSimulator.ts +5 -14
- package/lib/INestiaConfig.d.ts +60 -47
- package/lib/NestiaSdkApplication.d.ts +6 -5
- package/lib/NestiaSdkApplication.js +30 -87
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ControllerAnalyzer.js +8 -5
- package/lib/analyses/ControllerAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectAnalyzer.js +9 -1
- package/lib/analyses/ReflectAnalyzer.js.map +1 -1
- package/lib/executable/internal/NestiaConfigLoader.d.ts +7 -0
- package/lib/executable/internal/NestiaConfigLoader.js +582 -0
- package/lib/executable/internal/NestiaConfigLoader.js.map +1 -0
- package/lib/executable/internal/NestiaProjectGetter.d.ts +3 -0
- package/lib/executable/internal/NestiaProjectGetter.js +28 -0
- package/lib/executable/internal/NestiaProjectGetter.js.map +1 -0
- package/lib/executable/internal/NestiaSdkCommand.d.ts +3 -3
- package/lib/executable/internal/NestiaSdkCommand.js +13 -104
- package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
- package/lib/executable/internal/{nestia.config.getter.js → nestia.project.getter.js} +3 -3
- package/lib/executable/internal/nestia.project.getter.js.map +1 -0
- package/lib/executable/sdk.js +3 -3
- package/lib/executable/sdk.js.map +1 -1
- package/lib/generates/SdkGenerator.d.ts +2 -1
- package/lib/generates/SdkGenerator.js +7 -3
- package/lib/generates/SdkGenerator.js.map +1 -1
- package/lib/generates/SwaggerGenerator.js +26 -9
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.js +21 -15
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/{DistributionComposer.d.ts → SdkDistributionComposer.d.ts} +1 -1
- package/lib/generates/internal/{DistributionComposer.js → SdkDistributionComposer.js} +8 -12
- package/lib/generates/internal/SdkDistributionComposer.js.map +1 -0
- package/lib/generates/internal/SdkDtoGenerator.d.ts +9 -0
- package/lib/generates/internal/SdkDtoGenerator.js +264 -0
- package/lib/generates/internal/SdkDtoGenerator.js.map +1 -0
- package/lib/generates/internal/SdkFileProgrammer.js +8 -7
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkFunctionProgrammer.js +32 -22
- package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkImportWizard.d.ts +2 -0
- package/lib/generates/internal/SdkImportWizard.js +10 -0
- package/lib/generates/internal/SdkImportWizard.js.map +1 -1
- package/lib/generates/internal/SdkSimulationProgrammer.js +61 -25
- package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkTypeDefiner.d.ts +11 -0
- package/lib/generates/internal/SdkTypeDefiner.js +82 -0
- package/lib/generates/internal/SdkTypeDefiner.js.map +1 -0
- package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +1 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.js +67 -75
- package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
- package/lib/generates/internal/SwaggerSchemaValidator.js +0 -8
- package/lib/generates/internal/SwaggerSchemaValidator.js.map +1 -1
- package/lib/structures/IController.d.ts +2 -0
- package/lib/structures/IRoute.d.ts +9 -2
- package/lib/utils/ImportDictionary.d.ts +1 -2
- package/lib/utils/ImportDictionary.js +28 -24
- package/lib/utils/ImportDictionary.js.map +1 -1
- package/package.json +8 -8
- package/src/INestiaConfig.ts +65 -50
- package/src/NestiaSdkApplication.ts +39 -84
- package/src/analyses/ControllerAnalyzer.ts +10 -8
- package/src/analyses/ReflectAnalyzer.ts +8 -0
- package/src/executable/internal/NestiaConfigLoader.ts +82 -0
- package/src/executable/internal/NestiaProjectGetter.ts +11 -0
- package/src/executable/internal/NestiaSdkCommand.ts +23 -146
- package/src/executable/internal/{nestia.config.getter.ts → nestia.project.getter.ts} +2 -2
- package/src/executable/sdk.ts +3 -3
- package/src/generates/SdkGenerator.ts +9 -2
- package/src/generates/SwaggerGenerator.ts +37 -9
- package/src/generates/internal/E2eFileProgrammer.ts +33 -20
- package/src/generates/internal/{DistributionComposer.ts → SdkDistributionComposer.ts} +3 -6
- package/src/generates/internal/SdkDtoGenerator.ts +384 -0
- package/src/generates/internal/SdkFileProgrammer.ts +8 -7
- package/src/generates/internal/SdkFunctionProgrammer.ts +71 -37
- package/src/generates/internal/SdkImportWizard.ts +14 -0
- package/src/generates/internal/SdkSimulationProgrammer.ts +71 -37
- package/src/generates/internal/SdkTypeDefiner.ts +120 -0
- package/src/generates/internal/SwaggerSchemaGenerator.ts +94 -92
- package/src/generates/internal/SwaggerSchemaValidator.ts +0 -12
- package/src/structures/IController.ts +2 -0
- package/src/structures/IRoute.ts +10 -2
- package/src/utils/ImportDictionary.ts +29 -26
- package/lib/executable/internal/NestiaConfigCompilerOptions.d.ts +0 -12
- package/lib/executable/internal/NestiaConfigCompilerOptions.js +0 -18
- package/lib/executable/internal/NestiaConfigCompilerOptions.js.map +0 -1
- package/lib/executable/internal/NestiaSdkConfig.d.ts +0 -4
- package/lib/executable/internal/NestiaSdkConfig.js +0 -1019
- package/lib/executable/internal/NestiaSdkConfig.js.map +0 -1
- package/lib/executable/internal/nestia.config.getter.js.map +0 -1
- package/lib/generates/internal/DistributionComposer.js.map +0 -1
- package/src/executable/internal/NestiaConfigCompilerOptions.ts +0 -19
- package/src/executable/internal/NestiaSdkConfig.ts +0 -36
- /package/lib/executable/internal/{nestia.config.getter.d.ts → nestia.project.getter.d.ts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
2
3
|
import { IController } from "./IController";
|
|
3
4
|
export interface IRoute {
|
|
4
5
|
name: string;
|
|
@@ -11,10 +12,13 @@ export interface IRoute {
|
|
|
11
12
|
imports: [string, string[]][];
|
|
12
13
|
output: IRoute.IOutput;
|
|
13
14
|
location: string;
|
|
14
|
-
symbol:
|
|
15
|
+
symbol: {
|
|
16
|
+
class: string;
|
|
17
|
+
function: string;
|
|
18
|
+
};
|
|
15
19
|
description?: string;
|
|
16
20
|
operationId?: string;
|
|
17
|
-
|
|
21
|
+
jsDocTags: ts.JSDocTagInfo[];
|
|
18
22
|
setHeaders: Array<{
|
|
19
23
|
type: "setter";
|
|
20
24
|
source: string;
|
|
@@ -25,16 +29,19 @@ export interface IRoute {
|
|
|
25
29
|
}>;
|
|
26
30
|
security: Record<string, string[]>[];
|
|
27
31
|
exceptions: Record<number | "2XX" | "3XX" | "4XX" | "5XX", IRoute.IOutput>;
|
|
32
|
+
swaggerTags: string[];
|
|
28
33
|
}
|
|
29
34
|
export declare namespace IRoute {
|
|
30
35
|
type IParameter = IController.IParameter & {
|
|
31
36
|
optional: boolean;
|
|
32
37
|
type: ts.Type;
|
|
33
38
|
typeName: string;
|
|
39
|
+
metadata?: Metadata;
|
|
34
40
|
};
|
|
35
41
|
interface IOutput {
|
|
36
42
|
type: ts.Type;
|
|
37
43
|
typeName: string;
|
|
44
|
+
metadata?: Metadata;
|
|
38
45
|
description?: string;
|
|
39
46
|
contentType: "application/json" | "text/plain";
|
|
40
47
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export declare class ImportDictionary {
|
|
2
|
-
private readonly
|
|
3
|
-
private readonly internals_;
|
|
2
|
+
private readonly components_;
|
|
4
3
|
empty(): boolean;
|
|
5
4
|
external(props: ImportDictionary.IExternalProps): string;
|
|
6
5
|
internal(props: ImportDictionary.IInternalProps): string;
|
|
@@ -10,16 +10,15 @@ const HashSet_1 = require("tstl/container/HashSet");
|
|
|
10
10
|
const Pair_1 = require("tstl/utility/Pair");
|
|
11
11
|
class ImportDictionary {
|
|
12
12
|
constructor() {
|
|
13
|
-
this.
|
|
14
|
-
this.internals_ = new HashMap_1.HashMap();
|
|
13
|
+
this.components_ = new HashMap_1.HashMap();
|
|
15
14
|
}
|
|
16
15
|
empty() {
|
|
17
|
-
return this.
|
|
16
|
+
return this.components_.empty();
|
|
18
17
|
}
|
|
19
18
|
external(props) {
|
|
20
19
|
var _a;
|
|
21
|
-
const composition = this.
|
|
22
|
-
location: props.library
|
|
20
|
+
const composition = this.components_.take(new Pair_1.Pair(props.library, props.type), () => ({
|
|
21
|
+
location: `node_modules/${props.library}`,
|
|
23
22
|
elements: new HashSet_1.HashSet(),
|
|
24
23
|
default: false,
|
|
25
24
|
type: props.type,
|
|
@@ -39,7 +38,7 @@ class ImportDictionary {
|
|
|
39
38
|
return props.file.substring(0, props.file.length - 3);
|
|
40
39
|
return props.file;
|
|
41
40
|
})();
|
|
42
|
-
const composition = this.
|
|
41
|
+
const composition = this.components_.take(new Pair_1.Pair(file, props.type), () => ({
|
|
43
42
|
location: file,
|
|
44
43
|
elements: new HashSet_1.HashSet(),
|
|
45
44
|
default: false,
|
|
@@ -55,11 +54,25 @@ class ImportDictionary {
|
|
|
55
54
|
return (_a = props.instance) !== null && _a !== void 0 ? _a : file;
|
|
56
55
|
}
|
|
57
56
|
toScript(outDir) {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
57
|
+
const external = [];
|
|
58
|
+
const internal = [];
|
|
59
|
+
const locator = (str) => {
|
|
60
|
+
const location = path_1.default
|
|
61
|
+
.relative(outDir, str)
|
|
62
|
+
.split("\\")
|
|
63
|
+
.join("/");
|
|
64
|
+
const index = location.lastIndexOf(NODE_MODULES);
|
|
65
|
+
return index === -1
|
|
66
|
+
? location.startsWith("..")
|
|
67
|
+
? location
|
|
68
|
+
: `./${location}`
|
|
69
|
+
: location.substring(index + NODE_MODULES.length);
|
|
70
|
+
};
|
|
71
|
+
const enroll = (filter) => (container) => {
|
|
60
72
|
var _a;
|
|
61
|
-
const compositions =
|
|
73
|
+
const compositions = this.components_
|
|
62
74
|
.toJSON()
|
|
75
|
+
.filter((c) => filter(c.second.location))
|
|
63
76
|
.map((e) => (Object.assign(Object.assign({}, e.second), { location: locator(e.second.location) })))
|
|
64
77
|
.sort((a, b) => a.location.localeCompare(b.location));
|
|
65
78
|
for (const c of compositions) {
|
|
@@ -71,23 +84,14 @@ class ImportDictionary {
|
|
|
71
84
|
.toJSON()
|
|
72
85
|
.sort((a, b) => a.localeCompare(b))
|
|
73
86
|
.join(", ")} }`);
|
|
74
|
-
|
|
87
|
+
container.push(`import ${c.type ? "type " : ""}${brackets.join(", ")} from "${c.location}";`);
|
|
75
88
|
}
|
|
76
89
|
};
|
|
77
|
-
enroll((str) => str)(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
.relative(outDir, str)
|
|
83
|
-
.split("\\")
|
|
84
|
-
.join("/");
|
|
85
|
-
const index = location.lastIndexOf(NODE_MODULES);
|
|
86
|
-
return index === -1
|
|
87
|
-
? `./${location}`
|
|
88
|
-
: location.substring(index + NODE_MODULES.length);
|
|
89
|
-
})(this.internals_);
|
|
90
|
-
return statements.join("\n");
|
|
90
|
+
enroll((str) => str.indexOf(NODE_MODULES) !== -1)(external);
|
|
91
|
+
enroll((str) => str.indexOf(NODE_MODULES) === -1)(internal);
|
|
92
|
+
if (external.length && internal.length)
|
|
93
|
+
external.push("");
|
|
94
|
+
return [...external, ...internal].join("\n");
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
exports.ImportDictionary = ImportDictionary;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportDictionary.js","sourceRoot":"","sources":["../../src/utils/ImportDictionary.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,oDAAiD;AACjD,oDAAiD;AACjD,4CAAyC;AAEzC,MAAa,gBAAgB;IAA7B;QACqB,
|
|
1
|
+
{"version":3,"file":"ImportDictionary.js","sourceRoot":"","sources":["../../src/utils/ImportDictionary.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestia/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Nestia SDK and Swagger generator",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
@@ -35,25 +35,25 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://nestia.io",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@nestia/fetcher": "^2.0.
|
|
38
|
+
"@nestia/fetcher": "^2.0.1",
|
|
39
39
|
"cli": "^1.0.1",
|
|
40
40
|
"glob": "^7.2.0",
|
|
41
41
|
"path-to-regexp": "^6.2.1",
|
|
42
|
-
"reflect-metadata": ">=
|
|
43
|
-
"tgrid": "^0.8.
|
|
42
|
+
"reflect-metadata": ">=0.1.12",
|
|
43
|
+
"tgrid": "^0.8.8",
|
|
44
44
|
"tsconfck": "^2.0.1",
|
|
45
45
|
"tsconfig-paths": "^4.1.1",
|
|
46
46
|
"tstl": "^2.5.13",
|
|
47
|
-
"typia": "^5.0.
|
|
47
|
+
"typia": "^5.0.2"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@nestia/fetcher": ">=2.0.
|
|
50
|
+
"@nestia/fetcher": ">=2.0.1",
|
|
51
51
|
"@nestjs/common": ">=7.0.1",
|
|
52
52
|
"@nestjs/core": ">=7.0.1",
|
|
53
53
|
"reflect-metadata": ">=0.1.12",
|
|
54
54
|
"ts-node": ">=10.6.0",
|
|
55
55
|
"typescript": ">=4.8.0",
|
|
56
|
-
"typia": ">=5.0.
|
|
56
|
+
"typia": ">=5.0.2 <6.0.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@nestjs/common": ">= 7.0.1",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"rimraf": "^3.0.2",
|
|
74
74
|
"ts-node": "^10.9.1",
|
|
75
75
|
"ts-patch": "v3.0.2",
|
|
76
|
-
"typescript": "^5.
|
|
76
|
+
"typescript": "^5.2.2",
|
|
77
77
|
"typescript-transform-paths": "^3.4.4",
|
|
78
78
|
"uuid": "^9.0.0"
|
|
79
79
|
},
|
package/src/INestiaConfig.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import type ts from "typescript";
|
|
2
|
-
|
|
3
1
|
import type { ISwagger } from "./structures/ISwagger";
|
|
4
|
-
import { ISwaggerInfo } from "./structures/ISwaggerInfo";
|
|
5
|
-
import { ISwaggerSecurityScheme } from "./structures/ISwaggerSecurityScheme";
|
|
6
|
-
import type { StripEnums } from "./utils/StripEnums";
|
|
2
|
+
import type { ISwaggerInfo } from "./structures/ISwaggerInfo";
|
|
3
|
+
import type { ISwaggerSecurityScheme } from "./structures/ISwaggerSecurityScheme";
|
|
7
4
|
|
|
8
5
|
/**
|
|
9
6
|
* Definition for the `nestia.config.ts` file.
|
|
@@ -44,6 +41,21 @@ export interface INestiaConfig {
|
|
|
44
41
|
*/
|
|
45
42
|
distribute?: string;
|
|
46
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Allow simulation mode.
|
|
46
|
+
*
|
|
47
|
+
* If you configure this property to be `true`, the SDK library would be contain
|
|
48
|
+
* simulation mode. In the simulation mode, the SDK library would not communicate
|
|
49
|
+
* with the real backend server, but just returns random mock-up data
|
|
50
|
+
* with requestion data validation.
|
|
51
|
+
*
|
|
52
|
+
* For reference, random mock-up data would be generated by `typia.random<T>()`
|
|
53
|
+
* function.
|
|
54
|
+
*
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
simulate?: boolean;
|
|
58
|
+
|
|
47
59
|
/**
|
|
48
60
|
* Target directory that e2e test functions would be placed in.
|
|
49
61
|
*
|
|
@@ -56,26 +68,52 @@ export interface INestiaConfig {
|
|
|
56
68
|
e2e?: string;
|
|
57
69
|
|
|
58
70
|
/**
|
|
59
|
-
*
|
|
71
|
+
* Whether to use propagation mode or not.
|
|
72
|
+
*
|
|
73
|
+
* If being configured, interaction functions of the SDK library would
|
|
74
|
+
* perform the propagation mode. The propagation mode means that never
|
|
75
|
+
* throwing exception even when status code is not 200 (or 201), but just
|
|
76
|
+
* returning the {@link IPropagation} typed instance, which can specify its body
|
|
77
|
+
* type through discriminated union determined by status code.
|
|
78
|
+
*
|
|
79
|
+
* @default false
|
|
80
|
+
*/
|
|
81
|
+
propagate?: boolean;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Whether to clone DTO structures or not.
|
|
85
|
+
*
|
|
86
|
+
* If being configured, all of DTOs used in the backend server would be cloned
|
|
87
|
+
* into the `structures` directory, and the SDK library would be refer to the
|
|
88
|
+
* cloned DTOs instead of the original.
|
|
89
|
+
*
|
|
90
|
+
* @default false
|
|
91
|
+
*/
|
|
92
|
+
clone?: boolean;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Whether to wrap DTO by primitive type.
|
|
96
|
+
*
|
|
97
|
+
* If you don't configure this property as `false`, all of DTOs in the
|
|
98
|
+
* SDK library would be automatically wrapped by {@link Primitive} type.
|
|
60
99
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
100
|
+
* For refenrece, if a DTO type be capsuled by the {@link Primitive} type,
|
|
101
|
+
* all of methods in the DTO type would be automatically erased. Also, if
|
|
102
|
+
* the DTO has a `toJSON()` method, the DTO type would be automatically
|
|
103
|
+
* converted to return type of the `toJSON()` method.
|
|
65
104
|
*
|
|
66
|
-
*
|
|
67
|
-
|
|
105
|
+
* @default true
|
|
106
|
+
*/
|
|
107
|
+
primitive?: boolean;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Location of `tsconfig.json` file.
|
|
68
111
|
*
|
|
69
|
-
*
|
|
70
|
-
* const nestiaConfig: IConfiguration;
|
|
112
|
+
* If be configured, target file will replace the `tsconfig.json` file.
|
|
71
113
|
*
|
|
72
|
-
*
|
|
73
|
-
* ...tsconfig.compilerOptions,
|
|
74
|
-
* ...(nestiaConfig.compilerOptions ?? {})
|
|
75
|
-
* }
|
|
76
|
-
* ```
|
|
114
|
+
* @default tsconfig.json
|
|
77
115
|
*/
|
|
78
|
-
|
|
116
|
+
project?: string;
|
|
79
117
|
|
|
80
118
|
/**
|
|
81
119
|
* Whether to assert parameter types or not.
|
|
@@ -105,36 +143,6 @@ export interface INestiaConfig {
|
|
|
105
143
|
* @default false
|
|
106
144
|
*/
|
|
107
145
|
json?: boolean;
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Whether to wrap DTO by primitive type.
|
|
111
|
-
*
|
|
112
|
-
* If you don't configure this property as `false`, all of DTOs in the
|
|
113
|
-
* SDK library would be automatically wrapped by {@link Primitive} type.
|
|
114
|
-
*
|
|
115
|
-
* For refenrece, if a DTO type be capsuled by the {@link Primitive} type,
|
|
116
|
-
* all of methods in the DTO type would be automatically erased. Also, if
|
|
117
|
-
* the DTO has a `toJSON()` method, the DTO type would be automatically
|
|
118
|
-
* converted to return type of the `toJSON()` method.
|
|
119
|
-
*
|
|
120
|
-
* @default true
|
|
121
|
-
*/
|
|
122
|
-
primitive?: boolean;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Allow simulation mode.
|
|
126
|
-
*
|
|
127
|
-
* If you configure this property to be `true`, the SDK library would be contain
|
|
128
|
-
* simulation mode. In the simulation mode, the SDK library would not communicate
|
|
129
|
-
* with the real backend server, but just returns random mock-up data
|
|
130
|
-
* with requestion data validation.
|
|
131
|
-
*
|
|
132
|
-
* For reference, random mock-up data would be generated by `typia.random<T>()`
|
|
133
|
-
* function.
|
|
134
|
-
*
|
|
135
|
-
* @default false
|
|
136
|
-
*/
|
|
137
|
-
simulate?: boolean;
|
|
138
146
|
}
|
|
139
147
|
export namespace INestiaConfig {
|
|
140
148
|
/**
|
|
@@ -196,5 +204,12 @@ export namespace INestiaConfig {
|
|
|
196
204
|
* @default false
|
|
197
205
|
*/
|
|
198
206
|
decompose?: boolean;
|
|
207
|
+
|
|
208
|
+
operationId?(props: {
|
|
209
|
+
class: string;
|
|
210
|
+
function: string;
|
|
211
|
+
method: "HEAD" | "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
212
|
+
path: string;
|
|
213
|
+
}): string;
|
|
199
214
|
}
|
|
200
215
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import * as runner from "ts-node";
|
|
4
3
|
import { Pair, Singleton } from "tstl";
|
|
5
4
|
import ts from "typescript";
|
|
6
5
|
|
|
@@ -8,7 +7,6 @@ import { INestiaConfig } from "./INestiaConfig";
|
|
|
8
7
|
import { AccessorAnalyzer } from "./analyses/AccessorAnalyzer";
|
|
9
8
|
import { ControllerAnalyzer } from "./analyses/ControllerAnalyzer";
|
|
10
9
|
import { ReflectAnalyzer } from "./analyses/ReflectAnalyzer";
|
|
11
|
-
import { NestiaConfigCompilerOptions } from "./executable/internal/NestiaConfigCompilerOptions";
|
|
12
10
|
import { E2eGenerator } from "./generates/E2eGenerator";
|
|
13
11
|
import { SdkGenerator } from "./generates/SdkGenerator";
|
|
14
12
|
import { SwaggerGenerator } from "./generates/SwaggerGenerator";
|
|
@@ -19,13 +17,9 @@ import { NestiaConfigUtil } from "./utils/NestiaConfigUtil";
|
|
|
19
17
|
import { SourceFinder } from "./utils/SourceFinder";
|
|
20
18
|
|
|
21
19
|
export class NestiaSdkApplication {
|
|
22
|
-
private readonly
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
public constructor(private readonly config_: INestiaConfig) {
|
|
27
|
-
this.bundle_checker_ = new Singleton(async () => {
|
|
28
|
-
if (!this.config_.output) return () => false;
|
|
20
|
+
private readonly bundler_: Singleton<Promise<(str: string) => boolean>> =
|
|
21
|
+
new Singleton(async () => {
|
|
22
|
+
if (!this.config) return () => false;
|
|
29
23
|
|
|
30
24
|
const bundles: string[] = await fs.promises.readdir(
|
|
31
25
|
SdkGenerator.BUNDLE_PATH,
|
|
@@ -34,7 +28,7 @@ export class NestiaSdkApplication {
|
|
|
34
28
|
bundles,
|
|
35
29
|
async (file) => {
|
|
36
30
|
const relative: string = path.join(
|
|
37
|
-
this.
|
|
31
|
+
this.config!.output!,
|
|
38
32
|
file,
|
|
39
33
|
);
|
|
40
34
|
const location: string = path.join(
|
|
@@ -55,14 +49,33 @@ export class NestiaSdkApplication {
|
|
|
55
49
|
return false;
|
|
56
50
|
};
|
|
57
51
|
});
|
|
52
|
+
|
|
53
|
+
public constructor(
|
|
54
|
+
private readonly config: INestiaConfig,
|
|
55
|
+
private readonly compilerOptions: ts.CompilerOptions,
|
|
56
|
+
) {}
|
|
57
|
+
|
|
58
|
+
private async is_not_excluded(file: string): Promise<boolean> {
|
|
59
|
+
if (this.config.output)
|
|
60
|
+
return (
|
|
61
|
+
file.indexOf(path.join(this.config.output, "functional")) ===
|
|
62
|
+
-1 && (await this.bundler_.get())(file) === false
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const content: string = await fs.promises.readFile(file, "utf8");
|
|
66
|
+
return (
|
|
67
|
+
content.indexOf(
|
|
68
|
+
" * @nestia Generated by Nestia - https://github.com/samchon/nestia",
|
|
69
|
+
) === -1
|
|
70
|
+
);
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
public async e2e(): Promise<void> {
|
|
61
|
-
if (!this.
|
|
74
|
+
if (!this.config.output)
|
|
62
75
|
throw new Error(
|
|
63
76
|
"Error on NestiaApplication.e2e(): output path of SDK is not specified.",
|
|
64
77
|
);
|
|
65
|
-
else if (!this.
|
|
78
|
+
else if (!this.config.e2e)
|
|
66
79
|
throw new Error(
|
|
67
80
|
"Error on NestiaApplication.e2e(): output path of e2e test files is not specified.",
|
|
68
81
|
);
|
|
@@ -77,27 +90,27 @@ export class NestiaSdkApplication {
|
|
|
77
90
|
`Error on NestiaApplication.e2e(): output directory of ${title} does not exists.`,
|
|
78
91
|
);
|
|
79
92
|
};
|
|
80
|
-
await validate("sdk")(this.
|
|
81
|
-
await validate("e2e")(this.
|
|
93
|
+
await validate("sdk")(this.config.output);
|
|
94
|
+
await validate("e2e")(this.config.e2e);
|
|
82
95
|
|
|
83
96
|
title("Nestia E2E Generator");
|
|
84
97
|
await this.generate(
|
|
85
98
|
"e2e",
|
|
86
99
|
(config) => config,
|
|
87
|
-
() => (config) => async (routes) => {
|
|
88
|
-
await SdkGenerator.generate(config)(routes);
|
|
100
|
+
(checker) => (config) => async (routes) => {
|
|
101
|
+
await SdkGenerator.generate(checker)(config)(routes);
|
|
89
102
|
await E2eGenerator.generate(config)(routes);
|
|
90
103
|
},
|
|
91
104
|
);
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
public async sdk(): Promise<void> {
|
|
95
|
-
if (!this.
|
|
108
|
+
if (!this.config.output)
|
|
96
109
|
throw new Error(
|
|
97
110
|
"Error on NestiaApplication.sdk(): output path is not specified.",
|
|
98
111
|
);
|
|
99
112
|
|
|
100
|
-
const parent: string = path.resolve(this.
|
|
113
|
+
const parent: string = path.resolve(this.config.output + "/..");
|
|
101
114
|
const stats: fs.Stats = await fs.promises.lstat(parent);
|
|
102
115
|
if (stats.isDirectory() === false)
|
|
103
116
|
throw new Error(
|
|
@@ -105,23 +118,19 @@ export class NestiaSdkApplication {
|
|
|
105
118
|
);
|
|
106
119
|
|
|
107
120
|
title("Nestia SDK Generator");
|
|
108
|
-
await this.generate(
|
|
109
|
-
"sdk",
|
|
110
|
-
(config) => config,
|
|
111
|
-
() => SdkGenerator.generate,
|
|
112
|
-
);
|
|
121
|
+
await this.generate("sdk", (config) => config, SdkGenerator.generate);
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
public async swagger(): Promise<void> {
|
|
116
|
-
if (!this.
|
|
125
|
+
if (!this.config.swagger?.output)
|
|
117
126
|
throw new Error(
|
|
118
127
|
`Error on NestiaApplication.swagger(): output path of the "swagger.json" is not specified.`,
|
|
119
128
|
);
|
|
120
129
|
|
|
121
|
-
const parsed: path.ParsedPath = path.parse(this.
|
|
130
|
+
const parsed: path.ParsedPath = path.parse(this.config.swagger.output);
|
|
122
131
|
const directory: string = !!parsed.ext
|
|
123
132
|
? path.resolve(parsed.dir)
|
|
124
|
-
: this.
|
|
133
|
+
: this.config.swagger.output;
|
|
125
134
|
const stats: fs.Stats = await fs.promises.lstat(directory);
|
|
126
135
|
if (stats.isDirectory() === false)
|
|
127
136
|
throw new Error(
|
|
@@ -143,12 +152,9 @@ export class NestiaSdkApplication {
|
|
|
143
152
|
checker: ts.TypeChecker,
|
|
144
153
|
) => (config: Config) => (routes: IRoute[]) => Promise<void>,
|
|
145
154
|
): Promise<void> {
|
|
146
|
-
// MOUNT TS-NODE
|
|
147
|
-
this.prepare(method);
|
|
148
|
-
|
|
149
155
|
// LOAD CONTROLLER FILES
|
|
150
156
|
const input: INestiaConfig.IInput = NestiaConfigUtil.input(
|
|
151
|
-
this.
|
|
157
|
+
this.config.input,
|
|
152
158
|
);
|
|
153
159
|
const fileList: string[] = await ArrayUtil.asyncFilter(
|
|
154
160
|
await SourceFinder.find({
|
|
@@ -197,7 +203,7 @@ export class NestiaSdkApplication {
|
|
|
197
203
|
console.log("Analyzing source codes");
|
|
198
204
|
const program: ts.Program = ts.createProgram(
|
|
199
205
|
controllers.map((c) => c.file),
|
|
200
|
-
this.
|
|
206
|
+
this.compilerOptions,
|
|
201
207
|
);
|
|
202
208
|
const checker: ts.TypeChecker = program.getTypeChecker();
|
|
203
209
|
|
|
@@ -224,59 +230,7 @@ export class NestiaSdkApplication {
|
|
|
224
230
|
|
|
225
231
|
// DO GENERATE
|
|
226
232
|
AccessorAnalyzer.analyze(routeList);
|
|
227
|
-
await archiver(checker)(config(this.
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
private prepare(method: string): void {
|
|
231
|
-
// CONSTRUCT OPTIONS
|
|
232
|
-
if (!this.config_.compilerOptions)
|
|
233
|
-
this.config_.compilerOptions =
|
|
234
|
-
NestiaConfigCompilerOptions.DEFAULT_OPTIONS as any;
|
|
235
|
-
const absoluted: boolean = !!this.config_.compilerOptions?.baseUrl;
|
|
236
|
-
|
|
237
|
-
// CHECK STRICT OPTION
|
|
238
|
-
const strict: boolean =
|
|
239
|
-
this.config_.compilerOptions?.strictNullChecks !== undefined
|
|
240
|
-
? !!this.config_.compilerOptions.strictNullChecks
|
|
241
|
-
: !!this.config_.compilerOptions?.strict;
|
|
242
|
-
if (strict === false)
|
|
243
|
-
throw new Error(
|
|
244
|
-
`Error on NestiaSdkApplication.${method}(): nestia requires \`compilerOptions.strictNullChecks\` to be true.`,
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
const ttsc: boolean =
|
|
248
|
-
ts.version < "5.0.0" &&
|
|
249
|
-
(() => {
|
|
250
|
-
try {
|
|
251
|
-
require.resolve("ttypescript");
|
|
252
|
-
return true;
|
|
253
|
-
} catch (e) {
|
|
254
|
-
return false;
|
|
255
|
-
}
|
|
256
|
-
})();
|
|
257
|
-
|
|
258
|
-
// MOUNT TS-NODE
|
|
259
|
-
runner.register({
|
|
260
|
-
emit: false,
|
|
261
|
-
compiler: ttsc ? "ttypescript" : undefined,
|
|
262
|
-
compilerOptions: this.config_.compilerOptions,
|
|
263
|
-
require: absoluted ? ["tsconfig-paths/register"] : undefined,
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
private async is_not_excluded(file: string): Promise<boolean> {
|
|
268
|
-
if (this.config_.output)
|
|
269
|
-
return (
|
|
270
|
-
file.indexOf(path.join(this.config_.output, "functional")) ===
|
|
271
|
-
-1 && (await this.bundle_checker_.get())(file) === false
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
const content: string = await fs.promises.readFile(file, "utf8");
|
|
275
|
-
return (
|
|
276
|
-
content.indexOf(
|
|
277
|
-
" * @nestia Generated by Nestia - https://github.com/samchon/nestia",
|
|
278
|
-
) === -1
|
|
279
|
-
);
|
|
233
|
+
await archiver(checker)(config(this.config))(routeList);
|
|
280
234
|
}
|
|
281
235
|
}
|
|
282
236
|
|
|
@@ -301,4 +255,5 @@ const is_implicit_return_typed = (route: IRoute): boolean => {
|
|
|
301
255
|
else if (VARIABLE.test(name[i])) return false;
|
|
302
256
|
return true;
|
|
303
257
|
};
|
|
258
|
+
|
|
304
259
|
const VARIABLE = /[a-zA-Z_$0-9]/;
|
|
@@ -145,11 +145,11 @@ export namespace ControllerAnalyzer {
|
|
|
145
145
|
.map((pair) => [pair.first, pair.second.toJSON()]);
|
|
146
146
|
|
|
147
147
|
// PARSE COMMENT TAGS
|
|
148
|
-
const
|
|
148
|
+
const jsDocTags = signature.getJsDocTags();
|
|
149
149
|
const security: Record<string, string[]>[] = SecurityAnalyzer.merge(
|
|
150
150
|
...controller.security,
|
|
151
151
|
...func.security,
|
|
152
|
-
...
|
|
152
|
+
...jsDocTags
|
|
153
153
|
.filter((tag) => tag.name === "security")
|
|
154
154
|
.map((tag) =>
|
|
155
155
|
(tag.text ?? []).map((text) => {
|
|
@@ -177,8 +177,10 @@ export namespace ControllerAnalyzer {
|
|
|
177
177
|
},
|
|
178
178
|
imports,
|
|
179
179
|
status: func.status,
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
symbol: {
|
|
181
|
+
class: controller.name,
|
|
182
|
+
function: func.name,
|
|
183
|
+
},
|
|
182
184
|
location: (() => {
|
|
183
185
|
const file = declaration.getSourceFile();
|
|
184
186
|
const { line, character } = file.getLineAndCharacterOfPosition(
|
|
@@ -189,12 +191,12 @@ export namespace ControllerAnalyzer {
|
|
|
189
191
|
}:${character + 1}`;
|
|
190
192
|
})(),
|
|
191
193
|
description: CommentFactory.description(symbol),
|
|
192
|
-
operationId:
|
|
193
|
-
.find(({ name }) => name === "
|
|
194
|
+
operationId: jsDocTags
|
|
195
|
+
.find(({ name }) => name === "operationId")
|
|
194
196
|
?.text!?.[0].text.split(" ")[0]
|
|
195
197
|
.trim(),
|
|
196
|
-
|
|
197
|
-
setHeaders:
|
|
198
|
+
jsDocTags: jsDocTags,
|
|
199
|
+
setHeaders: jsDocTags
|
|
198
200
|
.filter(
|
|
199
201
|
(t) =>
|
|
200
202
|
t.text?.length &&
|
|
@@ -90,6 +90,8 @@ export namespace ReflectAnalyzer {
|
|
|
90
90
|
paths,
|
|
91
91
|
functions: [],
|
|
92
92
|
security: _Get_securities(creator),
|
|
93
|
+
swaggerTgas:
|
|
94
|
+
Reflect.getMetadata("swagger/apiUseTags", creator) ?? [],
|
|
93
95
|
};
|
|
94
96
|
|
|
95
97
|
// PARSE CHILDREN DATA
|
|
@@ -228,6 +230,12 @@ export namespace ReflectAnalyzer {
|
|
|
228
230
|
)?.value ?? "application/json",
|
|
229
231
|
security: _Get_securities(proto),
|
|
230
232
|
exceptions: _Get_exceptions(proto),
|
|
233
|
+
swaggerTags: [
|
|
234
|
+
...new Set([
|
|
235
|
+
...controller.swaggerTgas,
|
|
236
|
+
...(Reflect.getMetadata("swagger/apiUseTags", proto) ?? []),
|
|
237
|
+
]),
|
|
238
|
+
],
|
|
231
239
|
};
|
|
232
240
|
|
|
233
241
|
// VALIDATE PATH ARGUMENTS
|