@nestia/sdk 12.0.0-dev.20260601.1 → 12.0.0-dev.20260612.2

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 (209) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +93 -93
  3. package/assets/bundle/api/HttpError.ts +1 -1
  4. package/assets/bundle/api/IConnection.ts +1 -1
  5. package/assets/bundle/api/Primitive.ts +1 -1
  6. package/assets/bundle/api/Resolved.ts +1 -1
  7. package/assets/bundle/api/index.ts +4 -4
  8. package/assets/bundle/api/module.ts +6 -6
  9. package/assets/bundle/distribute/README.md +37 -37
  10. package/assets/bundle/distribute/package.json +28 -28
  11. package/assets/bundle/distribute/tsconfig.json +109 -109
  12. package/assets/bundle/e2e/index.ts +42 -42
  13. package/assets/config/nestia.config.ts +97 -97
  14. package/lib/NestiaSdkApplication.js +29 -7
  15. package/lib/NestiaSdkApplication.js.map +1 -1
  16. package/lib/NestiaSwaggerComposer.js +21 -13
  17. package/lib/NestiaSwaggerComposer.js.map +1 -1
  18. package/lib/analyses/AccessorAnalyzer.d.ts +4 -1
  19. package/lib/analyses/AccessorAnalyzer.js.map +1 -1
  20. package/lib/analyses/ConfigAnalyzer.js +1 -1
  21. package/lib/analyses/PathAnalyzer.d.ts +18 -3
  22. package/lib/analyses/PathAnalyzer.js +32 -0
  23. package/lib/analyses/PathAnalyzer.js.map +1 -1
  24. package/lib/analyses/ReflectControllerAnalyzer.js +3 -2
  25. package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -1
  26. package/lib/analyses/ReflectHttpOperationAnalyzer.d.ts +1 -1
  27. package/lib/analyses/ReflectHttpOperationAnalyzer.js +1 -1
  28. package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -1
  29. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.d.ts +1 -1
  30. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js +53 -20
  31. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js.map +1 -1
  32. package/lib/analyses/ReflectMcpOperationAnalyzer.d.ts +14 -0
  33. package/lib/analyses/ReflectMcpOperationAnalyzer.js +79 -0
  34. package/lib/analyses/ReflectMcpOperationAnalyzer.js.map +1 -0
  35. package/lib/analyses/TypedMcpRouteAnalyzer.d.ts +9 -0
  36. package/lib/analyses/TypedMcpRouteAnalyzer.js +31 -0
  37. package/lib/analyses/TypedMcpRouteAnalyzer.js.map +1 -0
  38. package/lib/executable/internal/NestiaConfigLoader.js +5 -1
  39. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  40. package/lib/executable/internal/NestiaSdkCommand.js +30 -14
  41. package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
  42. package/lib/executable/internal/NestiaSdkWatcher.d.ts +10 -0
  43. package/lib/executable/internal/NestiaSdkWatcher.js +322 -0
  44. package/lib/executable/internal/NestiaSdkWatcher.js.map +1 -0
  45. package/lib/executable/sdk.js +12 -12
  46. package/lib/executable/sdk.js.map +1 -1
  47. package/lib/generates/CloneGenerator.js +4 -2
  48. package/lib/generates/CloneGenerator.js.map +1 -1
  49. package/lib/generates/SdkGenerator.js +50 -1
  50. package/lib/generates/SdkGenerator.js.map +1 -1
  51. package/lib/generates/SwaggerGenerator.js +18 -2
  52. package/lib/generates/SwaggerGenerator.js.map +1 -1
  53. package/lib/generates/internal/E2eFileProgrammer.js +3 -1
  54. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  55. package/lib/generates/internal/ImportDictionary.d.ts +1 -0
  56. package/lib/generates/internal/ImportDictionary.js +9 -4
  57. package/lib/generates/internal/ImportDictionary.js.map +1 -1
  58. package/lib/generates/internal/SdkAliasCollection.d.ts +2 -0
  59. package/lib/generates/internal/SdkAliasCollection.js +11 -2
  60. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  61. package/lib/generates/internal/SdkDistributionComposer.d.ts +1 -0
  62. package/lib/generates/internal/SdkDistributionComposer.js +3 -0
  63. package/lib/generates/internal/SdkDistributionComposer.js.map +1 -1
  64. package/lib/generates/internal/SdkFileProgrammer.js +4 -1
  65. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  66. package/lib/generates/internal/SdkHttpCloneReferencer.d.ts +1 -1
  67. package/lib/generates/internal/SdkHttpCloneReferencer.js +42 -9
  68. package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -1
  69. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +3 -4
  70. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  71. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +2 -1
  72. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
  73. package/lib/generates/internal/SdkHttpSimulationProgrammer.js +6 -3
  74. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
  75. package/lib/generates/internal/SdkMcpRouteProgrammer.d.ts +15 -0
  76. package/lib/generates/internal/SdkMcpRouteProgrammer.js +148 -0
  77. package/lib/generates/internal/SdkMcpRouteProgrammer.js.map +1 -0
  78. package/lib/generates/internal/SdkRouteDirectory.d.ts +2 -1
  79. package/lib/generates/internal/SdkRouteDirectory.js.map +1 -1
  80. package/lib/generates/internal/SdkWebSocketCloneProgrammer.d.ts +6 -0
  81. package/lib/generates/internal/SdkWebSocketCloneProgrammer.js +283 -0
  82. package/lib/generates/internal/SdkWebSocketCloneProgrammer.js.map +1 -0
  83. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +11 -9
  84. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  85. package/lib/generates/internal/SwaggerOperationParameterComposer.js +10 -2
  86. package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
  87. package/lib/generates/internal/SwaggerOperationResponseComposer.d.ts +1 -1
  88. package/lib/generates/internal/SwaggerOperationResponseComposer.js +6 -1
  89. package/lib/generates/internal/SwaggerOperationResponseComposer.js.map +1 -1
  90. package/lib/generates/internal/SwaggerReadonlyArrayEmender.d.ts +9 -0
  91. package/lib/generates/internal/SwaggerReadonlyArrayEmender.js +174 -0
  92. package/lib/generates/internal/SwaggerReadonlyArrayEmender.js.map +1 -0
  93. package/lib/structures/INestiaSdkInput.d.ts +9 -2
  94. package/lib/structures/IReflectController.d.ts +2 -1
  95. package/lib/structures/IReflectHttpOperationSuccess.d.ts +4 -2
  96. package/lib/structures/IReflectMcpOperation.d.ts +35 -0
  97. package/lib/structures/IReflectMcpOperation.js +3 -0
  98. package/lib/structures/IReflectMcpOperation.js.map +1 -0
  99. package/lib/structures/IReflectMcpOperationParameter.d.ts +19 -0
  100. package/lib/structures/IReflectMcpOperationParameter.js +3 -0
  101. package/lib/structures/IReflectMcpOperationParameter.js.map +1 -0
  102. package/lib/structures/ITypedApplication.d.ts +2 -1
  103. package/lib/structures/ITypedHttpRouteSuccess.d.ts +3 -1
  104. package/lib/structures/ITypedMcpRoute.d.ts +31 -0
  105. package/lib/structures/ITypedMcpRoute.js +3 -0
  106. package/lib/structures/ITypedMcpRoute.js.map +1 -0
  107. package/lib/utils/HttpResponseContentTypeUtil.d.ts +5 -0
  108. package/lib/utils/HttpResponseContentTypeUtil.js +22 -0
  109. package/lib/utils/HttpResponseContentTypeUtil.js.map +1 -0
  110. package/native/go.mod +52 -52
  111. package/native/go.sum +84 -54
  112. package/native/sdk/register.go +322 -165
  113. package/native/sdk/sdk.go +17 -17
  114. package/native/sdk/sdk_metadata_json.go +327 -327
  115. package/native/sdk/sdk_transform.go +1879 -1549
  116. package/package.json +11 -9
  117. package/src/INestiaConfig.ts +267 -267
  118. package/src/NestiaSdkApplication.ts +39 -8
  119. package/src/NestiaSwaggerComposer.ts +153 -142
  120. package/src/analyses/AccessorAnalyzer.ts +64 -67
  121. package/src/analyses/ConfigAnalyzer.ts +330 -330
  122. package/src/analyses/ImportAnalyzer.ts +92 -92
  123. package/src/analyses/PathAnalyzer.ts +130 -69
  124. package/src/analyses/ReflectControllerAnalyzer.ts +112 -105
  125. package/src/analyses/ReflectHttpOperationAnalyzer.ts +183 -183
  126. package/src/analyses/ReflectHttpOperationExceptionAnalyzer.ts +90 -90
  127. package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +350 -350
  128. package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +163 -130
  129. package/src/analyses/ReflectMcpOperationAnalyzer.ts +124 -0
  130. package/src/analyses/ReflectMetadataAnalyzer.ts +44 -44
  131. package/src/analyses/SecurityAnalyzer.ts +25 -25
  132. package/src/analyses/TypedMcpRouteAnalyzer.ts +34 -0
  133. package/src/decorators/OperationMetadata.ts +29 -29
  134. package/src/executable/internal/CommandParser.ts +15 -15
  135. package/src/executable/internal/NestiaConfigLoader.ts +451 -446
  136. package/src/executable/internal/NestiaSdkCommand.ts +124 -106
  137. package/src/executable/internal/NestiaSdkWatcher.ts +342 -0
  138. package/src/executable/sdk.ts +90 -88
  139. package/src/generates/CloneGenerator.ts +73 -66
  140. package/src/generates/E2eGenerator.ts +32 -32
  141. package/src/generates/SdkGenerator.ts +176 -118
  142. package/src/generates/SwaggerGenerator.ts +342 -310
  143. package/src/generates/internal/E2eFileProgrammer.ts +240 -233
  144. package/src/generates/internal/FilePrinter.ts +65 -65
  145. package/src/generates/internal/ImportDictionary.ts +209 -204
  146. package/src/generates/internal/SdkAliasCollection.ts +274 -261
  147. package/src/generates/internal/SdkDistributionComposer.ts +123 -116
  148. package/src/generates/internal/SdkFileProgrammer.ts +116 -112
  149. package/src/generates/internal/SdkHttpCloneProgrammer.ts +126 -126
  150. package/src/generates/internal/SdkHttpCloneReferencer.ts +131 -77
  151. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +301 -301
  152. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +520 -510
  153. package/src/generates/internal/SdkHttpParameterProgrammer.ts +165 -165
  154. package/src/generates/internal/SdkHttpRouteProgrammer.ts +109 -109
  155. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +331 -314
  156. package/src/generates/internal/SdkImportWizard.ts +62 -62
  157. package/src/generates/internal/SdkMcpRouteProgrammer.ts +452 -0
  158. package/src/generates/internal/SdkRouteDirectory.ts +21 -18
  159. package/src/generates/internal/SdkTypeTagProgrammer.ts +114 -114
  160. package/src/generates/internal/SdkWebSocketCloneProgrammer.ts +319 -0
  161. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +389 -389
  162. package/src/generates/internal/SdkWebSocketParameterProgrammer.ts +89 -89
  163. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +331 -323
  164. package/src/generates/internal/SwaggerDescriptionComposer.ts +64 -64
  165. package/src/generates/internal/SwaggerOperationComposer.ts +119 -119
  166. package/src/generates/internal/SwaggerOperationParameterComposer.ts +175 -162
  167. package/src/generates/internal/SwaggerOperationResponseComposer.ts +115 -110
  168. package/src/generates/internal/SwaggerReadonlyArrayEmender.ts +262 -0
  169. package/src/index.ts +4 -4
  170. package/src/internal/legacy.ts +492 -492
  171. package/src/module.ts +4 -4
  172. package/src/structures/INestiaProject.ts +10 -10
  173. package/src/structures/INestiaSdkInput.ts +27 -20
  174. package/src/structures/IOperationMetadata.ts +41 -41
  175. package/src/structures/IReflectController.ts +18 -15
  176. package/src/structures/IReflectHttpOperation.ts +26 -26
  177. package/src/structures/IReflectHttpOperationException.ts +18 -18
  178. package/src/structures/IReflectHttpOperationParameter.ts +79 -79
  179. package/src/structures/IReflectHttpOperationSuccess.ts +18 -21
  180. package/src/structures/IReflectImport.ts +6 -6
  181. package/src/structures/IReflectMcpOperation.ts +38 -0
  182. package/src/structures/IReflectMcpOperationParameter.ts +27 -0
  183. package/src/structures/IReflectOperationError.ts +26 -26
  184. package/src/structures/IReflectType.ts +4 -4
  185. package/src/structures/IReflectWebSocketOperation.ts +17 -17
  186. package/src/structures/ITypedApplication.ts +12 -11
  187. package/src/structures/ITypedHttpRoute.ts +41 -41
  188. package/src/structures/ITypedHttpRouteException.ts +15 -15
  189. package/src/structures/ITypedHttpRouteParameter.ts +41 -41
  190. package/src/structures/ITypedHttpRouteSuccess.ts +18 -22
  191. package/src/structures/ITypedMcpRoute.ts +33 -0
  192. package/src/structures/ITypedWebSocketRoute.ts +24 -24
  193. package/src/structures/ITypedWebSocketRouteParameter.ts +3 -3
  194. package/src/transform.ts +59 -59
  195. package/src/typings/get-function-location.d.ts +7 -7
  196. package/src/utils/ArrayUtil.ts +26 -26
  197. package/src/utils/EmittedJavaScriptPatcher.ts +88 -88
  198. package/src/utils/FileRetriever.ts +22 -22
  199. package/src/utils/HttpResponseContentTypeUtil.ts +30 -0
  200. package/src/utils/MapUtil.ts +14 -14
  201. package/src/utils/PathUtil.ts +10 -10
  202. package/src/utils/SourceFinder.ts +63 -63
  203. package/src/utils/StringUtil.ts +17 -17
  204. package/src/utils/TsConfigReader.ts +108 -108
  205. package/src/utils/TtscExecutor.ts +68 -68
  206. package/src/utils/VersioningStrategy.ts +28 -28
  207. package/src/validators/HttpHeadersValidator.ts +11 -11
  208. package/src/validators/HttpQueryValidator.ts +11 -11
  209. package/src/validators/TextPlainValidator.ts +17 -17
