@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.
Files changed (135) hide show
  1. package/assets/bundle/api/Resolved.ts +1 -0
  2. package/assets/bundle/api/module.ts +1 -0
  3. package/lib/NestiaSdkApplication.d.ts +1 -0
  4. package/lib/NestiaSdkApplication.js +24 -26
  5. package/lib/NestiaSdkApplication.js.map +1 -1
  6. package/lib/analyses/ReflectControllerAnalyzer.js +2 -0
  7. package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -1
  8. package/lib/analyses/ReflectHttpOperationAnalyzer.js +10 -1
  9. package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -1
  10. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.d.ts +15 -0
  11. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js +50 -0
  12. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js.map +1 -0
  13. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js +14 -9
  14. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js.map +1 -1
  15. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js +2 -1
  16. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js.map +1 -1
  17. package/lib/analyses/ReflectWebSocketOperationAnalyzer.js +3 -2
  18. package/lib/analyses/ReflectWebSocketOperationAnalyzer.js.map +1 -1
  19. package/lib/analyses/TypedHttpRouteAnalyzer.js +3 -1
  20. package/lib/analyses/TypedHttpRouteAnalyzer.js.map +1 -1
  21. package/lib/executable/internal/NestiaSdkCommand.d.ts +1 -0
  22. package/lib/executable/internal/NestiaSdkCommand.js +3 -2
  23. package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
  24. package/lib/executable/sdk.js +3 -0
  25. package/lib/executable/sdk.js.map +1 -1
  26. package/lib/generates/CloneGenerator.d.ts +4 -0
  27. package/lib/generates/CloneGenerator.js +62 -60
  28. package/lib/generates/CloneGenerator.js.map +1 -1
  29. package/lib/generates/SdkGenerator.js +4 -3
  30. package/lib/generates/SdkGenerator.js.map +1 -1
  31. package/lib/generates/SwaggerGenerator.js +60 -8
  32. package/lib/generates/SwaggerGenerator.js.map +1 -1
  33. package/lib/generates/internal/E2eFileProgrammer.js +11 -3
  34. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  35. package/lib/generates/internal/ImportDictionary.js +1 -1
  36. package/lib/generates/internal/ImportDictionary.js.map +1 -1
  37. package/lib/generates/internal/SdkAliasCollection.d.ts +5 -1
  38. package/lib/generates/internal/SdkAliasCollection.js +24 -8
  39. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  40. package/lib/generates/internal/SdkFileProgrammer.js +1 -1
  41. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  42. package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +11 -0
  43. package/lib/generates/internal/SdkHttpCloneProgrammer.js +75 -142
  44. package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
  45. package/lib/generates/internal/SdkHttpCloneReferencer.d.ts +4 -0
  46. package/lib/generates/internal/SdkHttpCloneReferencer.js +62 -0
  47. package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -0
  48. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +26 -13
  49. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  50. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +17 -8
  51. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
  52. package/lib/generates/internal/SdkHttpRouteProgrammer.js +2 -2
  53. package/lib/generates/internal/SdkHttpRouteProgrammer.js.map +1 -1
  54. package/lib/generates/internal/SdkHttpSimulationProgrammer.js +8 -5
  55. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
  56. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +12 -5
  57. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
  58. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +3 -3
  59. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  60. package/lib/generates/internal/SwaggerOperationComposer.js +19 -1
  61. package/lib/generates/internal/SwaggerOperationComposer.js.map +1 -1
  62. package/lib/generates/internal/SwaggerOperationParameterComposer.js +3 -3
  63. package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
  64. package/lib/structures/IReflectHttpOperation.d.ts +1 -1
  65. package/lib/structures/IReflectHttpOperationException.d.ts +2 -2
  66. package/lib/structures/ITypedApplication.d.ts +2 -0
  67. package/lib/transform.js +2 -2
  68. package/lib/transform.js.map +1 -1
  69. package/lib/transformers/IOperationMetadata.d.ts +6 -1
  70. package/lib/transformers/{ISdkTransformerContext.d.ts → ISdkOperationTransformerContext.d.ts} +1 -1
  71. package/lib/transformers/{ISdkTransformerContext.js → ISdkOperationTransformerContext.js} +1 -1
  72. package/lib/transformers/ISdkOperationTransformerContext.js.map +1 -0
  73. package/lib/transformers/SdkOperationProgrammer.d.ts +13 -0
  74. package/lib/transformers/{SdkMetadataProgrammer.js → SdkOperationProgrammer.js} +36 -55
  75. package/lib/transformers/SdkOperationProgrammer.js.map +1 -0
  76. package/lib/transformers/SdkOperationTransformer.d.ts +4 -0
  77. package/lib/transformers/{SdkTransformer.js → SdkOperationTransformer.js} +56 -16
  78. package/lib/transformers/SdkOperationTransformer.js.map +1 -0
  79. package/lib/utils/MetadataUtil.d.ts +4 -0
  80. package/lib/utils/MetadataUtil.js +34 -0
  81. package/lib/utils/MetadataUtil.js.map +1 -0
  82. package/lib/utils/StringUtil.d.ts +1 -0
  83. package/lib/utils/StringUtil.js +6 -0
  84. package/lib/utils/StringUtil.js.map +1 -1
  85. package/lib/validators/HttpHeadersValidator.d.ts +5 -0
  86. package/lib/validators/HttpHeadersValidator.js +29 -0
  87. package/lib/validators/HttpHeadersValidator.js.map +1 -0
  88. package/lib/validators/HttpQueryValidator.d.ts +5 -0
  89. package/lib/validators/HttpQueryValidator.js +29 -0
  90. package/lib/validators/HttpQueryValidator.js.map +1 -0
  91. package/package.json +8 -8
  92. package/src/NestiaSdkApplication.ts +20 -30
  93. package/src/analyses/ReflectControllerAnalyzer.ts +2 -0
  94. package/src/analyses/ReflectHttpOperationAnalyzer.ts +10 -1
  95. package/src/analyses/ReflectHttpOperationExceptionAnalyzer.ts +71 -0
  96. package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +37 -8
  97. package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +8 -0
  98. package/src/analyses/ReflectWebSocketOperationAnalyzer.ts +10 -2
  99. package/src/analyses/TypedHttpRouteAnalyzer.ts +4 -1
  100. package/src/executable/internal/NestiaSdkCommand.ts +3 -2
  101. package/src/executable/sdk.ts +2 -0
  102. package/src/generates/CloneGenerator.ts +61 -60
  103. package/src/generates/SdkGenerator.ts +3 -3
  104. package/src/generates/SwaggerGenerator.ts +84 -10
  105. package/src/generates/internal/E2eFileProgrammer.ts +13 -3
  106. package/src/generates/internal/ImportDictionary.ts +1 -1
  107. package/src/generates/internal/SdkAliasCollection.ts +32 -10
  108. package/src/generates/internal/SdkFileProgrammer.ts +1 -1
  109. package/src/generates/internal/SdkHttpCloneProgrammer.ts +118 -144
  110. package/src/generates/internal/SdkHttpCloneReferencer.ts +71 -0
  111. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +31 -16
  112. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +252 -230
  113. package/src/generates/internal/SdkHttpRouteProgrammer.ts +2 -2
  114. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +30 -24
  115. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +14 -6
  116. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +6 -8
  117. package/src/generates/internal/SwaggerOperationComposer.ts +25 -0
  118. package/src/generates/internal/SwaggerOperationParameterComposer.ts +3 -0
  119. package/src/structures/IReflectHttpOperation.ts +1 -4
  120. package/src/structures/IReflectHttpOperationException.ts +2 -2
  121. package/src/structures/ITypedApplication.ts +3 -0
  122. package/src/transform.ts +2 -2
  123. package/src/transformers/IOperationMetadata.ts +7 -1
  124. package/src/transformers/{ISdkTransformerContext.ts → ISdkOperationTransformerContext.ts} +1 -1
  125. package/src/transformers/{SdkMetadataProgrammer.ts → SdkOperationProgrammer.ts} +40 -62
  126. package/src/transformers/{SdkTransformer.ts → SdkOperationTransformer.ts} +88 -16
  127. package/src/utils/MetadataUtil.ts +26 -0
  128. package/src/utils/StringUtil.ts +8 -0
  129. package/src/validators/HttpHeadersValidator.ts +34 -0
  130. package/src/validators/HttpQueryValidator.ts +34 -0
  131. package/lib/transformers/ISdkTransformerContext.js.map +0 -1
  132. package/lib/transformers/SdkMetadataProgrammer.d.ts +0 -11
  133. package/lib/transformers/SdkMetadataProgrammer.js.map +0 -1
  134. package/lib/transformers/SdkTransformer.d.ts +0 -4
  135. 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(acceptor.type.typeArguments?.[1]!),
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(acceptor.type.typeArguments?.[2]!),
100
+ SdkAliasCollection.name({
101
+ type: acceptor.type.typeArguments?.[1]!,
102
+ }),
95
103
  );
