@nestia/sdk 3.11.0-dev.20240813-11 → 3.11.0-dev.20240814
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.js +0 -13
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ReflectControllerAnalyzer.js +2 -0
- package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectHttpOperationAnalyzer.js +1 -0
- package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js +14 -7
- package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js +2 -1
- package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js.map +1 -1
- package/lib/analyses/TypedHttpRouteAnalyzer.js +3 -1
- package/lib/analyses/TypedHttpRouteAnalyzer.js.map +1 -1
- package/lib/generates/SwaggerGenerator.js +60 -8
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.js +11 -10
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkAliasCollection.d.ts +5 -1
- package/lib/generates/internal/SdkAliasCollection.js +20 -7
- package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
- package/lib/generates/internal/SdkFileProgrammer.js +8 -7
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpCloneProgrammer.js +4 -0
- package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpCloneReferencer.js +6 -0
- package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -1
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js +20 -13
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +15 -7
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpRouteProgrammer.js +2 -2
- package/lib/generates/internal/SdkHttpRouteProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpSimulationProgrammer.js +6 -3
- package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +10 -4
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +1 -1
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
- package/lib/generates/internal/SwaggerOperationComposer.js +19 -1
- package/lib/generates/internal/SwaggerOperationComposer.js.map +1 -1
- package/lib/generates/internal/SwaggerOperationParameterComposer.js +3 -3
- package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
- package/lib/transform.js +1 -1
- package/lib/transform.js.map +1 -1
- package/lib/transformers/SdkOperationProgrammer.js +17 -11
- package/lib/transformers/SdkOperationProgrammer.js.map +1 -1
- package/lib/transformers/SdkOperationTransformer.d.ts +1 -1
- package/lib/transformers/SdkOperationTransformer.js +12 -8
- package/lib/transformers/SdkOperationTransformer.js.map +1 -1
- package/lib/validators/HttpHeadersValidator.d.ts +5 -0
- package/lib/validators/HttpHeadersValidator.js +29 -0
- package/lib/validators/HttpHeadersValidator.js.map +1 -0
- package/lib/validators/HttpQueryValidator.d.ts +5 -0
- package/lib/validators/HttpQueryValidator.js +29 -0
- package/lib/validators/HttpQueryValidator.js.map +1 -0
- package/package.json +6 -6
- package/src/NestiaSdkApplication.ts +0 -14
- package/src/analyses/ReflectControllerAnalyzer.ts +2 -0
- package/src/analyses/ReflectHttpOperationAnalyzer.ts +1 -0
- package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +37 -5
- package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +8 -0
- package/src/analyses/TypedHttpRouteAnalyzer.ts +4 -1
- package/src/generates/SwaggerGenerator.ts +84 -10
- package/src/generates/internal/E2eFileProgrammer.ts +13 -10
- package/src/generates/internal/SdkAliasCollection.ts +28 -9
- package/src/generates/internal/SdkFileProgrammer.ts +8 -7
- package/src/generates/internal/SdkHttpCloneProgrammer.ts +4 -1
- package/src/generates/internal/SdkHttpCloneReferencer.ts +10 -0
- package/src/generates/internal/SdkHttpFunctionProgrammer.ts +25 -16
- package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +248 -229
- package/src/generates/internal/SdkHttpRouteProgrammer.ts +2 -2
- package/src/generates/internal/SdkHttpSimulationProgrammer.ts +6 -3
- package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +12 -8
- package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +1 -1
- package/src/generates/internal/SwaggerOperationComposer.ts +25 -0
- package/src/generates/internal/SwaggerOperationParameterComposer.ts +3 -0
- package/src/transform.ts +1 -1
- package/src/transformers/SdkOperationProgrammer.ts +41 -36
- package/src/transformers/SdkOperationTransformer.ts +29 -8
- package/src/validators/HttpHeadersValidator.ts +34 -0
- package/src/validators/HttpQueryValidator.ts +34 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SwaggerExample } from "@nestia/core";
|
|
1
2
|
import {
|
|
2
3
|
HEADERS_METADATA,
|
|
3
4
|
HTTP_CODE_METADATA,
|
|
@@ -78,6 +79,11 @@ export namespace ReflectHttpOperationResponseAnalyzer {
|
|
|
78
79
|
!typia.is<IReflectHttpOperationSuccess["contentType"]>(contentType)
|
|
79
80
|
)
|
|
80
81
|
return null;
|
|
82
|
+
|
|
83
|
+
const example: SwaggerExample.IData<any> | undefined = Reflect.getMetadata(
|
|
84
|
+
"nestia/SwaggerExample/Response",
|
|
85
|
+
ctx.function,
|
|
86
|
+
);
|
|
81
87
|
return {
|
|
82
88
|
contentType: contentType,
|
|
83
89
|
encrypted,
|
|
@@ -96,6 +102,8 @@ export namespace ReflectHttpOperationResponseAnalyzer {
|
|
|
96
102
|
meta.size()
|
|
97
103
|
? ["HEAD method must not have any return value."]
|
|
98
104
|
: [],
|
|
105
|
+
example: example?.example,
|
|
106
|
+
examples: example?.examples,
|
|
99
107
|
};
|
|
100
108
|
};
|
|
101
109
|
|
|
@@ -151,7 +151,10 @@ export namespace TypedHttpRouteAnalyzer {
|
|
|
151
151
|
},
|
|
152
152
|
),
|
|
153
153
|
};
|
|
154
|
-
if (errors.length)
|
|
154
|
+
if (errors.length) {
|
|
155
|
+
props.errors.push(...errors);
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
155
158
|
return props.paths.map((path) => ({
|
|
156
159
|
...props.operation,
|
|
157
160
|
controller: props.controller,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SwaggerCustomizer } from "@nestia/core";
|
|
1
2
|
import { OpenApi, OpenApiV3, SwaggerV2 } from "@samchon/openapi";
|
|
2
3
|
import fs from "fs";
|
|
3
4
|
import path from "path";
|
|
@@ -16,6 +17,7 @@ import { SwaggerOperationComposer } from "./internal/SwaggerOperationComposer";
|
|
|
16
17
|
export namespace SwaggerGenerator {
|
|
17
18
|
export const generate = async (app: ITypedApplication): Promise<void> => {
|
|
18
19
|
// GET CONFIGURATION
|
|
20
|
+
console.log("Generating Swagger Document");
|
|
19
21
|
if (app.project.config.swagger === undefined)
|
|
20
22
|
throw new Error("Swagger configuration is not defined.");
|
|
21
23
|
const config: INestiaConfig.ISwaggerConfig = app.project.config.swagger;
|
|
@@ -92,7 +94,7 @@ export namespace SwaggerGenerator {
|
|
|
92
94
|
const document: OpenApi.IDocument = props.document;
|
|
93
95
|
document.components.schemas ??= {};
|
|
94
96
|
Object.assign(document.components.schemas, json.components.schemas);
|
|
95
|
-
|
|
97
|
+
fillPaths({ ...props, schema, document });
|
|
96
98
|
|
|
97
99
|
return document;
|
|
98
100
|
};
|
|
@@ -175,23 +177,85 @@ export namespace SwaggerGenerator {
|
|
|
175
177
|
};
|
|
176
178
|
};
|
|
177
179
|
|
|
178
|
-
const
|
|
180
|
+
const fillPaths = (props: {
|
|
179
181
|
config: INestiaConfig.ISwaggerConfig;
|
|
180
182
|
document: OpenApi.IDocument;
|
|
181
183
|
schema: (metadata: Metadata) => OpenApi.IJsonSchema | undefined;
|
|
182
184
|
routes: ITypedHttpRoute[];
|
|
183
|
-
}):
|
|
184
|
-
|
|
185
|
+
}): void => {
|
|
186
|
+
// SWAGGER CUSTOMIZER
|
|
187
|
+
const customizers: Array<() => void> = [];
|
|
188
|
+
const neighbor = {
|
|
189
|
+
at: new Singleton(() => {
|
|
190
|
+
const functor: Map<Function, Endpoint> = new Map();
|
|
191
|
+
for (const r of props.routes) {
|
|
192
|
+
const method: OpenApi.Method =
|
|
193
|
+
r.method.toLowerCase() as OpenApi.Method;
|
|
194
|
+
const path: string = getPath(r);
|
|
195
|
+
const operation: OpenApi.IOperation | undefined =
|
|
196
|
+
props.document.paths?.[path]?.[method];
|
|
197
|
+
if (operation === undefined) continue;
|
|
198
|
+
functor.set(r.function, {
|
|
199
|
+
method,
|
|
200
|
+
path,
|
|
201
|
+
route: operation,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return functor;
|
|
205
|
+
}),
|
|
206
|
+
get: new Singleton(
|
|
207
|
+
() =>
|
|
208
|
+
(key: Accessor): OpenApi.IOperation | undefined => {
|
|
209
|
+
const method: OpenApi.Method =
|
|
210
|
+
key.method.toLowerCase() as OpenApi.Method;
|
|
211
|
+
const path: string =
|
|
212
|
+
"/" +
|
|
213
|
+
key.path
|
|
214
|
+
.split("/")
|
|
215
|
+
.filter((str) => !!str.length)
|
|
216
|
+
.map((str) =>
|
|
217
|
+
str.startsWith(":") ? `{${str.substring(1)}}` : str,
|
|
218
|
+
)
|
|
219
|
+
.join("/");
|
|
220
|
+
return props.document.paths?.[path]?.[method];
|
|
221
|
+
},
|
|
222
|
+
),
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// COMPOSE OPERATIONS
|
|
185
226
|
for (const r of props.routes) {
|
|
227
|
+
const operation: OpenApi.IOperation = SwaggerOperationComposer.compose({
|
|
228
|
+
...props,
|
|
229
|
+
route: r,
|
|
230
|
+
});
|
|
186
231
|
const path: string = getPath(r);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
232
|
+
props.document.paths ??= {};
|
|
233
|
+
props.document.paths[path] ??= {};
|
|
234
|
+
props.document.paths[path][r.method.toLowerCase() as "get"] = operation;
|
|
235
|
+
|
|
236
|
+
const closure: Function | Function[] | undefined = Reflect.getMetadata(
|
|
237
|
+
"nestia/SwaggerCustomizer",
|
|
238
|
+
r.controller.class.prototype,
|
|
239
|
+
r.name,
|
|
240
|
+
);
|
|
241
|
+
if (closure !== undefined) {
|
|
242
|
+
const array: Function[] = Array.isArray(closure) ? closure : [closure];
|
|
243
|
+
customizers.push(() => {
|
|
244
|
+
for (const closure of array)
|
|
245
|
+
closure({
|
|
246
|
+
swagger: props.document,
|
|
247
|
+
method: r.method,
|
|
248
|
+
path,
|
|
249
|
+
route: operation,
|
|
250
|
+
at: (func: Function) => neighbor.at.get().get(func),
|
|
251
|
+
get: (accessor: Accessor) => neighbor.get.get()(accessor),
|
|
252
|
+
} satisfies SwaggerCustomizer.IProps);
|
|
192
253
|
});
|
|
254
|
+
}
|
|
193
255
|
}
|
|
194
|
-
|
|
256
|
+
|
|
257
|
+
// DO CUSTOMIZE
|
|
258
|
+
for (const fn of customizers) fn();
|
|
195
259
|
};
|
|
196
260
|
|
|
197
261
|
const getPath = (route: {
|
|
@@ -207,3 +271,13 @@ export namespace SwaggerGenerator {
|
|
|
207
271
|
return str;
|
|
208
272
|
};
|
|
209
273
|
}
|
|
274
|
+
|
|
275
|
+
interface Accessor {
|
|
276
|
+
method: string;
|
|
277
|
+
path: string;
|
|
278
|
+
}
|
|
279
|
+
interface Endpoint {
|
|
280
|
+
method: string;
|
|
281
|
+
path: string;
|
|
282
|
+
route: OpenApi.IOperation;
|
|
283
|
+
}
|
|
@@ -30,13 +30,6 @@ export namespace E2eFileProgrammer {
|
|
|
30
30
|
instance: null,
|
|
31
31
|
name: "api",
|
|
32
32
|
});
|
|
33
|
-
for (const tuple of route.imports)
|
|
34
|
-
for (const instance of tuple.instances)
|
|
35
|
-
importer.internal({
|
|
36
|
-
type: true,
|
|
37
|
-
file: tuple.file,
|
|
38
|
-
instance,
|
|
39
|
-
});
|
|
40
33
|
|
|
41
34
|
const functor = generate_function(project)(importer)(route);
|
|
42
35
|
await FilePrinter.write({
|
|
@@ -73,7 +66,7 @@ export namespace E2eFileProgrammer {
|
|
|
73
66
|
(importer: ImportDictionary) =>
|
|
74
67
|
(route: ITypedHttpRoute) => {
|
|
75
68
|
const headers = route.parameters.find(
|
|
76
|
-
(p) => p.category === "headers" && p.field ===
|
|
69
|
+
(p) => p.category === "headers" && p.field === null,
|
|
77
70
|
);
|
|
78
71
|
const connection = headers
|
|
79
72
|
? ts.factory.createObjectLiteralExpression(
|
|
@@ -97,7 +90,13 @@ export namespace E2eFileProgrammer {
|
|
|
97
90
|
SdkImportWizard.typia(importer),
|
|
98
91
|
),
|
|
99
92
|
)("random"),
|
|
100
|
-
[
|
|
93
|
+
[
|
|
94
|
+
project.config.clone === true
|
|
95
|
+
? SdkAliasCollection.from(project)(importer)(
|
|
96
|
+
headers.metadata,
|
|
97
|
+
)
|
|
98
|
+
: SdkAliasCollection.name(headers),
|
|
99
|
+
],
|
|
101
100
|
undefined,
|
|
102
101
|
),
|
|
103
102
|
),
|
|
@@ -123,7 +122,11 @@ export namespace E2eFileProgrammer {
|
|
|
123
122
|
IdentifierFactory.access(
|
|
124
123
|
ts.factory.createIdentifier(SdkImportWizard.typia(importer)),
|
|
125
124
|
)("random"),
|
|
126
|
-
[
|
|
125
|
+
[
|
|
126
|
+
project.config.clone === true
|
|
127
|
+
? SdkAliasCollection.from(project)(importer)(p.metadata)
|
|
128
|
+
: SdkAliasCollection.name(p),
|
|
129
|
+
],
|
|
127
130
|
undefined,
|
|
128
131
|
),
|
|
129
132
|
),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import typia from "typia";
|
|
3
3
|
import { TypeFactory } from "typia/lib/factories/TypeFactory";
|
|
4
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
4
5
|
|
|
5
6
|
import { INestiaProject } from "../../structures/INestiaProject";
|
|
6
7
|
import { IReflectHttpOperationParameter } from "../../structures/IReflectHttpOperationParameter";
|
|
@@ -8,18 +9,29 @@ import { IReflectType } from "../../structures/IReflectType";
|
|
|
8
9
|
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
|
|
9
10
|
import { ITypedHttpRouteParameter } from "../../structures/ITypedHttpRouteParameter";
|
|
10
11
|
import { ImportDictionary } from "./ImportDictionary";
|
|
12
|
+
import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
|
|
11
13
|
|
|
12
14
|
export namespace SdkAliasCollection {
|
|
13
|
-
export const name = (type: IReflectType): ts.TypeNode =>
|
|
15
|
+
export const name = ({ type }: { type: IReflectType }): ts.TypeNode =>
|
|
14
16
|
ts.factory.createTypeReferenceNode(
|
|
15
17
|
type.name,
|
|
16
|
-
type.typeArguments
|
|
18
|
+
type.typeArguments
|
|
19
|
+
? type.typeArguments.map((a) => name({ type: a }))
|
|
20
|
+
: undefined,
|
|
17
21
|
);
|
|
18
22
|
|
|
23
|
+
export const from =
|
|
24
|
+
(project: INestiaProject) =>
|
|
25
|
+
(importer: ImportDictionary) =>
|
|
26
|
+
(metadata: Metadata) =>
|
|
27
|
+
SdkTypeProgrammer.write(project)(importer)(metadata);
|
|
28
|
+
|
|
19
29
|
export const headers =
|
|
20
30
|
(project: INestiaProject) =>
|
|
21
31
|
(importer: ImportDictionary) =>
|
|
22
32
|
(param: ITypedHttpRouteParameter.IHeaders): ts.TypeNode => {
|
|
33
|
+
if (project.config.clone === true)
|
|
34
|
+
return from(project)(importer)(param.metadata);
|
|
23
35
|
const type: ts.TypeNode = name(param);
|
|
24
36
|
if (project.config.primitive === false) return type;
|
|
25
37
|
return ts.factory.createTypeReferenceNode(
|
|
@@ -36,6 +48,8 @@ export namespace SdkAliasCollection {
|
|
|
36
48
|
(project: INestiaProject) =>
|
|
37
49
|
(importer: ImportDictionary) =>
|
|
38
50
|
(param: ITypedHttpRouteParameter.IQuery): ts.TypeNode => {
|
|
51
|
+
if (project.config.clone === true)
|
|
52
|
+
return from(project)(importer)(param.metadata);
|
|
39
53
|
const type: ts.TypeNode = name(param);
|
|
40
54
|
if (project.config.primitive === false) return type;
|
|
41
55
|
return ts.factory.createTypeReferenceNode(
|
|
@@ -52,9 +66,10 @@ export namespace SdkAliasCollection {
|
|
|
52
66
|
(project: INestiaProject) =>
|
|
53
67
|
(importer: ImportDictionary) =>
|
|
54
68
|
(param: ITypedHttpRouteParameter): ts.TypeNode => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
if (project.config.clone === true)
|
|
70
|
+
return from(project)(importer)(param.metadata);
|
|
71
|
+
const type: ts.TypeNode = name(param);
|
|
72
|
+
if (project.config.primitive === false) return type;
|
|
58
73
|
return ts.factory.createTypeReferenceNode(
|
|
59
74
|
importer.external({
|
|
60
75
|
type: true,
|
|
@@ -74,11 +89,15 @@ export namespace SdkAliasCollection {
|
|
|
74
89
|
(project: INestiaProject) =>
|
|
75
90
|
(importer: ImportDictionary) =>
|
|
76
91
|
(route: ITypedHttpRoute): ts.TypeNode => {
|
|
92
|
+
const schema = (p: { metadata: Metadata; type: IReflectType }) =>
|
|
93
|
+
project.config.clone === true
|
|
94
|
+
? from(project)(importer)(p.metadata)
|
|
95
|
+
: name(p);
|
|
77
96
|
if (project.config.propagate !== true) {
|
|
78
97
|
if (route.success.metadata.size() === 0)
|
|
79
98
|
return TypeFactory.keyword("void");
|
|
80
99
|
else if (project.config.primitive === false)
|
|
81
|
-
return
|
|
100
|
+
return schema(route.success);
|
|
82
101
|
return ts.factory.createTypeReferenceNode(
|
|
83
102
|
importer.external({
|
|
84
103
|
type: true,
|
|
@@ -89,7 +108,7 @@ export namespace SdkAliasCollection {
|
|
|
89
108
|
? "Primitive"
|
|
90
109
|
: "Resolved",
|
|
91
110
|
}),
|
|
92
|
-
[
|
|
111
|
+
[schema(route.success)],
|
|
93
112
|
);
|
|
94
113
|
}
|
|
95
114
|
|
|
@@ -98,11 +117,11 @@ export namespace SdkAliasCollection {
|
|
|
98
117
|
status: String(
|
|
99
118
|
route.success.status ?? (route.method === "POST" ? 201 : 200),
|
|
100
119
|
),
|
|
101
|
-
type:
|
|
120
|
+
type: schema(route.success),
|
|
102
121
|
},
|
|
103
122
|
...Object.entries(route.exceptions).map(([status, value]) => ({
|
|
104
123
|
status,
|
|
105
|
-
type:
|
|
124
|
+
type: schema(value),
|
|
106
125
|
})),
|
|
107
126
|
];
|
|
108
127
|
return ts.factory.createTypeReferenceNode(
|
|
@@ -75,13 +75,14 @@ export namespace SdkFileProgrammer {
|
|
|
75
75
|
`${outDir}/index.ts`,
|
|
76
76
|
);
|
|
77
77
|
directory.routes.forEach((route, i) => {
|
|
78
|
-
|
|
79
|
-
for (const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
if (!(project.config.clone === true && route.protocol === "http"))
|
|
79
|
+
for (const tuple of route.imports)
|
|
80
|
+
for (const instance of tuple.instances)
|
|
81
|
+
importer.internal({
|
|
82
|
+
file: tuple.file,
|
|
83
|
+
instance,
|
|
84
|
+
type: true,
|
|
85
|
+
});
|
|
85
86
|
statements.push(
|
|
86
87
|
...(route.protocol === "http"
|
|
87
88
|
? SdkHttpRouteProgrammer.write(project)(importer)(route)
|
|
@@ -23,6 +23,10 @@ export namespace SdkHttpCloneProgrammer {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export const write = (app: ITypedApplication): Map<string, IModule> => {
|
|
26
|
+
// console.log({
|
|
27
|
+
// objects: Array.from(app.collection.objects.keys()).sort(),
|
|
28
|
+
// aliases: Array.from(app.collection.aliases.keys()).sort(),
|
|
29
|
+
// });
|
|
26
30
|
// COMPOSE THE DICTIONARY
|
|
27
31
|
const dict: Map<string, IModule> = new Map();
|
|
28
32
|
for (const [k, v] of app.collection.objects.entries())
|
|
@@ -39,7 +43,6 @@ export namespace SdkHttpCloneProgrammer {
|
|
|
39
43
|
name: k,
|
|
40
44
|
programmer: (importer) => write_alias(app.project)(importer)(v),
|
|
41
45
|
});
|
|
42
|
-
|
|
43
46
|
return dict;
|
|
44
47
|
};
|
|
45
48
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
2
2
|
|
|
3
|
+
import { IReflectType } from "../../structures/IReflectType";
|
|
3
4
|
import { ITypedApplication } from "../../structures/ITypedApplication";
|
|
4
5
|
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
|
|
5
6
|
import { StringUtil } from "../../utils/StringUtil";
|
|
@@ -24,17 +25,20 @@ export namespace SdkHttpCloneReferencer {
|
|
|
24
25
|
visitType({
|
|
25
26
|
unique,
|
|
26
27
|
metadata: p.metadata,
|
|
28
|
+
type: p.type,
|
|
27
29
|
name: (name) => (p.type = { name }),
|
|
28
30
|
});
|
|
29
31
|
for (const v of Object.values(props.route.exceptions))
|
|
30
32
|
visitType({
|
|
31
33
|
unique,
|
|
32
34
|
metadata: v.metadata,
|
|
35
|
+
type: v.type,
|
|
33
36
|
name: (name) => (v.type = { name }),
|
|
34
37
|
});
|
|
35
38
|
visitType({
|
|
36
39
|
unique,
|
|
37
40
|
metadata: props.route.success.metadata,
|
|
41
|
+
type: props.route.success.type,
|
|
38
42
|
name: (name) => (props.route.success.type = { name }),
|
|
39
43
|
});
|
|
40
44
|
props.route.imports = Array.from(unique).map((str) => ({
|
|
@@ -46,6 +50,7 @@ export namespace SdkHttpCloneReferencer {
|
|
|
46
50
|
const visitType = (p: {
|
|
47
51
|
unique: Set<string>;
|
|
48
52
|
metadata: Metadata;
|
|
53
|
+
type: IReflectType;
|
|
49
54
|
name: (key: string) => void;
|
|
50
55
|
}): void => {
|
|
51
56
|
const enroll = (key: string) => {
|
|
@@ -59,3 +64,8 @@ export namespace SdkHttpCloneReferencer {
|
|
|
59
64
|
p.name(p.metadata.getName());
|
|
60
65
|
};
|
|
61
66
|
}
|
|
67
|
+
|
|
68
|
+
const getFullText = (type: IReflectType): string =>
|
|
69
|
+
type.typeArguments === undefined
|
|
70
|
+
? type.name
|
|
71
|
+
: `${type.name}<${type.typeArguments.map(getFullText).join(", ")}>`;
|
|
@@ -2,7 +2,6 @@ import ts from "typescript";
|
|
|
2
2
|
import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
|
|
3
3
|
import { TypeFactory } from "typia/lib/factories/TypeFactory";
|
|
4
4
|
|
|
5
|
-
import { INestiaConfig } from "../../INestiaConfig";
|
|
6
5
|
import { INestiaProject } from "../../structures/INestiaProject";
|
|
7
6
|
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
|
|
8
7
|
import { ITypedHttpRouteParameter } from "../../structures/ITypedHttpRouteParameter";
|
|
@@ -56,21 +55,26 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
56
55
|
? ts.factory.createTypeReferenceNode(
|
|
57
56
|
`${route.name}.${p === props.query ? "Query" : "Input"}`,
|
|
58
57
|
)
|
|
59
|
-
:
|
|
58
|
+
: project.config.clone === true
|
|
59
|
+
? SdkAliasCollection.from(project)(importer)(p.metadata)
|
|
60
|
+
: SdkAliasCollection.name(p),
|
|
60
61
|
),
|
|
61
62
|
),
|
|
62
63
|
],
|
|
63
64
|
ts.factory.createTypeReferenceNode("Promise", [
|
|
64
|
-
|
|
65
|
+
project.config.propagate === true ||
|
|
66
|
+
route.success.metadata.size() !== 0
|
|
67
|
+
? ts.factory.createTypeReferenceNode(`${route.name}.Output`)
|
|
68
|
+
: ts.factory.createTypeReferenceNode("void"),
|
|
65
69
|
]),
|
|
66
70
|
ts.factory.createBlock(
|
|
67
|
-
write_body(project
|
|
71
|
+
write_body(project)(importer)(route, props),
|
|
68
72
|
true,
|
|
69
73
|
),
|
|
70
74
|
);
|
|
71
75
|
|
|
72
76
|
const write_body =
|
|
73
|
-
(
|
|
77
|
+
(project: INestiaProject) =>
|
|
74
78
|
(importer: ImportDictionary) =>
|
|
75
79
|
(
|
|
76
80
|
route: ITypedHttpRoute,
|
|
@@ -84,10 +88,12 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
84
88
|
ts.factory.createCallExpression(
|
|
85
89
|
IdentifierFactory.access(
|
|
86
90
|
ts.factory.createIdentifier(
|
|
87
|
-
SdkImportWizard.Fetcher(
|
|
91
|
+
SdkImportWizard.Fetcher(
|
|
92
|
+
!!props.input?.encrypted || route.success.encrypted,
|
|
93
|
+
)(importer),
|
|
88
94
|
),
|
|
89
|
-
)(config.propagate ? "propagate" : "fetch"),
|
|
90
|
-
config.propagate
|
|
95
|
+
)(project.config.propagate ? "propagate" : "fetch"),
|
|
96
|
+
project.config.propagate
|
|
91
97
|
? route.method.toLowerCase() === "get" ||
|
|
92
98
|
route.method.toLowerCase() === "head"
|
|
93
99
|
? [TypeFactory.keyword("any")]
|
|
@@ -158,7 +164,7 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
158
164
|
...(props.input
|
|
159
165
|
? [ts.factory.createIdentifier(props.input.name)]
|
|
160
166
|
: []),
|
|
161
|
-
...(config.json &&
|
|
167
|
+
...(project.config.json &&
|
|
162
168
|
props.input !== undefined &&
|
|
163
169
|
(props.input.contentType === "application/json" ||
|
|
164
170
|
props.input.encrypted === true)
|
|
@@ -167,7 +173,7 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
167
173
|
],
|
|
168
174
|
);
|
|
169
175
|
const output = (awaiter: boolean) =>
|
|
170
|
-
config.simulate
|
|
176
|
+
project.config.simulate
|
|
171
177
|
? ts.factory.createConditionalExpression(
|
|
172
178
|
ts.factory.createIdentifier("!!connection.simulate"),
|
|
173
179
|
undefined,
|
|
@@ -188,7 +194,7 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
188
194
|
? ts.factory.createAwaitExpression(caller())
|
|
189
195
|
: caller();
|
|
190
196
|
return [
|
|
191
|
-
...(config.assert
|
|
197
|
+
...(project.config.assert
|
|
192
198
|
? route.parameters
|
|
193
199
|
.filter((p) => p.category !== "headers")
|
|
194
200
|
.map((p) =>
|
|
@@ -211,12 +217,13 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
211
217
|
: []),
|
|
212
218
|
...(route.success.setHeaders.length === 0
|
|
213
219
|
? [ts.factory.createReturnStatement(output(false))]
|
|
214
|
-
: write_set_headers(
|
|
220
|
+
: write_set_headers(project)(importer)(route)(output(true))),
|
|
215
221
|
];
|
|
216
222
|
};
|
|
217
223
|
|
|
218
224
|
const write_set_headers =
|
|
219
|
-
(
|
|
225
|
+
(project: INestiaProject) =>
|
|
226
|
+
(importer: ImportDictionary) =>
|
|
220
227
|
(route: ITypedHttpRoute) =>
|
|
221
228
|
(condition: ts.Expression): ts.Statement[] => {
|
|
222
229
|
const accessor = (x: string) => (y: string) =>
|
|
@@ -226,7 +233,9 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
226
233
|
...route.parameters.map((p) => p.name),
|
|
227
234
|
])("output");
|
|
228
235
|
const headers: string = accessor("connection")("headers");
|
|
229
|
-
const data: string = config.propagate
|
|
236
|
+
const data: string = project.config.propagate
|
|
237
|
+
? accessor(output)("data")
|
|
238
|
+
: output;
|
|
230
239
|
|
|
231
240
|
const assigners: ts.ExpressionStatement[] = [
|
|
232
241
|
ts.factory.createBinaryExpression(
|
|
@@ -261,14 +270,14 @@ export namespace SdkHttpFunctionProgrammer {
|
|
|
261
270
|
ts.factory.createVariableDeclaration(
|
|
262
271
|
output,
|
|
263
272
|
undefined,
|
|
264
|
-
SdkAliasCollection.
|
|
273
|
+
SdkAliasCollection.output(project)(importer)(route),
|
|
265
274
|
condition,
|
|
266
275
|
),
|
|
267
276
|
],
|
|
268
277
|
ts.NodeFlags.Const,
|
|
269
278
|
),
|
|
270
279
|
),
|
|
271
|
-
...(config.propagate
|
|
280
|
+
...(project.config.propagate
|
|
272
281
|
? [
|
|
273
282
|
ts.factory.createIfStatement(
|
|
274
283
|
ts.factory.createIdentifier(accessor(output)("success")),
|