@@ -1,4 +1,3 @@
1
- import { IMetadataDictionary } from "./internal/legacy";
2
1
  import fs from "fs";
3
2
  import path from "path";
4
3
  import { HashSet, Pair, TreeMap } from "tstl";
@@ -9,17 +8,20 @@ import { ConfigAnalyzer } from "./analyses/ConfigAnalyzer";
9
8
  import { PathAnalyzer } from "./analyses/PathAnalyzer";
10
9
  import { ReflectControllerAnalyzer } from "./analyses/ReflectControllerAnalyzer";
11
10
  import { TypedHttpRouteAnalyzer } from "./analyses/TypedHttpRouteAnalyzer";
11
+ import { TypedMcpRouteAnalyzer } from "./analyses/TypedMcpRouteAnalyzer";
12
12
  import { TypedWebSocketRouteAnalyzer } from "./analyses/TypedWebSocketRouteAnalyzer";
13
13
  import { E2eGenerator } from "./generates/E2eGenerator";
14
14
  import { SdkGenerator } from "./generates/SdkGenerator";
15
15
  import { SwaggerGenerator } from "./generates/SwaggerGenerator";
16
+ import { IMetadataDictionary } from "./internal/legacy";
16
17
  import { INestiaProject } from "./structures/INestiaProject";