96
- if (query) declare("Query", SdkAliasCollection.name(query.type));
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.type)
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
- ts.factory.createIdentifier(
168
- importer.external({
169
- type: true,
170
- library: "tgrid",
171
- instance: "Driver",
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: any;
12
- examples: Record<string, any>;
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 { SdkTransformer } from "./transformers/SdkTransformer";
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
- SdkTransformer.transformFile(program.getTypeChecker());
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: Record<string, IOperationMetadata.IResponse>;
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 ISdkTransformerContext {
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 { ISdkTransformerContext } from "./ISdkTransformerContext";
14
+ import { ISdkOperationTransformerContext } from "./ISdkOperationTransformerContext";
14
15
 
15
- export namespace SdkMetadataProgrammer {
16
+ export namespace SdkOperationProgrammer {
16
17
  export interface IProps {
17
- context: ISdkTransformerContext;
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: {}, // @todo
42
- description: (signature && getDescription(signature)) ?? null,
43
- jsDocTags: signature?.getJsDocTags() ?? [],
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: ISdkTransformerContext;
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
- ...writeType({
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: ISdkTransformerContext;
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: ISdkTransformerContext;
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 = p.signature?.getReturnType() ?? 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 = (metdata: Metadata): Set<string> => {
190
+ const iterateVisited = (metadata: Metadata): Set<string> => {
179
191
  const names: Set<string> = new Set();
180
- const visited: WeakSet<Metadata> = new WeakSet();
181
- const iterate = (metadata: Metadata): void => {
182
- if (visited.has(metadata)) return;
183
- visited.add(metadata);
184
- for (const alias of metadata.aliases) {
185
- names.add(alias.name);
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 { HashSet, hash } from "tstl";
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 { ISdkTransformerContext } from "./ISdkTransformerContext";
10
- import { SdkMetadataProgrammer } from "./SdkMetadataProgrammer";
10
+ import { ISdkOperationTransformerContext } from "./ISdkOperationTransformerContext";
11
+ import { SdkOperationProgrammer } from "./SdkOperationProgrammer";
11
12
 
12
- export namespace SdkTransformer {
13
- export const transformFile =
13
+ export namespace SdkOperationTransformer {
14
+ export const iterateFile =
14
15
  (checker: ts.TypeChecker) => (api: ts.TransformationContext) => {
15
- const context: ISdkTransformerContext = {
16
+ const context: ISdkOperationTransformerContext = {
16
17
  checker,
17
18
  api,
18
- collection: new MetadataCollection({
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
- transformNode({
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 transformNode = (props: {
65
- context: ISdkTransformerContext;
63
+ const iterateNode = (props: {
64
+ context: ISdkOperationTransformerContext;
66
65
  visitor: IVisitor;
67
66
  node: ts.Node;
68
67
  }): ts.Node =>
69
- ts.isClassDeclaration(props.node)
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: ISdkTransformerContext;
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: ISdkTransformerContext;
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 = SdkMetadataProgrammer.write(props);
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
+ }
@@ -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":""}