@nestia/sdk 3.11.0-dev.20240813-10 → 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/assets/bundle/api/Resolved.ts +1 -0
- package/assets/bundle/api/module.ts +1 -0
- package/lib/NestiaSdkApplication.d.ts +1 -0
- package/lib/NestiaSdkApplication.js +24 -26
- 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 +10 -1
- package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.d.ts +15 -0
- package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js +50 -0
- package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js.map +1 -0
- package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js +14 -9
- 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/ReflectWebSocketOperationAnalyzer.js +3 -2
- package/lib/analyses/ReflectWebSocketOperationAnalyzer.js.map +1 -1
- package/lib/analyses/TypedHttpRouteAnalyzer.js +3 -1
- package/lib/analyses/TypedHttpRouteAnalyzer.js.map +1 -1
- package/lib/executable/internal/NestiaSdkCommand.d.ts +1 -0
- package/lib/executable/internal/NestiaSdkCommand.js +3 -2
- package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
- package/lib/executable/sdk.js +3 -0
- package/lib/executable/sdk.js.map +1 -1
- package/lib/generates/CloneGenerator.d.ts +4 -0
- package/lib/generates/CloneGenerator.js +62 -60
- package/lib/generates/CloneGenerator.js.map +1 -1
- package/lib/generates/SdkGenerator.js +4 -3
- package/lib/generates/SdkGenerator.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 -3
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/ImportDictionary.js +1 -1
- package/lib/generates/internal/ImportDictionary.js.map +1 -1
- package/lib/generates/internal/SdkAliasCollection.d.ts +5 -1
- package/lib/generates/internal/SdkAliasCollection.js +24 -8
- package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
- package/lib/generates/internal/SdkFileProgrammer.js +1 -1
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +11 -0
- package/lib/generates/internal/SdkHttpCloneProgrammer.js +75 -142
- package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpCloneReferencer.d.ts +4 -0
- package/lib/generates/internal/SdkHttpCloneReferencer.js +62 -0
- package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -0
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js +26 -13
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +17 -8
- 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 +8 -5
- package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +12 -5
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +3 -3
- 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/structures/IReflectHttpOperation.d.ts +1 -1
- package/lib/structures/IReflectHttpOperationException.d.ts +2 -2
- package/lib/structures/ITypedApplication.d.ts +2 -0
- package/lib/transform.js +2 -2
- package/lib/transform.js.map +1 -1
- package/lib/transformers/IOperationMetadata.d.ts +6 -1
- package/lib/transformers/{ISdkTransformerContext.d.ts → ISdkOperationTransformerContext.d.ts} +1 -1
- package/lib/transformers/{ISdkTransformerContext.js → ISdkOperationTransformerContext.js} +1 -1
- package/lib/transformers/ISdkOperationTransformerContext.js.map +1 -0
- package/lib/transformers/SdkOperationProgrammer.d.ts +13 -0
- package/lib/transformers/{SdkMetadataProgrammer.js → SdkOperationProgrammer.js} +36 -55
- package/lib/transformers/SdkOperationProgrammer.js.map +1 -0
- package/lib/transformers/SdkOperationTransformer.d.ts +4 -0
- package/lib/transformers/{SdkTransformer.js → SdkOperationTransformer.js} +56 -16
- package/lib/transformers/SdkOperationTransformer.js.map +1 -0
- package/lib/utils/MetadataUtil.d.ts +4 -0
- package/lib/utils/MetadataUtil.js +34 -0
- package/lib/utils/MetadataUtil.js.map +1 -0
- package/lib/utils/StringUtil.d.ts +1 -0
- package/lib/utils/StringUtil.js +6 -0
- package/lib/utils/StringUtil.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 +8 -8
- package/src/NestiaSdkApplication.ts +20 -30
- package/src/analyses/ReflectControllerAnalyzer.ts +2 -0
- package/src/analyses/ReflectHttpOperationAnalyzer.ts +10 -1
- package/src/analyses/ReflectHttpOperationExceptionAnalyzer.ts +71 -0
- package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +37 -8
- package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +8 -0
- package/src/analyses/ReflectWebSocketOperationAnalyzer.ts +10 -2
- package/src/analyses/TypedHttpRouteAnalyzer.ts +4 -1
- package/src/executable/internal/NestiaSdkCommand.ts +3 -2
- package/src/executable/sdk.ts +2 -0
- package/src/generates/CloneGenerator.ts +61 -60
- package/src/generates/SdkGenerator.ts +3 -3
- package/src/generates/SwaggerGenerator.ts +84 -10
- package/src/generates/internal/E2eFileProgrammer.ts +13 -3
- package/src/generates/internal/ImportDictionary.ts +1 -1
- package/src/generates/internal/SdkAliasCollection.ts +32 -10
- package/src/generates/internal/SdkFileProgrammer.ts +1 -1
- package/src/generates/internal/SdkHttpCloneProgrammer.ts +118 -144
- package/src/generates/internal/SdkHttpCloneReferencer.ts +71 -0
- package/src/generates/internal/SdkHttpFunctionProgrammer.ts +31 -16
- package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +252 -230
- package/src/generates/internal/SdkHttpRouteProgrammer.ts +2 -2
- package/src/generates/internal/SdkHttpSimulationProgrammer.ts +30 -24
- package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +14 -6
- package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +6 -8
- package/src/generates/internal/SwaggerOperationComposer.ts +25 -0
- package/src/generates/internal/SwaggerOperationParameterComposer.ts +3 -0
- package/src/structures/IReflectHttpOperation.ts +1 -4
- package/src/structures/IReflectHttpOperationException.ts +2 -2
- package/src/structures/ITypedApplication.ts +3 -0
- package/src/transform.ts +2 -2
- package/src/transformers/IOperationMetadata.ts +7 -1
- package/src/transformers/{ISdkTransformerContext.ts → ISdkOperationTransformerContext.ts} +1 -1
- package/src/transformers/{SdkMetadataProgrammer.ts → SdkOperationProgrammer.ts} +40 -62
- package/src/transformers/{SdkTransformer.ts → SdkOperationTransformer.ts} +88 -16
- package/src/utils/MetadataUtil.ts +26 -0
- package/src/utils/StringUtil.ts +8 -0
- package/src/validators/HttpHeadersValidator.ts +34 -0
- package/src/validators/HttpQueryValidator.ts +34 -0
- package/lib/transformers/ISdkTransformerContext.js.map +0 -1
- package/lib/transformers/SdkMetadataProgrammer.d.ts +0 -11
- package/lib/transformers/SdkMetadataProgrammer.js.map +0 -1
- package/lib/transformers/SdkTransformer.d.ts +0 -4
- package/lib/transformers/SdkTransformer.js.map +0 -1
|
@@ -78,22 +78,30 @@ export namespace SdkWebSocketNamespaceProgrammer {
|
|
|
78
78
|
route.parameters.find((x) => x.category === "acceptor")!;
|
|
79
79
|
const query: ITypedWebSocketRouteParameter.IQuery | undefined =
|
|
80
80
|
route.parameters.find((x) => x.category === "query");
|
|
81
|
+
const driver: ITypedWebSocketRouteParameter.IDriver | undefined =
|
|
82
|
+
route.parameters.find((x) => x.category === "driver");
|
|
81
83
|
declare(
|
|
82
84
|
"Header",
|
|
83
|
-
SdkAliasCollection.name(
|
|
84
|
-
(route.parameters.find((x) => x.category === "header")?.type ??
|
|
85
|
+
SdkAliasCollection.name({
|
|
86
|
+
type: (route.parameters.find((x) => x.category === "header")?.type ??
|
|
85
87
|
acceptor.type.typeArguments?.[0])!,
|
|
86
|
-
),
|
|
88
|
+
}),
|
|
87
89
|
);
|
|
88
90
|
declare(
|
|
89
91
|
"Provider",
|
|
90
|
-
SdkAliasCollection.name(
|
|
92
|
+
SdkAliasCollection.name({
|
|
93
|
+
type:
|
|
94
|
+
driver?.type.typeArguments?.[0] ??
|
|
95
|
+
acceptor.type.typeArguments?.[2]!,
|
|
96
|
+
}),
|
|
91
97
|
);
|
|
92
98
|
declare(
|
|
93
99
|
"Listener",
|
|
94
|
-
SdkAliasCollection.name(
|
|
100
|
+
SdkAliasCollection.name({
|
|
101
|
+
type: acceptor.type.typeArguments?.[1]!,
|
|
102
|
+
}),
|
|
95
103
|
);
|
|
96
|
-
if (query) declare("Query", SdkAliasCollection.name(query
|
|
104
|
+
if (query) declare("Query", SdkAliasCollection.name(query));
|
|
97
105
|
return output;
|
|
98
106
|
};
|
|
99
107
|
|
|
@@ -78,7 +78,7 @@ export namespace SdkWebSocketRouteProgrammer {
|
|
|
78
78
|
IdentifierFactory.parameter(
|
|
79
79
|
p.name,
|
|
80
80
|
p.category === "param"
|
|
81
|
-
? SdkAliasCollection.name(p
|
|
81
|
+
? SdkAliasCollection.name(p)
|
|
82
82
|
: ts.factory.createTypeReferenceNode(`${route.name}.Query`),
|
|
83
83
|
),
|
|
84
84
|
),
|
|
@@ -164,13 +164,11 @@ export namespace SdkWebSocketRouteProgrammer {
|
|
|
164
164
|
),
|
|
165
165
|
local("driver")(
|
|
166
166
|
ts.factory.createTypeReferenceNode(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}),
|
|
173
|
-
),
|
|
167
|
+
importer.external({
|
|
168
|
+
type: true,
|
|
169
|
+
library: "tgrid",
|
|
170
|
+
instance: "Driver",
|
|
171
|
+
}),
|
|
174
172
|
[ts.factory.createTypeReferenceNode(`${route.name}.Listener`)],
|
|
175
173
|
),
|
|
176
174
|
)(
|
|
@@ -2,6 +2,7 @@ import { OpenApi } from "@samchon/openapi";
|
|
|
2
2
|
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
3
3
|
|
|
4
4
|
import { INestiaConfig } from "../../INestiaConfig";
|
|
5
|
+
import { SecurityAnalyzer } from "../../analyses/SecurityAnalyzer";
|
|
5
6
|
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
|
|
6
7
|
import { ITypedHttpRouteParameter } from "../../structures/ITypedHttpRouteParameter";
|
|
7
8
|
import { SwaggerDescriptionComposer } from "./SwaggerDescriptionComposer";
|
|
@@ -44,6 +45,29 @@ export namespace SwaggerOperationComposer {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
// SECURITY
|
|
49
|
+
const security: Record<string, string[]>[] = SecurityAnalyzer.merge(
|
|
50
|
+
...props.route.controller.security,
|
|
51
|
+
...props.route.security,
|
|
52
|
+
...props.route.jsDocTags
|
|
53
|
+
.filter((tag) => tag.name === "security")
|
|
54
|
+
.map((tag) =>
|
|
55
|
+
tag.text === undefined
|
|
56
|
+
? [{}]
|
|
57
|
+
: tag.text.map((text) => {
|
|
58
|
+
const line: string[] = text.text
|
|
59
|
+
.split(" ")
|
|
60
|
+
.filter((s) => s.trim())
|
|
61
|
+
.filter((s) => !!s.length);
|
|
62
|
+
if (line.length === 0) return {};
|
|
63
|
+
return {
|
|
64
|
+
[line[0]]: line.slice(1),
|
|
65
|
+
};
|
|
66
|
+
}),
|
|
67
|
+
)
|
|
68
|
+
.flat(),
|
|
69
|
+
);
|
|
70
|
+
|
|
47
71
|
// FINALIZE
|
|
48
72
|
return {
|
|
49
73
|
...SwaggerDescriptionComposer.compose({
|
|
@@ -85,6 +109,7 @@ export namespace SwaggerOperationComposer {
|
|
|
85
109
|
schema: props.schema,
|
|
86
110
|
route: props.route,
|
|
87
111
|
}),
|
|
112
|
+
security: security.length ? security : undefined,
|
|
88
113
|
};
|
|
89
114
|
};
|
|
90
115
|
}
|
|
@@ -77,6 +77,8 @@ export namespace SwaggerOperationParameterComposer {
|
|
|
77
77
|
jsDocTags: props.parameter.jsDocTags,
|
|
78
78
|
kind: "title",
|
|
79
79
|
}),
|
|
80
|
+
example: props.parameter.example,
|
|
81
|
+
examples: props.parameter.examples,
|
|
80
82
|
});
|
|
81
83
|
|
|
82
84
|
export const query = (
|
|
@@ -114,6 +116,7 @@ export namespace SwaggerOperationParameterComposer {
|
|
|
114
116
|
jsDocTags: props.jsDocTags,
|
|
115
117
|
kind: "title",
|
|
116
118
|
}),
|
|
119
|
+
required: props.parameter.metadata.isRequired(),
|
|
117
120
|
example: props.parameter.example,
|
|
118
121
|
examples: props.parameter.examples,
|
|
119
122
|
};
|
|
@@ -15,10 +15,7 @@ export interface IReflectHttpOperation {
|
|
|
15
15
|
versions: Array<string | typeof VERSION_NEUTRAL> | undefined;
|
|
16
16
|
parameters: IReflectHttpOperationParameter[];
|
|
17
17
|
success: IReflectHttpOperationSuccess;
|
|
18
|
-
exceptions: Record<
|
|
19
|
-
number | "2XX" | "3XX" | "4XX" | "5XX",
|
|
20
|
-
IReflectHttpOperationException
|
|
21
|
-
>;
|
|
18
|
+
exceptions: Record<string, IReflectHttpOperationException>;
|
|
22
19
|
security: Record<string, string[]>[];
|
|
23
20
|
tags: string[];
|
|
24
21
|
imports: IReflectTypeImport[];
|
|
@@ -8,8 +8,8 @@ export interface IReflectHttpOperationException {
|
|
|
8
8
|
// BASIC PROPERTIES
|
|
9
9
|
status: number | "2XX" | "3XX" | "4XX" | "5XX";
|
|
10
10
|
description: string | null;
|
|
11
|
-
example
|
|
12
|
-
examples
|
|
11
|
+
example?: any;
|
|
12
|
+
examples?: Record<string, any>;
|
|
13
13
|
|
|
14
14
|
// REFLECTED PROPERTIES
|
|
15
15
|
type: IReflectType;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { IMetadataDictionary } from "typia/lib/schemas/metadata/IMetadataDictionary";
|
|
2
|
+
|
|
1
3
|
import { INestiaProject } from "./INestiaProject";
|
|
2
4
|
import { ITypedHttpRoute } from "./ITypedHttpRoute";
|
|
3
5
|
import { ITypedWebSocketRoute } from "./ITypedWebSocketRoute";
|
|
4
6
|
|
|
5
7
|
export interface ITypedApplication {
|
|
6
8
|
project: INestiaProject;
|
|
9
|
+
collection: IMetadataDictionary;
|
|
7
10
|
routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>;
|
|
8
11
|
}
|
package/src/transform.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { SdkOperationTransformer } from "./transformers/SdkOperationTransformer";
|
|
4
4
|
|
|
5
5
|
export const transform = (
|
|
6
6
|
program: ts.Program,
|
|
7
7
|
): ts.TransformerFactory<ts.SourceFile> =>
|
|
8
|
-
|
|
8
|
+
SdkOperationTransformer.iterateFile(program.getTypeChecker());
|
|
9
9
|
export default transform;
|
|
@@ -9,7 +9,7 @@ import { IReflectTypeImport } from "../structures/IReflectTypeImport";
|
|
|
9
9
|
export interface IOperationMetadata {
|
|
10
10
|
parameters: IOperationMetadata.IParameter[];
|
|
11
11
|
success: IOperationMetadata.IResponse;
|
|
12
|
-
exceptions:
|
|
12
|
+
exceptions: IOperationMetadata.IResponse[];
|
|
13
13
|
description: string | null;
|
|
14
14
|
jsDocTags: IJsDocTagInfo[];
|
|
15
15
|
}
|
|
@@ -26,6 +26,12 @@ export namespace IOperationMetadata {
|
|
|
26
26
|
primitive: ValidationPipe<ISchema, IError>;
|
|
27
27
|
resolved: ValidationPipe<ISchema, IError>;
|
|
28
28
|
}
|
|
29
|
+
export interface IException {
|
|
30
|
+
type: IReflectType | null;
|
|
31
|
+
imports: IReflectTypeImport[];
|
|
32
|
+
primitive: ValidationPipe<ISchema, IError>;
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
export interface ISchema {
|
|
30
36
|
components: IMetadataComponents;
|
|
31
37
|
metadata: IMetadata;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
|
|
3
3
|
|
|
4
|
-
export interface
|
|
4
|
+
export interface ISdkOperationTransformerContext {
|
|
5
5
|
checker: ts.TypeChecker;
|
|
6
6
|
api: ts.TransformationContext;
|
|
7
7
|
collection: MetadataCollection;
|
|
@@ -9,18 +9,19 @@ import { ValidationPipe } from "typia/lib/typings/ValidationPipe";
|
|
|
9
9
|
import { Escaper } from "typia/lib/utils/Escaper";
|
|
10
10
|
|
|
11
11
|
import { ImportAnalyzer } from "../analyses/ImportAnalyzer";
|
|
12
|
+
import { MetadataUtil } from "../utils/MetadataUtil";
|
|
12
13
|
import { IOperationMetadata } from "./IOperationMetadata";
|
|
13
|
-
import {
|
|
14
|
+
import { ISdkOperationTransformerContext } from "./ISdkOperationTransformerContext";
|
|
14
15
|
|
|
15
|
-
export namespace
|
|
16
|
+
export namespace SdkOperationProgrammer {
|
|
16
17
|
export interface IProps {
|
|
17
|
-
context:
|
|
18
|
+
context: ISdkOperationTransformerContext;
|
|
18
19
|
generics: WeakMap<ts.Type, ts.Type>;
|
|
19
20
|
node: ts.MethodDeclaration;
|
|
21
|
+
symbol: ts.Symbol | undefined;
|
|
22
|
+
exceptions: ts.TypeNode[];
|
|
20
23
|
}
|
|
21
24
|
export const write = (p: IProps): IOperationMetadata => {
|
|
22
|
-
const signature: ts.Signature | undefined =
|
|
23
|
-
p.context.checker.getSignatureFromDeclaration(p.node);
|
|
24
25
|
return {
|
|
25
26
|
parameters: p.node.parameters.map((parameter, index) =>
|
|
26
27
|
writeParameter({
|
|
@@ -35,32 +36,42 @@ export namespace SdkMetadataProgrammer {
|
|
|
35
36
|
generics: p.generics,
|
|
36
37
|
type: getReturnType({
|
|
37
38
|
checker: p.context.checker,
|
|
38
|
-
signature,
|
|
39
|
+
signature: p.context.checker.getSignatureFromDeclaration(p.node),
|
|
39
40
|
}),
|
|
40
41
|
}),
|
|
41
|
-
exceptions:
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
exceptions: p.exceptions.map((e) =>
|
|
43
|
+
writeResponse({
|
|
44
|
+
context: p.context,
|
|
45
|
+
generics: p.generics,
|
|
46
|
+
type: p.context.checker.getTypeFromTypeNode(e),
|
|
47
|
+
}),
|
|
48
|
+
),
|
|
49
|
+
jsDocTags: p.symbol?.getJsDocTags() ?? [],
|
|
50
|
+
description: p.symbol
|
|
51
|
+
? CommentFactory.description(p.symbol) ?? null
|
|
52
|
+
: null,
|
|
44
53
|
};
|
|
45
54
|
};
|
|
46
55
|
|
|
47
56
|
const writeParameter = (props: {
|
|
48
|
-
context:
|
|
57
|
+
context: ISdkOperationTransformerContext;
|
|
49
58
|
generics: WeakMap<ts.Type, ts.Type>;
|
|
50
59
|
parameter: ts.ParameterDeclaration;
|
|
51
60
|
index: number;
|
|
52
61
|
}): IOperationMetadata.IParameter => {
|
|
53
62
|
const symbol: ts.Symbol | undefined =
|
|
54
63
|
props.context.checker.getSymbolAtLocation(props.parameter);
|
|
64
|
+
const common: IOperationMetadata.IResponse = writeType({
|
|
65
|
+
context: props.context,
|
|
66
|
+
generics: props.generics,
|
|
67
|
+
type:
|
|
68
|
+
props.context.checker.getTypeFromTypeNode(
|
|
69
|
+
props.parameter.type ?? TypeFactory.keyword("any"),
|
|
70
|
+
) ?? null,
|
|
71
|
+
required: props.parameter.questionToken === undefined,
|
|
72
|
+
});
|
|
55
73
|
return {
|
|
56
|
-
...
|
|
57
|
-
...props,
|
|
58
|
-
type:
|
|
59
|
-
props.context.checker.getTypeFromTypeNode(
|
|
60
|
-
props.parameter.type ?? TypeFactory.keyword("any"),
|
|
61
|
-
) ?? null,
|
|
62
|
-
required: props.parameter.questionToken === undefined,
|
|
63
|
-
}),
|
|
74
|
+
...common,
|
|
64
75
|
name: props.parameter.name.getText(),
|
|
65
76
|
index: props.index,
|
|
66
77
|
description: (symbol && CommentFactory.description(symbol)) ?? null,
|
|
@@ -69,7 +80,7 @@ export namespace SdkMetadataProgrammer {
|
|
|
69
80
|
};
|
|
70
81
|
|
|
71
82
|
const writeResponse = (props: {
|
|
72
|
-
context:
|
|
83
|
+
context: ISdkOperationTransformerContext;
|
|
73
84
|
generics: WeakMap<ts.Type, ts.Type>;
|
|
74
85
|
type: ts.Type | null;
|
|
75
86
|
}): IOperationMetadata.IResponse =>
|
|
@@ -79,7 +90,7 @@ export namespace SdkMetadataProgrammer {
|
|
|
79
90
|
});
|
|
80
91
|
|
|
81
92
|
const writeType = (p: {
|
|
82
|
-
context:
|
|
93
|
+
context: ISdkOperationTransformerContext;
|
|
83
94
|
generics: WeakMap<ts.Type, ts.Type>;
|
|
84
95
|
type: ts.Type | null;
|
|
85
96
|
required: boolean;
|
|
@@ -163,7 +174,8 @@ export namespace SdkMetadataProgrammer {
|
|
|
163
174
|
checker: ts.TypeChecker;
|
|
164
175
|
signature: ts.Signature | undefined;
|
|
165
176
|
}): ts.Type | null => {
|
|
166
|
-
const type: ts.Type | null =
|
|
177
|
+
const type: ts.Type | null =
|
|
178
|
+
(p.signature && p.checker.getReturnTypeOfSignature(p.signature)) ?? null;
|
|
167
179
|
if (type === null) return null;
|
|
168
180
|
else if (type.symbol?.name === "Promise") {
|
|
169
181
|
const generic: readonly ts.Type[] = p.checker.getTypeArguments(
|
|
@@ -175,38 +187,14 @@ export namespace SdkMetadataProgrammer {
|
|
|
175
187
|
};
|
|
176
188
|
}
|
|
177
189
|
|
|
178
|
-
const iterateVisited = (
|
|
190
|
+
const iterateVisited = (metadata: Metadata): Set<string> => {
|
|
179
191
|
const names: Set<string> = new Set();
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
for (const
|
|
185
|
-
|
|
186
|
-
iterate(alias.value);
|
|
187
|
-
}
|
|
188
|
-
for (const array of metadata.arrays) {
|
|
189
|
-
names.add(array.type.name);
|
|
190
|
-
iterate(array.type.value);
|
|
191
|
-
}
|
|
192
|
-
for (const tuple of metadata.tuples) {
|
|
193
|
-
names.add(tuple.type.name);
|
|
194
|
-
tuple.type.elements.map(iterate);
|
|
195
|
-
}
|
|
196
|
-
for (const object of metadata.objects) {
|
|
197
|
-
names.add(object.name);
|
|
198
|
-
object.properties.map((p) => {
|
|
199
|
-
iterate(p.key);
|
|
200
|
-
iterate(p.value);
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
if (metadata.escaped) {
|
|
204
|
-
iterate(metadata.escaped.original);
|
|
205
|
-
iterate(metadata.escaped.returns);
|
|
206
|
-
}
|
|
207
|
-
if (metadata.rest) iterate(metadata.rest);
|
|
208
|
-
};
|
|
209
|
-
iterate(metdata);
|
|
192
|
+
MetadataUtil.visit((m) => {
|
|
193
|
+
for (const alias of m.aliases) names.add(alias.name);
|
|
194
|
+
for (const array of m.arrays) names.add(array.type.name);
|
|
195
|
+
for (const tuple of m.tuples) names.add(tuple.type.name);
|
|
196
|
+
for (const object of m.objects) names.add(object.name);
|
|
197
|
+
})(metadata);
|
|
210
198
|
return names;
|
|
211
199
|
};
|
|
212
200
|
|
|
@@ -222,13 +210,3 @@ const join = ({
|
|
|
222
210
|
else if (Escaper.variable(key)) return `${object.name}.${key}`;
|
|
223
211
|
return `${object.name}[${JSON.stringify(key)}]`;
|
|
224
212
|
};
|
|
225
|
-
|
|
226
|
-
const getDescription = (signature: ts.Signature): string | null => {
|
|
227
|
-
const content: string[] = signature
|
|
228
|
-
.getDocumentationComment(undefined)
|
|
229
|
-
.filter((c) => c.kind === "text")
|
|
230
|
-
.map((c) => c.text);
|
|
231
|
-
return content.length
|
|
232
|
-
? content.map((line) => line.split("\r\n").join("\n")).join("\n")
|
|
233
|
-
: null;
|
|
234
|
-
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { HashSet, Singleton, hash } from "tstl";
|
|
2
3
|
import ts from "typescript";
|
|
3
4
|
import { LiteralFactory } from "typia/lib/factories/LiteralFactory";
|
|
4
5
|
import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
|
|
@@ -6,18 +7,16 @@ import { TypeFactory } from "typia/lib/factories/TypeFactory";
|
|
|
6
7
|
|
|
7
8
|
import { GenericAnalyzer } from "../analyses/GenericAnalyzer";
|
|
8
9
|
import { IOperationMetadata } from "./IOperationMetadata";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { ISdkOperationTransformerContext } from "./ISdkOperationTransformerContext";
|
|
11
|
+
import { SdkOperationProgrammer } from "./SdkOperationProgrammer";
|
|
11
12
|
|
|
12
|
-
export namespace
|
|
13
|
-
export const
|
|
13
|
+
export namespace SdkOperationTransformer {
|
|
14
|
+
export const iterateFile =
|
|
14
15
|
(checker: ts.TypeChecker) => (api: ts.TransformationContext) => {
|
|
15
|
-
const context:
|
|
16
|
+
const context: ISdkOperationTransformerContext = {
|
|
16
17
|
checker,
|
|
17
18
|
api,
|
|
18
|
-
collection:
|
|
19
|
-
replace: MetadataCollection.replace,
|
|
20
|
-
}),
|
|
19
|
+
collection: collection.get(),
|
|
21
20
|
};
|
|
22
21
|
return (file: ts.SourceFile): ts.SourceFile => {
|
|
23
22
|
if (file.isDeclarationFile === true) return file;
|
|
@@ -28,7 +27,7 @@ export namespace SdkTransformer {
|
|
|
28
27
|
file = ts.visitEachChild(
|
|
29
28
|
file,
|
|
30
29
|
(node) =>
|
|
31
|
-
|
|
30
|
+
iterateNode({
|
|
32
31
|
context,
|
|
33
32
|
visitor,
|
|
34
33
|
node,
|
|
@@ -61,20 +60,36 @@ export namespace SdkTransformer {
|
|
|
61
60
|
visited: HashSet<MethodKey>;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
const
|
|
65
|
-
context:
|
|
63
|
+
const iterateNode = (props: {
|
|
64
|
+
context: ISdkOperationTransformerContext;
|
|
66
65
|
visitor: IVisitor;
|
|
67
66
|
node: ts.Node;
|
|
68
67
|
}): ts.Node =>
|
|
69
|
-
ts.
|
|
68
|
+
ts.visitEachChild(
|
|
69
|
+
transformNode(props),
|
|
70
|
+
(child) =>
|
|
71
|
+
iterateNode({
|
|
72
|
+
...props,
|
|
73
|
+
node: child,
|
|
74
|
+
}),
|
|
75
|
+
props.context.api,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const transformNode = (props: {
|
|
79
|
+
context: ISdkOperationTransformerContext;
|
|
80
|
+
visitor: IVisitor;
|
|
81
|
+
node: ts.Node;
|
|
82
|
+
}): ts.Node => {
|
|
83
|
+
return ts.isClassDeclaration(props.node)
|
|
70
84
|
? transformClass({
|
|
71
85
|
...props,
|
|
72
86
|
node: props.node,
|
|
73
87
|
})
|
|
74
88
|
: props.node;
|
|
89
|
+
};
|
|
75
90
|
|
|
76
91
|
const transformClass = (props: {
|
|
77
|
-
context:
|
|
92
|
+
context: ISdkOperationTransformerContext;
|
|
78
93
|
visitor: IVisitor;
|
|
79
94
|
node: ts.ClassDeclaration;
|
|
80
95
|
}): ts.ClassDeclaration => {
|
|
@@ -82,6 +97,20 @@ export namespace SdkTransformer {
|
|
|
82
97
|
props.context.checker,
|
|
83
98
|
props.node,
|
|
84
99
|
);
|
|
100
|
+
|
|
101
|
+
// TO AVOID COMMENT COMPILATION BUG
|
|
102
|
+
const symbolDict: Map<string, ts.Symbol> = new Map();
|
|
103
|
+
const classType: ts.InterfaceType = props.context.checker.getTypeAtLocation(
|
|
104
|
+
props.node,
|
|
105
|
+
) as ts.InterfaceType;
|
|
106
|
+
for (const symbol of classType.getProperties()) {
|
|
107
|
+
const declaration: ts.Declaration | undefined = (symbol.declarations ||
|
|
108
|
+
[])[0];
|
|
109
|
+
if (!declaration || !ts.isMethodDeclaration(declaration)) continue;
|
|
110
|
+
const identifier = declaration.name;
|
|
111
|
+
if (!ts.isIdentifier(identifier)) continue;
|
|
112
|
+
symbolDict.set(identifier.escapedText.toString(), symbol);
|
|
113
|
+
}
|
|
85
114
|
return ts.factory.updateClassDeclaration(
|
|
86
115
|
props.node,
|
|
87
116
|
props.node.modifiers,
|
|
@@ -95,6 +124,7 @@ export namespace SdkTransformer {
|
|
|
95
124
|
generics,
|
|
96
125
|
class: props.node,
|
|
97
126
|
node: m,
|
|
127
|
+
symbol: symbolDict.get(m.name.getText()),
|
|
98
128
|
})
|
|
99
129
|
: m,
|
|
100
130
|
),
|
|
@@ -102,11 +132,12 @@ export namespace SdkTransformer {
|
|
|
102
132
|
};
|
|
103
133
|
|
|
104
134
|
const transformMethod = (props: {
|
|
105
|
-
context:
|
|
135
|
+
context: ISdkOperationTransformerContext;
|
|
106
136
|
visitor: IVisitor;
|
|
107
137
|
class: ts.ClassDeclaration;
|
|
108
138
|
generics: WeakMap<ts.Type, ts.Type>;
|
|
109
139
|
node: ts.MethodDeclaration;
|
|
140
|
+
symbol: ts.Symbol | undefined;
|
|
110
141
|
}): ts.MethodDeclaration => {
|
|
111
142
|
const decorators: readonly ts.Decorator[] | undefined = ts.getDecorators
|
|
112
143
|
? ts.getDecorators(props.node)
|
|
@@ -121,7 +152,13 @@ export namespace SdkTransformer {
|
|
|
121
152
|
if (props.visitor.visited.has(key)) return props.node;
|
|
122
153
|
else props.visitor.visited.insert(key);
|
|
123
154
|
|
|
124
|
-
const metadata: IOperationMetadata =
|
|
155
|
+
const metadata: IOperationMetadata = SdkOperationProgrammer.write({
|
|
156
|
+
...props,
|
|
157
|
+
exceptions: getExceptionTypes({
|
|
158
|
+
checker: props.context.checker,
|
|
159
|
+
decorators,
|
|
160
|
+
}),
|
|
161
|
+
});
|
|
125
162
|
return ts.factory.updateMethodDeclaration(
|
|
126
163
|
props.node,
|
|
127
164
|
[
|
|
@@ -150,6 +187,26 @@ export namespace SdkTransformer {
|
|
|
150
187
|
props.node.body,
|
|
151
188
|
);
|
|
152
189
|
};
|
|
190
|
+
|
|
191
|
+
const getExceptionTypes = (props: {
|
|
192
|
+
checker: ts.TypeChecker;
|
|
193
|
+
decorators: readonly ts.Decorator[];
|
|
194
|
+
}) =>
|
|
195
|
+
props.decorators
|
|
196
|
+
.map((deco) => {
|
|
197
|
+
if (false === ts.isCallExpression(deco.expression)) return null;
|
|
198
|
+
const signature: ts.Signature | undefined =
|
|
199
|
+
props.checker.getResolvedSignature(deco.expression);
|
|
200
|
+
if (signature === undefined) return null;
|
|
201
|
+
else if (!signature.declaration) return null;
|
|
202
|
+
const location: string = path.resolve(
|
|
203
|
+
signature.declaration.getSourceFile()?.fileName ?? "",
|
|
204
|
+
);
|
|
205
|
+
if (location.includes(TYPED_EXCEPTION_PATH) === false) return null;
|
|
206
|
+
else if (deco.expression.typeArguments?.length !== 1) return null;
|
|
207
|
+
return deco.expression.typeArguments[0];
|
|
208
|
+
})
|
|
209
|
+
.filter((t) => t !== null);
|
|
153
210
|
}
|
|
154
211
|
|
|
155
212
|
class MethodKey {
|
|
@@ -166,3 +223,18 @@ class MethodKey {
|
|
|
166
223
|
return hash(this.className, this.methodName);
|
|
167
224
|
}
|
|
168
225
|
}
|
|
226
|
+
|
|
227
|
+
const TYPED_EXCEPTION_PATH = path.join(
|
|
228
|
+
"@nestia",
|
|
229
|
+
"core",
|
|
230
|
+
"lib",
|
|
231
|
+
"decorators",
|
|
232
|
+
`TypedException.d.ts`,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const collection = new Singleton(
|
|
236
|
+
() =>
|
|
237
|
+
new MetadataCollection({
|
|
238
|
+
replace: MetadataCollection.replace,
|
|
239
|
+
}),
|
|
240
|
+
);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Metadata as metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
2
|
+
|
|
3
|
+
export namespace MetadataUtil {
|
|
4
|
+
export const visit = (closure: (m: metadata) => unknown) => {
|
|
5
|
+
const visited: WeakSet<metadata> = new WeakSet();
|
|
6
|
+
const iterate = (metadata: metadata): void => {
|
|
7
|
+
if (visited.has(metadata)) return;
|
|
8
|
+
visited.add(metadata);
|
|
9
|
+
closure(metadata);
|
|
10
|
+
for (const alias of metadata.aliases) iterate(alias.value);
|
|
11
|
+
for (const array of metadata.arrays) iterate(array.type.value);
|
|
12
|
+
for (const tuple of metadata.tuples) tuple.type.elements.map(iterate);
|
|
13
|
+
for (const object of metadata.objects)
|
|
14
|
+
object.properties.forEach((p) => {
|
|
15
|
+
iterate(p.key);
|
|
16
|
+
iterate(p.value);
|
|
17
|
+
});
|
|
18
|
+
if (metadata.escaped) {
|
|
19
|
+
iterate(metadata.escaped.original);
|
|
20
|
+
iterate(metadata.escaped.returns);
|
|
21
|
+
}
|
|
22
|
+
if (metadata.rest) iterate(metadata.rest);
|
|
23
|
+
};
|
|
24
|
+
return iterate;
|
|
25
|
+
};
|
|
26
|
+
}
|
package/src/utils/StringUtil.ts
CHANGED
|
@@ -6,4 +6,12 @@ export namespace StringUtil {
|
|
|
6
6
|
(keep: string[]) =>
|
|
7
7
|
(change: string): string =>
|
|
8
8
|
keep.includes(change) ? escapeDuplicate(keep)(`_${change}`) : change;
|
|
9
|
+
|
|
10
|
+
export const isImplicit = (str: string) =>
|
|
11
|
+
str === "object" ||
|
|
12
|
+
str === "__type" ||
|
|
13
|
+
str === "__object" ||
|
|
14
|
+
str.startsWith("__type.") ||
|
|
15
|
+
str.startsWith("__object.") ||
|
|
16
|
+
str.includes("readonly [");
|
|
9
17
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
|
|
2
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
3
|
+
import { MetadataArrayType } from "typia/lib/schemas/metadata/MetadataArrayType";
|
|
4
|
+
|
|
5
|
+
export namespace HttpHeadersValidator {
|
|
6
|
+
export const validate = (
|
|
7
|
+
meta: Metadata,
|
|
8
|
+
explore: MetadataFactory.IExplore,
|
|
9
|
+
): string[] => {
|
|
10
|
+
const errors: string[] = [];
|
|
11
|
+
const insert = (msg: string) => errors.push(msg);
|
|
12
|
+
|
|
13
|
+
if (explore.top === true) {
|
|
14
|
+
const expected: number =
|
|
15
|
+
meta.atomics.length +
|
|
16
|
+
meta.templates.length +
|
|
17
|
+
meta.constants.map((c) => c.values.length).reduce((a, b) => a + b, 0) +
|
|
18
|
+
meta.arrays.length;
|
|
19
|
+
if (meta.size() !== expected)
|
|
20
|
+
insert("Only atomic or array of atomic types are allowed.");
|
|
21
|
+
} else if (
|
|
22
|
+
explore.nested !== null &&
|
|
23
|
+
explore.nested instanceof MetadataArrayType
|
|
24
|
+
) {
|
|
25
|
+
const expected: number =
|
|
26
|
+
meta.atomics.length +
|
|
27
|
+
meta.templates.length +
|
|
28
|
+
meta.constants.map((c) => c.values.length).reduce((a, b) => a + b, 0);
|
|
29
|
+
if (meta.size() !== expected)
|
|
30
|
+
insert("Only atomic types are allowed in array.");
|
|
31
|
+
}
|
|
32
|
+
return errors;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
|
|
2
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
3
|
+
import { MetadataArrayType } from "typia/lib/schemas/metadata/MetadataArrayType";
|
|
4
|
+
|
|
5
|
+
export namespace HttpQueryValidator {
|
|
6
|
+
export const validate = (
|
|
7
|
+
meta: Metadata,
|
|
8
|
+
explore: MetadataFactory.IExplore,
|
|
9
|
+
): string[] => {
|
|
10
|
+
const errors: string[] = [];
|
|
11
|
+
const insert = (msg: string) => errors.push(msg);
|
|
12
|
+
|
|
13
|
+
if (explore.top === true) {
|
|
14
|
+
const expected: number =
|
|
15
|
+
meta.atomics.length +
|
|
16
|
+
meta.templates.length +
|
|
17
|
+
meta.constants.map((c) => c.values.length).reduce((a, b) => a + b, 0) +
|
|
18
|
+
meta.arrays.length;
|
|
19
|
+
if (meta.size() !== expected)
|
|
20
|
+
insert("Only atomic or array of atomic types are allowed.");
|
|
21
|
+
} else if (
|
|
22
|
+
explore.nested !== null &&
|
|
23
|
+
explore.nested instanceof MetadataArrayType
|
|
24
|
+
) {
|
|
25
|
+
const expected: number =
|
|
26
|
+
meta.atomics.length +
|
|
27
|
+
meta.templates.length +
|
|
28
|
+
meta.constants.map((c) => c.values.length).reduce((a, b) => a + b, 0);
|
|
29
|
+
if (meta.size() !== expected)
|
|
30
|
+
insert("Only atomic types are allowed in array.");
|
|
31
|
+
}
|
|
32
|
+
return errors;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ISdkTransformerContext.js","sourceRoot":"","sources":["../../src/transformers/ISdkTransformerContext.ts"],"names":[],"mappings":""}
|