18
+ import { IOperationMetadata } from "./structures/IOperationMetadata";
17
19
  import { IReflectController } from "./structures/IReflectController";
18
20
  import { IReflectOperationError } from "./structures/IReflectOperationError";
19
21
  import { ITypedApplication } from "./structures/ITypedApplication";
20
22
  import { ITypedHttpRoute } from "./structures/ITypedHttpRoute";
23
+ import { ITypedMcpRoute } from "./structures/ITypedMcpRoute";
21
24
  import { ITypedWebSocketRoute } from "./structures/ITypedWebSocketRoute";
22
- import { IOperationMetadata } from "./structures/IOperationMetadata";
23
25
  import { StringUtil } from "./utils/StringUtil";
24
26
  import { VersioningStrategy } from "./utils/VersioningStrategy";
25
27
 
@@ -161,7 +163,11 @@ export class NestiaSdkApplication {
161
163
  const set: HashSet<Pair<string, string>> = new HashSet();
162
164
  for (const controller of controllers)
163
165
  for (const controllerPath of controller.paths)
164
- for (const operation of controller.operations)
166
+ for (const operation of controller.operations) {
167
+ if (operation.protocol === "mcp") {
168
+ set.insert(new Pair(`mcp:${operation.toolName}`, "mcp"));
169
+ continue;
170
+ }
165
171
  for (const operationPath of operation.paths)
166
172
  set.insert(
167
173
  new Pair(
@@ -169,6 +175,7 @@ export class NestiaSdkApplication {
169
175
  operation.protocol === "http" ? operation.method : "",
170
176
  ),
171
177
  );
178
+ }
172
179
  return set.size();
173
180
  })();
