@nestia/sdk 3.0.5-dev.20240418 → 3.1.0-dev.20240426
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/NestiaSdkApplication.d.ts +1 -0
- package/lib/NestiaSdkApplication.js +17 -17
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/AccessorAnalyzer.d.ts +3 -2
- package/lib/analyses/AccessorAnalyzer.js.map +1 -1
- package/lib/analyses/ExceptionAnalyzer.d.ts +11 -3
- package/lib/analyses/ExceptionAnalyzer.js +23 -18
- package/lib/analyses/ExceptionAnalyzer.js.map +1 -1
- package/lib/analyses/GenericAnalyzer.d.ts +1 -0
- package/lib/analyses/ImportAnalyzer.d.ts +6 -1
- package/lib/analyses/ImportAnalyzer.js +27 -29
- package/lib/analyses/ImportAnalyzer.js.map +1 -1
- package/lib/analyses/PathAnalyzer.d.ts +0 -5
- package/lib/analyses/PathAnalyzer.js +0 -32
- package/lib/analyses/PathAnalyzer.js.map +1 -1
- package/lib/analyses/{ReflectAnalyzer.d.ts → ReflectControllerAnalyzer.d.ts} +3 -4
- package/lib/analyses/ReflectControllerAnalyzer.js +145 -0
- package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -0
- package/lib/analyses/ReflectHttpOperationAnalyzer.d.ts +10 -0
- package/lib/analyses/ReflectHttpOperationAnalyzer.js +224 -0
- package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -0
- package/lib/analyses/ReflectMetadataAnalyzer.d.ts +8 -0
- package/lib/analyses/ReflectMetadataAnalyzer.js +34 -0
- package/lib/analyses/ReflectMetadataAnalyzer.js.map +1 -0
- package/lib/analyses/ReflectWebSocketOperationAnalyzer.d.ts +10 -0
- package/lib/analyses/ReflectWebSocketOperationAnalyzer.js +78 -0
- package/lib/analyses/ReflectWebSocketOperationAnalyzer.js.map +1 -0
- package/lib/analyses/SecurityAnalyzer.js +1 -1
- package/lib/analyses/SecurityAnalyzer.js.map +1 -1
- package/lib/analyses/TypedControllerAnalyzer.d.ts +9 -0
- package/lib/analyses/TypedControllerAnalyzer.js +77 -0
- package/lib/analyses/TypedControllerAnalyzer.js.map +1 -0
- package/lib/analyses/TypedHttpOperationAnalyzer.d.ts +16 -0
- package/lib/analyses/TypedHttpOperationAnalyzer.js +251 -0
- package/lib/analyses/TypedHttpOperationAnalyzer.js.map +1 -0
- package/lib/analyses/TypedWebSocketOperationAnalyzer.d.ts +16 -0
- package/lib/analyses/TypedWebSocketOperationAnalyzer.js +218 -0
- package/lib/analyses/TypedWebSocketOperationAnalyzer.js.map +1 -0
- package/lib/executable/internal/NestiaConfigLoader.d.ts +1 -0
- package/lib/generates/CloneGenerator.d.ts +3 -4
- package/lib/generates/CloneGenerator.js +8 -8
- package/lib/generates/CloneGenerator.js.map +1 -1
- package/lib/generates/E2eGenerator.d.ts +3 -4
- package/lib/generates/E2eGenerator.js +7 -7
- package/lib/generates/E2eGenerator.js.map +1 -1
- package/lib/generates/SdkGenerator.d.ts +4 -4
- package/lib/generates/SdkGenerator.js +8 -8
- package/lib/generates/SdkGenerator.js.map +1 -1
- package/lib/generates/SwaggerGenerator.d.ts +5 -2
- package/lib/generates/SwaggerGenerator.js +15 -13
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.d.ts +4 -5
- package/lib/generates/internal/E2eFileProgrammer.js +13 -12
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/FilePrinter.d.ts +1 -0
- package/lib/generates/internal/ImportDictionary.d.ts +1 -0
- package/lib/generates/internal/SdkAliasCollection.d.ts +9 -8
- package/lib/generates/internal/SdkAliasCollection.js +20 -20
- package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
- package/lib/generates/internal/SdkDistributionComposer.d.ts +1 -1
- package/lib/generates/internal/SdkDistributionComposer.js +36 -2
- package/lib/generates/internal/SdkDistributionComposer.js.map +1 -1
- package/lib/generates/internal/SdkFileProgrammer.d.ts +4 -4
- package/lib/generates/internal/SdkFileProgrammer.js +10 -7
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +13 -0
- package/lib/generates/internal/{SdkCloneProgrammer.js → SdkHttpCloneProgrammer.js} +14 -14
- package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkHttpFunctionProgrammer.d.ts +12 -0
- package/lib/generates/internal/{SdkFunctionProgrammer.js → SdkHttpFunctionProgrammer.js} +12 -12
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.d.ts +12 -0
- package/lib/generates/internal/{SdkNamespaceProgrammer.js → SdkHttpNamespaceProgrammer.js} +26 -26
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkHttpRouteProgrammer.d.ts +8 -0
- package/lib/generates/internal/{SdkRouteProgrammer.js → SdkHttpRouteProgrammer.js} +11 -11
- package/lib/generates/internal/SdkHttpRouteProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkHttpSimulationProgrammer.d.ts +13 -0
- package/lib/generates/internal/{SdkSimulationProgrammer.js → SdkHttpSimulationProgrammer.js} +18 -18
- package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkRouteDirectory.d.ts +3 -2
- package/lib/generates/internal/SdkRouteDirectory.js.map +1 -1
- package/lib/generates/internal/SdkTypeProgrammer.d.ts +4 -3
- package/lib/generates/internal/SdkTypeProgrammer.js +33 -33
- package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.d.ts +8 -0
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +115 -0
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.d.ts +8 -0
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +79 -0
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -0
- package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +6 -5
- package/lib/generates/internal/SwaggerSchemaGenerator.js +3 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
- package/lib/structures/INestiaProject.d.ts +1 -0
- package/lib/structures/IReflectController.d.ts +15 -0
- package/lib/structures/{IRoute.js → IReflectController.js} +1 -1
- package/lib/structures/IReflectController.js.map +1 -0
- package/lib/structures/{IController.d.ts → IReflectHttpOperation.d.ts} +15 -25
- package/lib/structures/IReflectHttpOperation.js +3 -0
- package/lib/structures/IReflectHttpOperation.js.map +1 -0
- package/lib/structures/IReflectWebSocketOperation.d.ts +16 -0
- package/lib/structures/IReflectWebSocketOperation.js +3 -0
- package/lib/structures/IReflectWebSocketOperation.js.map +1 -0
- package/lib/structures/ISwaggerError.d.ts +2 -2
- package/lib/structures/ITypeTuple.d.ts +1 -0
- package/lib/structures/{IRoute.d.ts → ITypedHttpRoute.d.ts} +12 -12
- package/lib/structures/{IController.js → ITypedHttpRoute.js} +1 -1
- package/lib/structures/ITypedHttpRoute.js.map +1 -0
- package/lib/structures/ITypedWebSocketRoute.d.ts +54 -0
- package/lib/structures/ITypedWebSocketRoute.js +3 -0
- package/lib/structures/ITypedWebSocketRoute.js.map +1 -0
- package/lib/structures/TypeEntry.d.ts +1 -0
- package/lib/utils/VersioningStrategy.d.ts +6 -0
- package/lib/utils/VersioningStrategy.js +22 -0
- package/lib/utils/VersioningStrategy.js.map +1 -0
- package/package.json +9 -7
- package/src/NestiaSdkApplication.ts +36 -34
- package/src/analyses/AccessorAnalyzer.ts +12 -5
- package/src/analyses/ExceptionAnalyzer.ts +49 -39
- package/src/analyses/ImportAnalyzer.ts +123 -104
- package/src/analyses/PathAnalyzer.ts +0 -41
- package/src/analyses/ReflectControllerAnalyzer.ts +155 -0
- package/src/analyses/ReflectHttpOperationAnalyzer.ts +290 -0
- package/src/analyses/ReflectMetadataAnalyzer.ts +53 -0
- package/src/analyses/ReflectWebSocketOperationAnalyzer.ts +96 -0
- package/src/analyses/SecurityAnalyzer.ts +2 -1
- package/src/analyses/TypedControllerAnalyzer.ts +92 -0
- package/src/analyses/TypedHttpOperationAnalyzer.ts +352 -0
- package/src/analyses/TypedWebSocketOperationAnalyzer.ts +368 -0
- package/src/generates/CloneGenerator.ts +17 -15
- package/src/generates/E2eGenerator.ts +10 -12
- package/src/generates/SdkGenerator.ts +19 -12
- package/src/generates/SwaggerGenerator.ts +31 -21
- package/src/generates/internal/E2eFileProgrammer.ts +20 -24
- package/src/generates/internal/SdkAliasCollection.ts +38 -33
- package/src/generates/internal/SdkDistributionComposer.ts +13 -4
- package/src/generates/internal/SdkFileProgrammer.ts +17 -13
- package/src/generates/internal/{SdkCloneProgrammer.ts → SdkHttpCloneProgrammer.ts} +14 -15
- package/src/generates/internal/{SdkFunctionProgrammer.ts → SdkHttpFunctionProgrammer.ts} +24 -23
- package/src/generates/internal/{SdkNamespaceProgrammer.ts → SdkHttpNamespaceProgrammer.ts} +44 -49
- package/src/generates/internal/{SdkRouteProgrammer.ts → SdkHttpRouteProgrammer.ts} +12 -13
- package/src/generates/internal/{SdkSimulationProgrammer.ts → SdkHttpSimulationProgrammer.ts} +23 -25
- package/src/generates/internal/SdkRouteDirectory.ts +3 -2
- package/src/generates/internal/SdkTypeProgrammer.ts +43 -37
- package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +378 -0
- package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +248 -0
- package/src/generates/internal/SwaggerSchemaGenerator.ts +26 -21
- package/src/structures/IReflectController.ts +17 -0
- package/src/structures/{IController.ts → IReflectHttpOperation.ts} +78 -94
- package/src/structures/IReflectWebSocketOperation.ts +17 -0
- package/src/structures/ISwaggerError.ts +2 -2
- package/src/structures/{IRoute.ts → ITypedHttpRoute.ts} +14 -12
- package/src/structures/ITypedWebSocketRoute.ts +67 -0
- package/src/utils/VersioningStrategy.ts +28 -0
- package/lib/analyses/ControllerAnalyzer.d.ts +0 -7
- package/lib/analyses/ControllerAnalyzer.js +0 -269
- package/lib/analyses/ControllerAnalyzer.js.map +0 -1
- package/lib/analyses/ReflectAnalyzer.js +0 -377
- package/lib/analyses/ReflectAnalyzer.js.map +0 -1
- package/lib/generates/internal/SdkCloneProgrammer.d.ts +0 -12
- package/lib/generates/internal/SdkCloneProgrammer.js.map +0 -1
- package/lib/generates/internal/SdkFunctionProgrammer.d.ts +0 -11
- package/lib/generates/internal/SdkFunctionProgrammer.js.map +0 -1
- package/lib/generates/internal/SdkNamespaceProgrammer.d.ts +0 -11
- package/lib/generates/internal/SdkNamespaceProgrammer.js.map +0 -1
- package/lib/generates/internal/SdkRouteProgrammer.d.ts +0 -7
- package/lib/generates/internal/SdkRouteProgrammer.js.map +0 -1
- package/lib/generates/internal/SdkSimulationProgrammer.d.ts +0 -12
- package/lib/generates/internal/SdkSimulationProgrammer.js.map +0 -1
- package/lib/structures/IController.js.map +0 -1
- package/lib/structures/IRoute.js.map +0 -1
- package/src/analyses/ControllerAnalyzer.ts +0 -402
- package/src/analyses/ReflectAnalyzer.ts +0 -471
|
@@ -5,15 +5,16 @@ import ts from "typescript";
|
|
|
5
5
|
import { INestiaConfig } from "./INestiaConfig";
|
|
6
6
|
import { AccessorAnalyzer } from "./analyses/AccessorAnalyzer";
|
|
7
7
|
import { ConfigAnalyzer } from "./analyses/ConfigAnalyzer";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { ReflectControllerAnalyzer } from "./analyses/ReflectControllerAnalyzer";
|
|
9
|
+
import { TypedControllerAnalyzer } from "./analyses/TypedControllerAnalyzer";
|
|
10
10
|
import { E2eGenerator } from "./generates/E2eGenerator";
|
|
11
11
|
import { SdkGenerator } from "./generates/SdkGenerator";
|
|
12
12
|
import { SwaggerGenerator } from "./generates/SwaggerGenerator";
|
|
13
|
-
import { IController } from "./structures/IController";
|
|
14
13
|
import { IErrorReport } from "./structures/IErrorReport";
|
|
15
14
|
import { INestiaProject } from "./structures/INestiaProject";
|
|
16
|
-
import {
|
|
15
|
+
import { IReflectController } from "./structures/IReflectController";
|
|
16
|
+
import { ITypedHttpRoute } from "./structures/ITypedHttpRoute";
|
|
17
|
+
import { ITypedWebSocketRoute } from "./structures/ITypedWebSocketRoute";
|
|
17
18
|
import { MapUtil } from "./utils/MapUtil";
|
|
18
19
|
|
|
19
20
|
export class NestiaSdkApplication {
|
|
@@ -46,14 +47,12 @@ export class NestiaSdkApplication {
|
|
|
46
47
|
await validate("e2e")(this.config.e2e);
|
|
47
48
|
|
|
48
49
|
print_title("Nestia E2E Generator");
|
|
49
|
-
await this.generate(
|
|
50
|
-
|
|
51
|
-
(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
},
|
|
56
|
-
);
|
|
50
|
+
await this.generate("e2e", (project) => async (routes) => {
|
|
51
|
+
await SdkGenerator.generate(project)(routes);
|
|
52
|
+
await E2eGenerator.generate(project)(
|
|
53
|
+
routes.filter((r) => r.protocol === "http") as ITypedHttpRoute[],
|
|
54
|
+
);
|
|
55
|
+
});
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
public async sdk(): Promise<void> {
|
|
@@ -70,7 +69,7 @@ export class NestiaSdkApplication {
|
|
|
70
69
|
);
|
|
71
70
|
|
|
72
71
|
print_title("Nestia SDK Generator");
|
|
73
|
-
await this.generate("sdk",
|
|
72
|
+
await this.generate("sdk", SdkGenerator.generate);
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
public async swagger(): Promise<void> {
|
|
@@ -90,25 +89,22 @@ export class NestiaSdkApplication {
|
|
|
90
89
|
);
|
|
91
90
|
|
|
92
91
|
print_title("Nestia Swagger Generator");
|
|
93
|
-
await this.generate(
|
|
94
|
-
"swagger",
|
|
95
|
-
(config) => config.swagger!,
|
|
96
|
-
SwaggerGenerator.generate,
|
|
97
|
-
);
|
|
92
|
+
await this.generate("swagger", SwaggerGenerator.generate);
|
|
98
93
|
}
|
|
99
94
|
|
|
100
|
-
private async generate
|
|
95
|
+
private async generate(
|
|
101
96
|
method: string,
|
|
102
|
-
config: (entire: INestiaConfig) => Config,
|
|
103
97
|
archiver: (
|
|
104
|
-
|
|
105
|
-
) => (
|
|
98
|
+
project: INestiaProject,
|
|
99
|
+
) => (
|
|
100
|
+
routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
|
|
101
|
+
) => Promise<void>,
|
|
106
102
|
): Promise<void> {
|
|
107
103
|
//----
|
|
108
104
|
// ANALYZE REFLECTS
|
|
109
105
|
//----
|
|
110
106
|
const unique: WeakSet<any> = new WeakSet();
|
|
111
|
-
const controllers:
|
|
107
|
+
const controllers: IReflectController[] = [];
|
|
112
108
|
const project: INestiaProject = {
|
|
113
109
|
config: this.config,
|
|
114
110
|
input: await ConfigAnalyzer.input(this.config),
|
|
@@ -120,7 +116,7 @@ export class NestiaSdkApplication {
|
|
|
120
116
|
console.log("Analyzing reflections");
|
|
121
117
|
for (const include of (await ConfigAnalyzer.input(this.config)).include)
|
|
122
118
|
controllers.push(
|
|
123
|
-
...(await
|
|
119
|
+
...(await ReflectControllerAnalyzer.analyze(project)(
|
|
124
120
|
unique,
|
|
125
121
|
include.file,
|
|
126
122
|
include.paths,
|
|
@@ -132,9 +128,11 @@ export class NestiaSdkApplication {
|
|
|
132
128
|
const set: Set<string> = new Set();
|
|
133
129
|
for (const c of controllers)
|
|
134
130
|
for (const cPath of c.paths)
|
|
135
|
-
for (const
|
|
136
|
-
for (const fPath of
|
|
137
|
-
set.add(
|
|
131
|
+
for (const op of c.operations)
|
|
132
|
+
for (const fPath of op.paths)
|
|
133
|
+
set.add(
|
|
134
|
+
`${op.protocol === "http" ? `${op.method}::` : ""}${cPath}/${fPath}`,
|
|
135
|
+
);
|
|
138
136
|
return set.size;
|
|
139
137
|
})();
|
|
140
138
|
|
|
@@ -145,7 +143,7 @@ export class NestiaSdkApplication {
|
|
|
145
143
|
.map(
|
|
146
144
|
(c) =>
|
|
147
145
|
c.paths.length *
|
|
148
|
-
c.
|
|
146
|
+
c.operations.map((f) => f.paths.length).reduce((a, b) => a + b, 0),
|
|
149
147
|
)
|
|
150
148
|
.reduce((a, b) => a + b, 0)}`,
|
|
151
149
|
);
|
|
@@ -161,11 +159,13 @@ export class NestiaSdkApplication {
|
|
|
161
159
|
);
|
|
162
160
|
project.checker = program.getTypeChecker();
|
|
163
161
|
|
|
164
|
-
const routeList:
|
|
162
|
+
const routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute> = [];
|
|
165
163
|
for (const c of controllers) {
|
|
166
164
|
const file: ts.SourceFile | undefined = program.getSourceFile(c.file);
|
|
167
165
|
if (file === undefined) continue;
|
|
168
|
-
routeList.push(
|
|
166
|
+
routeList.push(
|
|
167
|
+
...(await TypedControllerAnalyzer.analyze(project)(file, c)),
|
|
168
|
+
);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// REPORT ERRORS
|
|
@@ -177,7 +177,9 @@ export class NestiaSdkApplication {
|
|
|
177
177
|
|
|
178
178
|
// FIND IMPLICIT TYPES
|
|
179
179
|
if (this.config.clone !== true) {
|
|
180
|
-
const implicit:
|
|
180
|
+
const implicit: ITypedHttpRoute[] = routeList.filter(
|
|
181
|
+
(r) => r.protocol === "http" && is_implicit_return_typed(r),
|
|
182
|
+
) as ITypedHttpRoute[];
|
|
181
183
|
if (implicit.length > 0)
|
|
182
184
|
throw new Error(
|
|
183
185
|
`NestiaApplication.${method}(): implicit return type is not allowed.\n` +
|
|
@@ -186,7 +188,7 @@ export class NestiaSdkApplication {
|
|
|
186
188
|
implicit
|
|
187
189
|
.map(
|
|
188
190
|
(it) =>
|
|
189
|
-
` - ${it.
|
|
191
|
+
` - ${it.controller.name}.${it.name} at "${it.location}"`,
|
|
190
192
|
)
|
|
191
193
|
.join("\n"),
|
|
192
194
|
);
|
|
@@ -194,7 +196,7 @@ export class NestiaSdkApplication {
|
|
|
194
196
|
|
|
195
197
|
// DO GENERATE
|
|
196
198
|
AccessorAnalyzer.analyze(routeList);
|
|
197
|
-
await archiver(project
|
|
199
|
+
await archiver(project)(routeList);
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
202
|
|
|
@@ -204,7 +206,7 @@ const print_title = (str: string): void => {
|
|
|
204
206
|
console.log("-----------------------------------------------------------");
|
|
205
207
|
};
|
|
206
208
|
|
|
207
|
-
const is_implicit_return_typed = (route:
|
|
209
|
+
const is_implicit_return_typed = (route: ITypedHttpRoute): boolean => {
|
|
208
210
|
const name: string = route.output.typeName;
|
|
209
211
|
if (name === "void") return false;
|
|
210
212
|
else if (name.indexOf("readonly [") !== -1) return true;
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { Escaper } from "typia/lib/utils/Escaper";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
|
|
4
|
+
import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
|
|
4
5
|
|
|
5
6
|
export namespace AccessorAnalyzer {
|
|
6
|
-
export const analyze = (
|
|
7
|
+
export const analyze = (
|
|
8
|
+
routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
|
|
9
|
+
) => {
|
|
7
10
|
shrink(routes);
|
|
8
11
|
variable(routes);
|
|
9
12
|
shrink(routes);
|
|
10
13
|
for (const r of routes) r.name = r.accessors.at(-1) ?? r.name;
|
|
11
14
|
};
|
|
12
15
|
|
|
13
|
-
const prepare = (
|
|
16
|
+
const prepare = (
|
|
17
|
+
routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
|
|
18
|
+
): Map<string, number> => {
|
|
14
19
|
const dict: Map<string, number> = new Map();
|
|
15
20
|
for (const route of routeList)
|
|
16
21
|
route.accessors.forEach((_a, i) => {
|
|
@@ -20,7 +25,9 @@ export namespace AccessorAnalyzer {
|
|
|
20
25
|
return dict;
|
|
21
26
|
};
|
|
22
27
|
|
|
23
|
-
const variable = (
|
|
28
|
+
const variable = (
|
|
29
|
+
routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
|
|
30
|
+
) => {
|
|
24
31
|
const dict: Map<string, number> = prepare(routeList);
|
|
25
32
|
for (const route of routeList) {
|
|
26
33
|
const emended: string[] = route.accessors.slice();
|
|
@@ -42,7 +49,7 @@ export namespace AccessorAnalyzer {
|
|
|
42
49
|
}
|
|
43
50
|
};
|
|
44
51
|
|
|
45
|
-
const shrink = (routeList:
|
|
52
|
+
const shrink = (routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute>) => {
|
|
46
53
|
const dict: Map<string, number> = prepare(routeList);
|
|
47
54
|
for (const route of routeList) {
|
|
48
55
|
if (
|
|
@@ -4,53 +4,62 @@ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
|
|
|
4
4
|
import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
|
|
5
5
|
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
6
6
|
|
|
7
|
-
import { IController } from "../structures/IController";
|
|
8
7
|
import { INestiaProject } from "../structures/INestiaProject";
|
|
9
|
-
import {
|
|
8
|
+
import { IReflectController } from "../structures/IReflectController";
|
|
9
|
+
import { IReflectHttpOperation } from "../structures/IReflectHttpOperation";
|
|
10
10
|
import { ITypeTuple } from "../structures/ITypeTuple";
|
|
11
|
+
import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
|
|
11
12
|
import { GenericAnalyzer } from "./GenericAnalyzer";
|
|
12
13
|
import { ImportAnalyzer } from "./ImportAnalyzer";
|
|
13
14
|
|
|
14
15
|
export namespace ExceptionAnalyzer {
|
|
15
16
|
export const analyze =
|
|
16
17
|
(project: INestiaProject) =>
|
|
17
|
-
(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
(props: {
|
|
19
|
+
generics: GenericAnalyzer.Dictionary;
|
|
20
|
+
imports: ImportAnalyzer.Dictionary;
|
|
21
|
+
controller: IReflectController;
|
|
22
|
+
operation: IReflectHttpOperation;
|
|
23
|
+
declaration: ts.MethodDeclaration;
|
|
24
|
+
}): Record<
|
|
25
|
+
number | "2XX" | "3XX" | "4XX" | "5XX",
|
|
26
|
+
ITypedHttpRoute.IOutput
|
|
27
|
+
> => {
|
|
25
28
|
const output: Record<
|
|
26
29
|
number | "2XX" | "3XX" | "4XX" | "5XX",
|
|
27
|
-
|
|
30
|
+
ITypedHttpRoute.IOutput
|
|
28
31
|
> = {} as any;
|
|
29
|
-
for (const decorator of declaration.modifiers ?? [])
|
|
32
|
+
for (const decorator of props.declaration.modifiers ?? [])
|
|
30
33
|
if (ts.isDecorator(decorator))
|
|
31
|
-
analyzeTyped(project)(
|
|
34
|
+
analyzeTyped(project)({
|
|
35
|
+
...props,
|
|
32
36
|
output,
|
|
33
|
-
|
|
37
|
+
decorator,
|
|
38
|
+
});
|
|
34
39
|
return output;
|
|
35
40
|
};
|
|
36
41
|
|
|
37
42
|
const analyzeTyped =
|
|
38
43
|
(project: INestiaProject) =>
|
|
39
|
-
(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
(props: {
|
|
45
|
+
generics: GenericAnalyzer.Dictionary;
|
|
46
|
+
imports: ImportAnalyzer.Dictionary;
|
|
47
|
+
controller: IReflectController;
|
|
48
|
+
operation: IReflectHttpOperation;
|
|
49
|
+
output: Record<
|
|
50
|
+
number | "2XX" | "3XX" | "4XX" | "5XX",
|
|
51
|
+
ITypedHttpRoute.IOutput
|
|
52
|
+
>;
|
|
53
|
+
decorator: ts.Decorator;
|
|
54
|
+
}): boolean => {
|
|
46
55
|
// CHECK DECORATOR
|
|
47
|
-
if (!ts.isCallExpression(decorator.expression)) return false;
|
|
48
|
-
else if ((decorator.expression.typeArguments ?? []).length !== 1)
|
|
56
|
+
if (!ts.isCallExpression(props.decorator.expression)) return false;
|
|
57
|
+
else if ((props.decorator.expression.typeArguments ?? []).length !== 1)
|
|
49
58
|
return false;
|
|
50
59
|
|
|
51
60
|
// CHECK SIGNATURE
|
|
52
61
|
const signature: ts.Signature | undefined =
|
|
53
|
-
project.checker.getResolvedSignature(decorator.expression);
|
|
62
|
+
project.checker.getResolvedSignature(props.decorator.expression);
|
|
54
63
|
if (!signature || !signature.declaration) return false;
|
|
55
64
|
else if (
|
|
56
65
|
path
|
|
@@ -61,48 +70,49 @@ export namespace ExceptionAnalyzer {
|
|
|
61
70
|
|
|
62
71
|
// GET TYPE INFO
|
|
63
72
|
const status: string | null = getStatus(project.checker)(
|
|
64
|
-
decorator.expression.arguments[0] ?? null,
|
|
73
|
+
props.decorator.expression.arguments[0] ?? null,
|
|
65
74
|
);
|
|
66
75
|
if (status === null) return false;
|
|
67
76
|
|
|
68
|
-
const node: ts.TypeNode = decorator.expression.typeArguments![0];
|
|
77
|
+
const node: ts.TypeNode = props.decorator.expression.typeArguments![0];
|
|
69
78
|
const type: ts.Type = project.checker.getTypeFromTypeNode(node);
|
|
70
79
|
if (type.isTypeParameter()) {
|
|
71
80
|
project.errors.push({
|
|
72
|
-
file: controller.file,
|
|
73
|
-
controller: controller.name,
|
|
74
|
-
function:
|
|
81
|
+
file: props.controller.file,
|
|
82
|
+
controller: props.controller.name,
|
|
83
|
+
function: props.operation.name,
|
|
75
84
|
message: "TypedException() without generic argument specification.",
|
|
76
85
|
});
|
|
77
86
|
return false;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
const tuple: ITypeTuple | null = ImportAnalyzer.analyze(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
importDict,
|
|
89
|
+
const tuple: ITypeTuple | null = ImportAnalyzer.analyze(project.checker)({
|
|
90
|
+
generics: props.generics,
|
|
91
|
+
imports: props.imports,
|
|
84
92
|
type,
|
|
85
|
-
);
|
|
93
|
+
});
|
|
86
94
|
if (
|
|
87
95
|
tuple === null ||
|
|
88
96
|
(project.config.clone !== true &&
|
|
89
97
|
(tuple.typeName === "__type" || tuple.typeName === "__object"))
|
|
90
98
|
) {
|
|
91
99
|
project.errors.push({
|
|
92
|
-
file: controller.file,
|
|
93
|
-
controller: controller.name,
|
|
94
|
-
function:
|
|
100
|
+
file: props.controller.file,
|
|
101
|
+
controller: props.controller.name,
|
|
102
|
+
function: props.operation.name,
|
|
95
103
|
message: "TypeException() with implicit (unnamed) type.",
|
|
96
104
|
});
|
|
97
105
|
return false;
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
// DO ASSIGN
|
|
101
|
-
const matched:
|
|
109
|
+
const matched: IReflectHttpOperation.IException[] = Object.entries(
|
|
110
|
+
props.operation.exceptions,
|
|
111
|
+
)
|
|
102
112
|
.filter(([key]) => status === key)
|
|
103
113
|
.map(([_key, value]) => value);
|
|
104
114
|
for (const m of matched)
|
|
105
|
-
output[m.status] = {
|
|
115
|
+
props.output[m.status] = {
|
|
106
116
|
type: tuple.type,
|
|
107
117
|
typeName: tuple.typeName,
|
|
108
118
|
contentType: "application/json",
|
|
@@ -12,126 +12,145 @@ export namespace ImportAnalyzer {
|
|
|
12
12
|
|
|
13
13
|
export type Dictionary = HashMap<string, HashSet<string>>;
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
checker: ts.TypeChecker
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return {
|
|
15
|
+
export const analyze =
|
|
16
|
+
(checker: ts.TypeChecker) =>
|
|
17
|
+
(props: {
|
|
18
|
+
generics: GenericAnalyzer.Dictionary;
|
|
19
|
+
imports: Dictionary;
|
|
20
|
+
type: ts.Type;
|
|
21
|
+
}): ITypeTuple | null => {
|
|
22
|
+
const type: ts.Type = get_type(checker)(props.type);
|
|
23
|
+
explore_escaped_name(checker)({
|
|
24
|
+
...props,
|
|
26
25
|
type,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
});
|
|
27
|
+
try {
|
|
28
|
+
return {
|
|
29
|
+
type,
|
|
30
|
+
typeName: explore_escaped_name(checker)({
|
|
31
|
+
...props,
|
|
32
|
+
type,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
33
39
|
|
|
34
40
|
/* ---------------------------------------------------------
|
|
35
41
|
TYPE
|
|
36
42
|
--------------------------------------------------------- */
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
const get_type =
|
|
44
|
+
(checker: ts.TypeChecker) =>
|
|
45
|
+
(type: ts.Type): ts.Type => {
|
|
46
|
+
const symbol: ts.Symbol | undefined = type.getSymbol();
|
|
47
|
+
return symbol && get_name(symbol) === "Promise"
|
|
48
|
+
? escape_promise(checker)(type)
|
|
49
|
+
: type;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const escape_promise =
|
|
53
|
+
(checker: ts.TypeChecker) =>
|
|
54
|
+
(type: ts.Type): ts.Type => {
|
|
55
|
+
const generic: readonly ts.Type[] = checker.getTypeArguments(
|
|
56
|
+
type as ts.TypeReference,
|
|
51
57
|
);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
if (generic.length !== 1)
|
|
59
|
+
throw new Error(
|
|
60
|
+
"Error on ImportAnalyzer.analyze(): invalid promise type.",
|
|
61
|
+
);
|
|
62
|
+
return generic[0];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const get_name = (symbol: ts.Symbol): string =>
|
|
66
|
+
explore_name(
|
|
57
67
|
symbol.escapedName.toString(),
|
|
58
68
|
symbol.getDeclarations()?.[0]?.parent,
|
|
59
69
|
);
|
|
60
|
-
}
|
|
61
70
|
|
|
62
71
|
/* ---------------------------------------------------------
|
|
63
72
|
ESCAPED TEXT WITH IMPORT STATEMENTS
|
|
64
73
|
--------------------------------------------------------- */
|
|
65
|
-
|
|
66
|
-
checker: ts.TypeChecker
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)
|
|
87
|
-
.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
()
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
74
|
+
const explore_escaped_name =
|
|
75
|
+
(checker: ts.TypeChecker) =>
|
|
76
|
+
(props: {
|
|
77
|
+
generics: GenericAnalyzer.Dictionary;
|
|
78
|
+
imports: Dictionary;
|
|
79
|
+
type: ts.Type;
|
|
80
|
+
}): string => {
|
|
81
|
+
//----
|
|
82
|
+
// CONDITIONAL BRANCHES
|
|
83
|
+
//----
|
|
84
|
+
// DECOMPOSE GENERIC ARGUMENT
|
|
85
|
+
let type: ts.Type = props.type;
|
|
86
|
+
while (props.generics.has(type) === true)
|
|
87
|
+
type = props.generics.get(type)!;
|
|
88
|
+
|
|
89
|
+
// PRIMITIVE
|
|
90
|
+
const symbol: ts.Symbol | undefined =
|
|
91
|
+
type.aliasSymbol ?? type.getSymbol();
|
|
92
|
+
|
|
93
|
+
// UNION OR INTERSECT
|
|
94
|
+
if (type.aliasSymbol === undefined && type.isUnionOrIntersection()) {
|
|
95
|
+
const joiner: string = type.isIntersection() ? " & " : " | ";
|
|
96
|
+
return type.types
|
|
97
|
+
.map((child) =>
|
|
98
|
+
explore_escaped_name(checker)({
|
|
99
|
+
...props,
|
|
100
|
+
type: child,
|
|
101
|
+
}),
|
|
102
|
+
)
|
|
103
|
+
.join(joiner);
|
|
104
|
+
}
|
|
105
|
+
// NO SYMBOL
|
|
106
|
+
else if (symbol === undefined)
|
|
107
|
+
return checker.typeToString(
|
|
108
|
+
type,
|
|
109
|
+
undefined,
|
|
110
|
+
ts.TypeFormatFlags.NoTruncation,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
//----
|
|
114
|
+
// SPECIALIZATION
|
|
115
|
+
//----
|
|
116
|
+
const name: string = get_name(symbol);
|
|
117
|
+
const sourceFile: ts.SourceFile | undefined =
|
|
118
|
+
symbol.declarations?.[0]?.getSourceFile();
|
|
119
|
+
if (sourceFile === undefined) return name;
|
|
120
|
+
else if (sourceFile.fileName.indexOf("typescript/lib") === -1) {
|
|
121
|
+
const set: HashSet<string> = props.imports.take(
|
|
122
|
+
sourceFile.fileName,
|
|
123
|
+
() => new HashSet(),
|
|
124
|
+
);
|
|
125
|
+
set.insert(name.split(".")[0]);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// CHECK GENERIC
|
|
129
|
+
const generic: readonly ts.Type[] = type.aliasSymbol
|
|
130
|
+
? type.aliasTypeArguments ?? []
|
|
131
|
+
: checker.getTypeArguments(type as ts.TypeReference);
|
|
132
|
+
return generic.length
|
|
133
|
+
? name === "Promise"
|
|
134
|
+
? explore_escaped_name(checker)({
|
|
135
|
+
...props,
|
|
136
|
+
type: generic[0],
|
|
137
|
+
})
|
|
138
|
+
: `${name}<${generic
|
|
139
|
+
.map((child) =>
|
|
140
|
+
explore_escaped_name(checker)({
|
|
141
|
+
...props,
|
|
142
|
+
type: child,
|
|
143
|
+
}),
|
|
144
|
+
)
|
|
145
|
+
.join(", ")}>`
|
|
146
|
+
: name;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const explore_name = (name: string, decl?: ts.Node): string =>
|
|
150
|
+
decl && ts.isModuleBlock(decl)
|
|
131
151
|
? explore_name(
|
|
132
152
|
`${decl.parent.name.getFullText().trim()}.${name}`,
|
|
133
153
|
decl.parent.parent,
|
|
134
154
|
)
|
|
135
155
|
: name;
|
|
136
|
-
}
|
|
137
156
|
}
|
|
@@ -1,29 +1,7 @@
|
|
|
1
|
-
import { RequestMethod } from "@nestjs/common";
|
|
2
1
|
import path from "path";
|
|
3
2
|
import { Token, parse } from "path-to-regexp";
|
|
4
3
|
|
|
5
|
-
import { INormalizedInput } from "../structures/INormalizedInput";
|
|
6
|
-
|
|
7
4
|
export namespace PathAnalyzer {
|
|
8
|
-
export const combinate =
|
|
9
|
-
(globalPrefix: INormalizedInput["globalPrefix"]) =>
|
|
10
|
-
(versions: Array<string | null>) =>
|
|
11
|
-
(props: { path: string; method: string }): string[] => {
|
|
12
|
-
const out = (str: string) =>
|
|
13
|
-
versions.map((v) => (v === null ? str : join(v, str)));
|
|
14
|
-
if (!globalPrefix?.prefix.length) return out(props.path);
|
|
15
|
-
else if (!globalPrefix.exclude?.length)
|
|
16
|
-
return out(props.path).map((str) => join(globalPrefix.prefix, str));
|
|
17
|
-
return globalPrefix.exclude.some((exclude) =>
|
|
18
|
-
typeof exclude === "string"
|
|
19
|
-
? RegExp(exclude).test(props.path)
|
|
20
|
-
: METHOD(exclude.method) === props.method &&
|
|
21
|
-
RegExp(exclude.path).test(props.path),
|
|
22
|
-
)
|
|
23
|
-
? out(props.path)
|
|
24
|
-
: out(props.path).map((str) => join(globalPrefix.prefix, str));
|
|
25
|
-
};
|
|
26
|
-
|
|
27
5
|
export const join = (...args: string[]) =>
|
|
28
6
|
"/" +
|
|
29
7
|
_Trim(
|
|
@@ -89,22 +67,3 @@ export namespace PathAnalyzer {
|
|
|
89
67
|
value: string;
|
|
90
68
|
}
|
|
91
69
|
}
|
|
92
|
-
|
|
93
|
-
const METHOD = (value: RequestMethod) =>
|
|
94
|
-
value === RequestMethod.ALL
|
|
95
|
-
? "all"
|
|
96
|
-
: value === RequestMethod.DELETE
|
|
97
|
-
? "delete"
|
|
98
|
-
: value === RequestMethod.GET
|
|
99
|
-
? "get"
|
|
100
|
-
: value === RequestMethod.HEAD
|
|
101
|
-
? "head"
|
|
102
|
-
: value === RequestMethod.OPTIONS
|
|
103
|
-
? "options"
|
|
104
|
-
: value === RequestMethod.PATCH
|
|
105
|
-
? "patch"
|
|
106
|
-
: value === RequestMethod.POST
|
|
107
|
-
? "post"
|
|
108
|
-
: value === RequestMethod.PUT
|
|
109
|
-
? "put"
|
|
110
|
-
: "unknown";
|