174
181
 
@@ -179,7 +186,9 @@ export class NestiaSdkApplication {
179
186
  .map(
180
187
  (c) =>
181
188
  c.paths.length *
182
- c.operations.map((f) => f.paths.length).reduce((a, b) => a + b, 0),
189
+ c.operations
190
+ .map((f) => (f.protocol === "mcp" ? 1 : f.paths.length))
191
+ .reduce((a, b) => a + b, 0),
183
192
  )
184
193
  .reduce((a, b) => a + b, 0)}`,
185
194
  );
@@ -194,10 +203,20 @@ export class NestiaSdkApplication {
194
203
  TypedHttpRouteAnalyzer.dictionary(controllers);
195
204
 
196
205
  // CONVERT TO TYPED OPERATIONS
197
- const globalPrefix: string = project.input.globalPrefix?.prefix ?? "";
198
- const routes: Array<ITypedHttpRoute | ITypedWebSocketRoute> = [];
206
+ const routes: Array<
207
+ ITypedHttpRoute | ITypedWebSocketRoute | ITypedMcpRoute
208
+ > = [];
199
209
  for (const c of controllers)
200
210
  for (const o of c.operations) {
211
+ if (o.protocol === "mcp") {
212
+ routes.push(
213
+ ...TypedMcpRouteAnalyzer.analyze({
214
+ controller: c,
215
+ operation: o,
216
+ }),
217
+ );
218
+ continue;
219
+ }
201
220
  const pathList: Set<string> = new Set();
202
221
  const versions: string[] = VersioningStrategy.merge(project)([
203
222
  ...(c.versions ?? []),
@@ -206,10 +225,22 @@ export class NestiaSdkApplication {
206
225
  for (const v of versions)
207
226
  for (const prefix of wrapPaths(c.prefixes))
208
227
  for (const cPath of wrapPaths(c.paths))
209
- for (const filePath of wrapPaths(o.paths))
228
+ for (const filePath of wrapPaths(o.paths)) {
229
+ const localPath: string = PathAnalyzer.join(
230
+ prefix,
231
+ cPath,
232
+ filePath,
233
+ );
210
234
  pathList.add(
211
- PathAnalyzer.join(globalPrefix, v, prefix, cPath, filePath),
235
+ PathAnalyzer.joinWithGlobalPrefix({
236
+ globalPrefix: project.input.globalPrefix?.prefix ?? "",
237
+ exclude: project.input.globalPrefix?.exclude,
238
+ excludePath: localPath,
239
+ method: o.protocol === "http" ? o.method : "",
240
+ path: PathAnalyzer.join(v, localPath),
241
+ }),
212
242
  );
243
+ }
213
244
  if (o.protocol === "http")
214
245
  routes.push(
215
246
  ...TypedHttpRouteAnalyzer.analyze({
@@ -1,142 +1,153 @@
1
- import { INestApplication } from "@nestjs/common";
2
- import { IMetadataDictionary } from "./internal/legacy";
3
- import { OpenApiV3, OpenApiV3_1, SwaggerV2 } from "@typia/interface";
4
- import { OpenApiConverter } from "@typia/utils";
5
- import path from "path";
6
- import { TreeMap } from "tstl";
7
- import { OpenApi } from "typia";
8
-
9
- import { INestiaConfig } from "./INestiaConfig";
10
- import { AccessorAnalyzer } from "./analyses/AccessorAnalyzer";
11
- import { ConfigAnalyzer } from "./analyses/ConfigAnalyzer";
12
- import { PathAnalyzer } from "./analyses/PathAnalyzer";
13
- import { ReflectControllerAnalyzer } from "./analyses/ReflectControllerAnalyzer";
14
- import { TypedHttpRouteAnalyzer } from "./analyses/TypedHttpRouteAnalyzer";
15
- import { SwaggerGenerator } from "./generates/SwaggerGenerator";
16
- import { INestiaProject } from "./structures/INestiaProject";
17
- import { INestiaSdkInput } from "./structures/INestiaSdkInput";
18
- import { IReflectController } from "./structures/IReflectController";
19
- import { IReflectOperationError } from "./structures/IReflectOperationError";
20
- import { ITypedHttpRoute } from "./structures/ITypedHttpRoute";
21
- import { IOperationMetadata } from "./structures/IOperationMetadata";
22
- import { VersioningStrategy } from "./utils/VersioningStrategy";
23
-
24
- export namespace NestiaSwaggerComposer {
25
- export const document = async (
26
- app: INestApplication,
27
- config: Omit<INestiaConfig.ISwaggerConfig, "output">,
28
- ): Promise<
29
- | OpenApi.IDocument
30
- | OpenApiV3_1.IDocument
31
- | OpenApiV3.IDocument
32
- | SwaggerV2.IDocument
33
- > => {
34
- const input: INestiaSdkInput = await ConfigAnalyzer.application(app);
35
- const document: OpenApi.IDocument = await SwaggerGenerator.compose({
36
- config,
37
- routes: analyze(input),
38
- document: await SwaggerGenerator.initialize(config),
39
- });
40
- return (config.openapi ?? "3.2") === "3.2"
41
- ? document
42
- : OpenApiConverter.downgradeDocument(document, config.openapi as "2.0");
43
- };
44
-
45
- const analyze = (input: INestiaSdkInput): ITypedHttpRoute[] => {
46
- // GET REFLECT CONTROLLERS
47
- const unique: WeakSet<any> = new WeakSet();
48
- const project: Omit<INestiaProject, "config"> = {
49
- input,
50
- errors: [],
51
- warnings: [],
52
- };
53
- const controllers: IReflectController[] = project.input.controllers
54
- .map((c) =>
55
- ReflectControllerAnalyzer.analyze({ project, controller: c, unique }),
56
- )
57
- .filter((c): c is IReflectController => c !== null);
58
- if (project.errors.length)
59
- throw report({ type: "error", errors: project.errors });
60
-
61
- // METADATA COMPONENTS
62
- const collection: IMetadataDictionary =
63
- TypedHttpRouteAnalyzer.dictionary(controllers);
64
-
65
- // CONVERT TO TYPED OPERATIONS
66
- const globalPrefix: string = project.input.globalPrefix?.prefix ?? "";
67
- const routes: ITypedHttpRoute[] = [];
68
- for (const c of controllers)
69
- for (const o of c.operations) {
70
- const pathList: Set<string> = new Set();
71
- const versions: string[] = VersioningStrategy.merge(project)([
72
- ...(c.versions ?? []),
73
- ...(o.versions ?? []),
74
- ]);
75
- for (const v of versions)
76
- for (const prefix of wrapPaths(c.prefixes))
77
- for (const cPath of wrapPaths(c.paths))
78
- for (const filePath of wrapPaths(o.paths))
79
- pathList.add(
80
- PathAnalyzer.join(globalPrefix, v, prefix, cPath, filePath),
81
- );
82
- if (o.protocol === "http")
83
- routes.push(
84
- ...TypedHttpRouteAnalyzer.analyze({
85
- controller: c,
86
- errors: project.errors,
87
- dictionary: collection,
88
- operation: o,
89
- paths: Array.from(pathList),
90
- }),
91
- );
92
- }
93
- AccessorAnalyzer.analyze(routes);
94
- return routes;
95
- };
96
- }
97
-
98
- const report = (props: {
99
- type: "error" | "warning";
100
- errors: IReflectOperationError[];
101
- }): void => {
102
- const map: TreeMap<
103
- IReflectOperationError.Key,
104
- Array<string | IOperationMetadata.IError>
105
- > = new TreeMap();
106
- for (const e of props.errors)
107
- map.take(new IReflectOperationError.Key(e), () => []).push(...e.contents);
108
-
109
- const messages: string[] = [];
110
- for (const {
111
- first: { error },
112
- second: contents,
113
- } of map) {
114
- if (error.contents.length === 0) continue;
115
- const location: string = path.relative(process.cwd(), error.file);
116
- messages.push(
117
- [
118
- `${location} - `,
119
- error.class,
120
- ...(error.function !== null ? [`.${error.function}()`] : [""]),
121
- ...(error.from !== null ? [` from ${error.from}`] : [""]),
122
- ":\n",
123
- contents
124
- .map((c) => {
125
- if (typeof c === "string") return ` - ${c}`;
126
- else
127
- return [
128
- c.accessor
129
- ? ` - ${c.name}: `
130
- : ` - ${c.name} (${c.accessor}): `,
131
- ...c.messages.map((msg) => ` - ${msg}`),
132
- ].join("\n");
133
- })
134
- .join("\n"),
135
- ].join(""),
136
- );
137
- }
138
- throw new Error(`Error on NestiaSwaggerComposer.compose():\n${messages}`);
139
- };
140
-
141
- const wrapPaths = (paths: string[]): string[] =>
142
- paths.length === 0 ? [""] : paths;
1
+ import { INestApplication } from "@nestjs/common";
2
+ import { OpenApiV3, OpenApiV3_1, SwaggerV2 } from "@typia/interface";
3
+ import { OpenApiConverter } from "@typia/utils";
4
+ import path from "path";
5
+ import { TreeMap } from "tstl";
6
+ import { OpenApi } from "typia";
7
+
8
+ import { INestiaConfig } from "./INestiaConfig";
9
+ import { AccessorAnalyzer } from "./analyses/AccessorAnalyzer";
10
+ import { ConfigAnalyzer } from "./analyses/ConfigAnalyzer";
11
+ import { PathAnalyzer } from "./analyses/PathAnalyzer";
12
+ import { ReflectControllerAnalyzer } from "./analyses/ReflectControllerAnalyzer";
13
+ import { TypedHttpRouteAnalyzer } from "./analyses/TypedHttpRouteAnalyzer";
14
+ import { SwaggerGenerator } from "./generates/SwaggerGenerator";
15
+ import { IMetadataDictionary } from "./internal/legacy";
16
+ import { INestiaProject } from "./structures/INestiaProject";
17
+ import { INestiaSdkInput } from "./structures/INestiaSdkInput";
18
+ import { IOperationMetadata } from "./structures/IOperationMetadata";
19
+ import { IReflectController } from "./structures/IReflectController";
20
+ import { IReflectOperationError } from "./structures/IReflectOperationError";
21
+ import { ITypedHttpRoute } from "./structures/ITypedHttpRoute";
22
+ import { VersioningStrategy } from "./utils/VersioningStrategy";
23
+
24
+ export namespace NestiaSwaggerComposer {
25
+ export const document = async (
26
+ app: INestApplication,
27
+ config: Omit<INestiaConfig.ISwaggerConfig, "output">,
28
+ ): Promise<
29
+ | OpenApi.IDocument
30
+ | OpenApiV3_1.IDocument
31
+ | OpenApiV3.IDocument
32
+ | SwaggerV2.IDocument
33
+ > => {
34
+ const input: INestiaSdkInput = await ConfigAnalyzer.application(app);
35
+ const document: OpenApi.IDocument = await SwaggerGenerator.compose({
36
+ config,
37
+ routes: analyze(input),
38
+ document: await SwaggerGenerator.initialize(config),
39
+ });
40
+ return (config.openapi ?? "3.2") === "3.2"
41
+ ? document
42
+ : OpenApiConverter.downgradeDocument(document, config.openapi as "2.0");
43
+ };
44
+
45
+ const analyze = (input: INestiaSdkInput): ITypedHttpRoute[] => {
46
+ // GET REFLECT CONTROLLERS
47
+ const unique: WeakSet<any> = new WeakSet();
48
+ const project: Omit<INestiaProject, "config"> = {
49
+ input,
50
+ errors: [],
51
+ warnings: [],
52
+ };
53
+ const controllers: IReflectController[] = project.input.controllers
54
+ .map((c) =>
55
+ ReflectControllerAnalyzer.analyze({ project, controller: c, unique }),
56
+ )
57
+ .filter((c): c is IReflectController => c !== null);
58
+ if (project.errors.length)
59
+ throw report({ type: "error", errors: project.errors });
60
+
61
+ // METADATA COMPONENTS
62
+ const collection: IMetadataDictionary =
63
+ TypedHttpRouteAnalyzer.dictionary(controllers);
64
+
65
+ // CONVERT TO TYPED OPERATIONS
66
+ const routes: ITypedHttpRoute[] = [];
67
+ for (const c of controllers)
68
+ for (const o of c.operations) {
69
+ if (o.protocol !== "http") continue;
70
+ const pathList: Set<string> = new Set();
71
+ const versions: string[] = VersioningStrategy.merge(project)([
72
+ ...(c.versions ?? []),
73
+ ...(o.versions ?? []),
74
+ ]);
75
+ for (const v of versions)
76
+ for (const prefix of wrapPaths(c.prefixes))
77
+ for (const cPath of wrapPaths(c.paths))
78
+ for (const filePath of wrapPaths(o.paths)) {
79
+ const localPath: string = PathAnalyzer.join(
80
+ prefix,
81
+ cPath,
82
+ filePath,
83
+ );
84
+ pathList.add(
85
+ PathAnalyzer.joinWithGlobalPrefix({
86
+ globalPrefix: project.input.globalPrefix?.prefix ?? "",
87
+ exclude: project.input.globalPrefix?.exclude,
88
+ excludePath: localPath,
89
+ method: o.method,
90
+ path: PathAnalyzer.join(v, localPath),
91
+ }),
92
+ );
93
+ }
94
+ routes.push(
95
+ ...TypedHttpRouteAnalyzer.analyze({
96
+ controller: c,
97
+ errors: project.errors,
98
+ dictionary: collection,
99
+ operation: o,
100
+ paths: Array.from(pathList),
101
+ }),
102
+ );
103
+ }
104
+ AccessorAnalyzer.analyze(routes);
105
+ return routes;
106
+ };
107
+ }
108
+
109
+ const report = (props: {
110
+ type: "error" | "warning";
111
+ errors: IReflectOperationError[];
112
+ }): void => {
113
+ const map: TreeMap<
114
+ IReflectOperationError.Key,
115
+ Array<string | IOperationMetadata.IError>
116
+ > = new TreeMap();
117
+ for (const e of props.errors)
118
+ map.take(new IReflectOperationError.Key(e), () => []).push(...e.contents);
119
+
120
+ const messages: string[] = [];
121
+ for (const {
122
+ first: { error },
123
+ second: contents,
124
+ } of map) {
125
+ if (error.contents.length === 0) continue;
126
+ const location: string = path.relative(process.cwd(), error.file);
127
+ messages.push(
128
+ [
129
+ `${location} - `,
130
+ error.class,
131
+ ...(error.function !== null ? [`.${error.function}()`] : [""]),
132
+ ...(error.from !== null ? [` from ${error.from}`] : [""]),
133
+ ":\n",
134
+ contents
135
+ .map((c) => {
136
+ if (typeof c === "string") return ` - ${c}`;
137
+ else
138
+ return [
139
+ c.accessor
140
+ ? ` - ${c.name}: `
141
+ : ` - ${c.name} (${c.accessor}): `,
142
+ ...c.messages.map((msg) => ` - ${msg}`),
143
+ ].join("\n");
144
+ })
145
+ .join("\n"),
146
+ ].join(""),
147
+ );
148
+ }
149
+ throw new Error(`Error on NestiaSwaggerComposer.compose():\n${messages}`);
150
+ };
151
+
152
+ const wrapPaths = (paths: string[]): string[] =>
153
+ paths.length === 0 ? [""] : paths;
@@ -1,67 +1,64 @@
1
- import { NamingConvention } from "@typia/utils";
2
-
3
- import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
4
- import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
5
-
6
- export namespace AccessorAnalyzer {
7
- export const analyze = (
8
- routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
9
- ) => {
10
- shrink(routes);
11
- variable(routes);
12
- shrink(routes);
13
- for (const r of routes) r.name = r.accessor.at(-1) ?? r.name;
14
- };
15
-
16
- const prepare = (
17
- routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
18
- ): Map<string, number> => {
19
- const dict: Map<string, number> = new Map();
20
- for (const route of routeList)
21
- route.accessor.forEach((_a, i) => {
22
- const key: string = route.accessor.slice(0, i + 1).join(".");
23
- dict.set(key, (dict.get(key) ?? 0) + 1);
24
- });
25
- return dict;
26
- };
27
-
28
- const variable = (
29
- routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
30
- ) => {
31
- const dict: Map<string, number> = prepare(routeList);
32
- for (const route of routeList) {
33
- const emended: string[] = route.accessor.slice();
34
- route.accessor.forEach((accessor, i) => {
35
- if (NamingConvention.variable(accessor)) return;
36
- while (true) {
37
- accessor = "_" + accessor;
38
- const partial: string = [
39
- ...route.accessor.slice(0, i),
40
- accessor,
41
- ].join(".");
42
- if (dict.has(partial) === false) {
43
- emended[i] = accessor;
44
- break;
45
- }
46
- }
47
- });
48
- route.accessor.splice(0, route.accessor.length, ...emended);
49
- }
50
- };
51
-
52
- const shrink = (routeList: Array<ITypedHttpRoute | ITypedWebSocketRoute>) => {
53
- const dict: Map<string, number> = prepare(routeList);
54
- for (const route of routeList) {
55
- if (
56
- route.accessor.length < 2 ||
57
- route.accessor.at(-1) !== route.accessor.at(-2)
58
- )
59
- continue;
60
-
61
- const cut: string[] = route.accessor.slice(0, -1);
62
- if ((dict.get(cut.join(".")) ?? 0) > 1) continue;
63
-
64
- route.accessor = cut;
65
- }
66
- };
67
- }
1
+ import { NamingConvention } from "@typia/utils";
2
+
3
+ import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
4
+ import { ITypedMcpRoute } from "../structures/ITypedMcpRoute";
5
+ import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
6
+
7
+ type AnyRoute = ITypedHttpRoute | ITypedWebSocketRoute | ITypedMcpRoute;
8
+
9
+ export namespace AccessorAnalyzer {
10
+ export const analyze = (routes: Array<AnyRoute>) => {
11
+ shrink(routes);
12
+ variable(routes);
13
+ shrink(routes);
14
+ for (const r of routes) r.name = r.accessor.at(-1) ?? r.name;
15
+ };
16
+
17
+ const prepare = (routeList: Array<AnyRoute>): Map<string, number> => {
18
+ const dict: Map<string, number> = new Map();
19
+ for (const route of routeList)
20
+ route.accessor.forEach((_a, i) => {
21
+ const key: string = route.accessor.slice(0, i + 1).join(".");
22
+ dict.set(key, (dict.get(key) ?? 0) + 1);
23
+ });
24
+ return dict;
25
+ };
26
+
27
+ const variable = (routeList: Array<AnyRoute>) => {
28
+ const dict: Map<string, number> = prepare(routeList);
29
+ for (const route of routeList) {
30
+ const emended: string[] = route.accessor.slice();
31
+ route.accessor.forEach((accessor, i) => {
32
+ if (NamingConvention.variable(accessor)) return;
33
+ while (true) {
34
+ accessor = "_" + accessor;
35
+ const partial: string = [
36
+ ...route.accessor.slice(0, i),
37
+ accessor,
38
+ ].join(".");
39
+ if (dict.has(partial) === false) {
40
+ emended[i] = accessor;
41
+ break;
42
+ }
43
+ }
44
+ });
45
+ route.accessor.splice(0, route.accessor.length, ...emended);
46
+ }
47
+ };
48
+
49
+ const shrink = (routeList: Array<AnyRoute>) => {
50
+ const dict: Map<string, number> = prepare(routeList);
51
+ for (const route of routeList) {
52
+ if (
53
+ route.accessor.length < 2 ||
54
+ route.accessor.at(-1) !== route.accessor.at(-2)
55
+ )
56
+ continue;
57
+
58
+ const cut: string[] = route.accessor.slice(0, -1);
59
+ if ((dict.get(cut.join(".")) ?? 0) > 1) continue;
60
+
61
+ route.accessor = cut;
62
+ }
63
+ };
64
+ }