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

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 (259) 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/factories/ExpressionFactory.d.ts +9 -0
  48. package/lib/factories/ExpressionFactory.js +16 -0
  49. package/lib/factories/ExpressionFactory.js.map +1 -0
  50. package/lib/factories/IdentifierFactory.d.ts +22 -0
  51. package/lib/factories/IdentifierFactory.js +50 -0
  52. package/lib/factories/IdentifierFactory.js.map +1 -0
  53. package/lib/factories/LiteralFactory.d.ts +9 -0
  54. package/lib/factories/LiteralFactory.js +48 -0
  55. package/lib/factories/LiteralFactory.js.map +1 -0
  56. package/lib/factories/StatementFactory.d.ts +14 -0
  57. package/lib/factories/StatementFactory.js +20 -0
  58. package/lib/factories/StatementFactory.js.map +1 -0
  59. package/lib/factories/TypeFactory.d.ts +24 -0
  60. package/lib/factories/TypeFactory.js +27 -0
  61. package/lib/factories/TypeFactory.js.map +1 -0
  62. package/lib/generates/CloneGenerator.js +6 -4
  63. package/lib/generates/CloneGenerator.js.map +1 -1
  64. package/lib/generates/SdkGenerator.js +50 -1
  65. package/lib/generates/SdkGenerator.js.map +1 -1
  66. package/lib/generates/SwaggerGenerator.js +18 -2
  67. package/lib/generates/SwaggerGenerator.js.map +1 -1
  68. package/lib/generates/internal/E2eFileProgrammer.js +32 -29
  69. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  70. package/lib/generates/internal/FilePrinter.d.ts +2 -2
  71. package/lib/generates/internal/FilePrinter.js +14 -25
  72. package/lib/generates/internal/FilePrinter.js.map +1 -1
  73. package/lib/generates/internal/ImportDictionary.d.ts +2 -1
  74. package/lib/generates/internal/ImportDictionary.js +16 -10
  75. package/lib/generates/internal/ImportDictionary.js.map +1 -1
  76. package/lib/generates/internal/SdkAliasCollection.d.ts +12 -10
  77. package/lib/generates/internal/SdkAliasCollection.js +29 -22
  78. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  79. package/lib/generates/internal/SdkDistributionComposer.d.ts +1 -0
  80. package/lib/generates/internal/SdkDistributionComposer.js +3 -0
  81. package/lib/generates/internal/SdkDistributionComposer.js.map +1 -1
  82. package/lib/generates/internal/SdkFileProgrammer.js +6 -3
  83. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  84. package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +1 -1
  85. package/lib/generates/internal/SdkHttpCloneProgrammer.js +3 -3
  86. package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
  87. package/lib/generates/internal/SdkHttpCloneReferencer.d.ts +1 -1
  88. package/lib/generates/internal/SdkHttpCloneReferencer.js +42 -9
  89. package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -1
  90. package/lib/generates/internal/SdkHttpFunctionProgrammer.d.ts +1 -1
  91. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +47 -51
  92. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  93. package/lib/generates/internal/SdkHttpNamespaceProgrammer.d.ts +1 -1
  94. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +63 -61
  95. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
  96. package/lib/generates/internal/SdkHttpParameterProgrammer.d.ts +2 -2
  97. package/lib/generates/internal/SdkHttpParameterProgrammer.js +11 -13
  98. package/lib/generates/internal/SdkHttpParameterProgrammer.js.map +1 -1
  99. package/lib/generates/internal/SdkHttpRouteProgrammer.d.ts +1 -1
  100. package/lib/generates/internal/SdkHttpSimulationProgrammer.d.ts +1 -1
  101. package/lib/generates/internal/SdkHttpSimulationProgrammer.js +52 -47
  102. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
  103. package/lib/generates/internal/SdkMcpRouteProgrammer.d.ts +15 -0
  104. package/lib/generates/internal/SdkMcpRouteProgrammer.js +149 -0
  105. package/lib/generates/internal/SdkMcpRouteProgrammer.js.map +1 -0
  106. package/lib/generates/internal/SdkRouteDirectory.d.ts +2 -1
  107. package/lib/generates/internal/SdkRouteDirectory.js.map +1 -1
  108. package/lib/generates/internal/SdkTypeProgrammer.d.ts +3 -3
  109. package/lib/generates/internal/SdkTypeProgrammer.js +42 -43
  110. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
  111. package/lib/generates/internal/SdkTypeTagProgrammer.d.ts +2 -1
  112. package/lib/generates/internal/SdkTypeTagProgrammer.js +7 -9
  113. package/lib/generates/internal/SdkTypeTagProgrammer.js.map +1 -1
  114. package/lib/generates/internal/SdkWebSocketCloneProgrammer.d.ts +6 -0
  115. package/lib/generates/internal/SdkWebSocketCloneProgrammer.js +283 -0
  116. package/lib/generates/internal/SdkWebSocketCloneProgrammer.js.map +1 -0
  117. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.d.ts +2 -2
  118. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +45 -47
  119. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
  120. package/lib/generates/internal/SdkWebSocketParameterProgrammer.d.ts +3 -3
  121. package/lib/generates/internal/SdkWebSocketParameterProgrammer.js +9 -9
  122. package/lib/generates/internal/SdkWebSocketParameterProgrammer.js.map +1 -1
  123. package/lib/generates/internal/SdkWebSocketRouteProgrammer.d.ts +2 -2
  124. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +37 -41
  125. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  126. package/lib/generates/internal/SwaggerOperationParameterComposer.js +10 -2
  127. package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
  128. package/lib/generates/internal/SwaggerOperationResponseComposer.d.ts +1 -1
  129. package/lib/generates/internal/SwaggerOperationResponseComposer.js +6 -1
  130. package/lib/generates/internal/SwaggerOperationResponseComposer.js.map +1 -1
  131. package/lib/generates/internal/SwaggerReadonlyArrayEmender.d.ts +9 -0
  132. package/lib/generates/internal/SwaggerReadonlyArrayEmender.js +174 -0
  133. package/lib/generates/internal/SwaggerReadonlyArrayEmender.js.map +1 -0
  134. package/lib/structures/INestiaSdkInput.d.ts +9 -2
  135. package/lib/structures/IReflectController.d.ts +2 -1
  136. package/lib/structures/IReflectHttpOperationSuccess.d.ts +4 -2
  137. package/lib/structures/IReflectMcpOperation.d.ts +35 -0
  138. package/lib/structures/IReflectMcpOperation.js +3 -0
  139. package/lib/structures/IReflectMcpOperation.js.map +1 -0
  140. package/lib/structures/IReflectMcpOperationParameter.d.ts +19 -0
  141. package/lib/structures/IReflectMcpOperationParameter.js +3 -0
  142. package/lib/structures/IReflectMcpOperationParameter.js.map +1 -0
  143. package/lib/structures/ITypedApplication.d.ts +2 -1
  144. package/lib/structures/ITypedHttpRouteSuccess.d.ts +3 -1
  145. package/lib/structures/ITypedMcpRoute.d.ts +31 -0
  146. package/lib/structures/ITypedMcpRoute.js +3 -0
  147. package/lib/structures/ITypedMcpRoute.js.map +1 -0
  148. package/lib/transform.d.ts +5 -9
  149. package/lib/transform.js +8 -31
  150. package/lib/transform.js.map +1 -1
  151. package/lib/utils/HttpResponseContentTypeUtil.d.ts +5 -0
  152. package/lib/utils/HttpResponseContentTypeUtil.js +22 -0
  153. package/lib/utils/HttpResponseContentTypeUtil.js.map +1 -0
  154. package/native/go.mod +52 -52
  155. package/native/go.sum +84 -54
  156. package/native/sdk/register.go +322 -165
  157. package/native/sdk/sdk.go +17 -17
  158. package/native/sdk/sdk_metadata_json.go +327 -327
  159. package/native/sdk/sdk_transform.go +1879 -1549
  160. package/package.json +13 -11
  161. package/src/INestiaConfig.ts +267 -267
  162. package/src/NestiaSdkApplication.ts +39 -8
  163. package/src/NestiaSwaggerComposer.ts +153 -142
  164. package/src/analyses/AccessorAnalyzer.ts +64 -67
  165. package/src/analyses/ConfigAnalyzer.ts +330 -330
  166. package/src/analyses/ImportAnalyzer.ts +92 -92
  167. package/src/analyses/PathAnalyzer.ts +130 -69
  168. package/src/analyses/ReflectControllerAnalyzer.ts +112 -105
  169. package/src/analyses/ReflectHttpOperationAnalyzer.ts +183 -183
  170. package/src/analyses/ReflectHttpOperationExceptionAnalyzer.ts +90 -90
  171. package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +350 -350
  172. package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +163 -130
  173. package/src/analyses/ReflectMcpOperationAnalyzer.ts +124 -0
  174. package/src/analyses/ReflectMetadataAnalyzer.ts +44 -44
  175. package/src/analyses/SecurityAnalyzer.ts +25 -25
  176. package/src/analyses/TypedMcpRouteAnalyzer.ts +34 -0
  177. package/src/decorators/OperationMetadata.ts +29 -29
  178. package/src/executable/internal/CommandParser.ts +15 -15
  179. package/src/executable/internal/NestiaConfigLoader.ts +451 -446
  180. package/src/executable/internal/NestiaSdkCommand.ts +124 -106
  181. package/src/executable/internal/NestiaSdkWatcher.ts +342 -0
  182. package/src/executable/sdk.ts +90 -88
  183. package/src/factories/ExpressionFactory.ts +23 -0
  184. package/src/factories/IdentifierFactory.ts +84 -0
  185. package/src/factories/LiteralFactory.ts +54 -0
  186. package/src/factories/StatementFactory.ts +56 -0
  187. package/src/factories/TypeFactory.ts +27 -0
  188. package/src/generates/CloneGenerator.ts +74 -66
  189. package/src/generates/E2eGenerator.ts +32 -32
  190. package/src/generates/SdkGenerator.ts +176 -118
  191. package/src/generates/SwaggerGenerator.ts +342 -310
  192. package/src/generates/internal/E2eFileProgrammer.ts +246 -233
  193. package/src/generates/internal/FilePrinter.ts +57 -65
  194. package/src/generates/internal/ImportDictionary.ts +207 -204
  195. package/src/generates/internal/SdkAliasCollection.ts +280 -261
  196. package/src/generates/internal/SdkDistributionComposer.ts +123 -116
  197. package/src/generates/internal/SdkFileProgrammer.ts +113 -112
  198. package/src/generates/internal/SdkHttpCloneProgrammer.ts +124 -126
  199. package/src/generates/internal/SdkHttpCloneReferencer.ts +131 -77
  200. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +290 -301
  201. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +507 -510
  202. package/src/generates/internal/SdkHttpParameterProgrammer.ts +163 -165
  203. package/src/generates/internal/SdkHttpRouteProgrammer.ts +109 -109
  204. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +322 -314
  205. package/src/generates/internal/SdkImportWizard.ts +62 -62
  206. package/src/generates/internal/SdkMcpRouteProgrammer.ts +447 -0
  207. package/src/generates/internal/SdkRouteDirectory.ts +21 -18
  208. package/src/generates/internal/SdkTypeProgrammer.ts +389 -382
  209. package/src/generates/internal/SdkTypeTagProgrammer.ts +110 -114
  210. package/src/generates/internal/SdkWebSocketCloneProgrammer.ts +319 -0
  211. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +383 -389
  212. package/src/generates/internal/SdkWebSocketParameterProgrammer.ts +91 -89
  213. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +304 -323
  214. package/src/generates/internal/SwaggerDescriptionComposer.ts +64 -64
  215. package/src/generates/internal/SwaggerOperationComposer.ts +119 -119
  216. package/src/generates/internal/SwaggerOperationParameterComposer.ts +175 -162
  217. package/src/generates/internal/SwaggerOperationResponseComposer.ts +115 -110
  218. package/src/generates/internal/SwaggerReadonlyArrayEmender.ts +262 -0
  219. package/src/index.ts +4 -4
  220. package/src/internal/legacy.ts +492 -492
  221. package/src/module.ts +4 -4
  222. package/src/structures/INestiaProject.ts +10 -10
  223. package/src/structures/INestiaSdkInput.ts +27 -20
  224. package/src/structures/IOperationMetadata.ts +41 -41
  225. package/src/structures/IReflectController.ts +18 -15
  226. package/src/structures/IReflectHttpOperation.ts +26 -26
  227. package/src/structures/IReflectHttpOperationException.ts +18 -18
  228. package/src/structures/IReflectHttpOperationParameter.ts +79 -79
  229. package/src/structures/IReflectHttpOperationSuccess.ts +18 -21
  230. package/src/structures/IReflectImport.ts +6 -6
  231. package/src/structures/IReflectMcpOperation.ts +38 -0
  232. package/src/structures/IReflectMcpOperationParameter.ts +27 -0
  233. package/src/structures/IReflectOperationError.ts +26 -26
  234. package/src/structures/IReflectType.ts +4 -4
  235. package/src/structures/IReflectWebSocketOperation.ts +17 -17
  236. package/src/structures/ITypedApplication.ts +12 -11
  237. package/src/structures/ITypedHttpRoute.ts +41 -41
  238. package/src/structures/ITypedHttpRouteException.ts +15 -15
  239. package/src/structures/ITypedHttpRouteParameter.ts +41 -41
  240. package/src/structures/ITypedHttpRouteSuccess.ts +18 -22
  241. package/src/structures/ITypedMcpRoute.ts +33 -0
  242. package/src/structures/ITypedWebSocketRoute.ts +24 -24
  243. package/src/structures/ITypedWebSocketRouteParameter.ts +3 -3
  244. package/src/transform.ts +28 -59
  245. package/src/typings/get-function-location.d.ts +7 -7
  246. package/src/utils/ArrayUtil.ts +26 -26
  247. package/src/utils/EmittedJavaScriptPatcher.ts +88 -88
  248. package/src/utils/FileRetriever.ts +22 -22
  249. package/src/utils/HttpResponseContentTypeUtil.ts +30 -0
  250. package/src/utils/MapUtil.ts +14 -14
  251. package/src/utils/PathUtil.ts +10 -10
  252. package/src/utils/SourceFinder.ts +63 -63
  253. package/src/utils/StringUtil.ts +17 -17
  254. package/src/utils/TsConfigReader.ts +108 -108
  255. package/src/utils/TtscExecutor.ts +68 -68
  256. package/src/utils/VersioningStrategy.ts +28 -28
  257. package/src/validators/HttpHeadersValidator.ts +11 -11
  258. package/src/validators/HttpQueryValidator.ts +11 -11
  259. package/src/validators/TextPlainValidator.ts +17 -17
@@ -1,130 +1,163 @@
1
- import { SwaggerExample } from "@nestia/core";
2
- import {
3
- HEADERS_METADATA,
4
- HTTP_CODE_METADATA,
5
- INTERCEPTORS_METADATA,
6
- } from "@nestjs/common/constants";
7
- import { HttpQueryProgrammer, JsonMetadataFactory, sizeOf } from "../internal/legacy";
8
-
9
- import { IReflectController } from "../structures/IReflectController";
10
- import { IReflectHttpOperationSuccess } from "../structures/IReflectHttpOperationSuccess";
11
- import { IReflectOperationError } from "../structures/IReflectOperationError";
12
- import { IOperationMetadata } from "../structures/IOperationMetadata";
13
- import { TextPlainValidator } from "../validators/TextPlainValidator";
14
-
15
- export namespace ReflectHttpOperationResponseAnalyzer {
16
- export interface IContext {
17
- controller: IReflectController;
18
- function: Function;
19
- functionName: string;
20
- httpMethod: string;
21
- metadata: IOperationMetadata;
22
- errors: IReflectOperationError[];
23
- }
24
-
25
- export const analyze = (
26
- ctx: IContext,
27
- ): IReflectHttpOperationSuccess | null => {
28
- const errors: Array<string | IOperationMetadata.IError> = [];
29
- const report = () => {
30
- ctx.errors.push({
31
- file: ctx.controller.file,
32
- class: ctx.controller.class.name,
33
- function: ctx.functionName,
34
- from: "return",
35
- contents: errors,
36
- });
37
- return null;
38
- };
39
-
40
- const encrypted: boolean = hasInterceptor({
41
- name: "EncryptedRouteInterceptor",
42
- function: ctx.function,
43
- });
44
- const contentType: string | null = encrypted
45
- ? "text/plain"
46
- : hasInterceptor({
47
- name: "TypedQueryRouteInterceptor",
48
- function: ctx.function,
49
- })
50
- ? "application/x-www-form-urlencoded"
51
- : (Reflect.getMetadata(HEADERS_METADATA, ctx.function)?.find(
52
- (h: Record<string, string>) =>
53
- typeof h?.name === "string" &&
54
- typeof h?.value === "string" &&
55
- h.name.toLowerCase() === "content-type",
56
- )?.value ??
57
- Reflect.getMetadata("swagger/apiProduces", ctx.function)?.[0] ??
58
- (ctx.httpMethod === "HEAD" ? null : "application/json"));
59
-
60
- const schema =
61
- contentType === "application/json"
62
- ? ctx.metadata.success.primitive
63
- : ctx.metadata.success.resolved;
64
- if (schema.success === false) errors.push(...schema.errors);
65
- if (ctx.httpMethod === "HEAD" && contentType !== null)
66
- errors.push(`HEAD method must not have a content type.`);
67
- if (isContentType(contentType) === false)
68
- errors.push(
69
- `@nestia/sdk does not support ${JSON.stringify(contentType)} content type.`,
70
- );
71
-
72
- if (errors.length) return report();
73
- else if (
74
- ctx.metadata.success.type === null ||
75
- schema.success === false ||
76
- !isContentType(contentType)
77
- )
78
- return null;
79
-
80
- const example: SwaggerExample.IData<any> | undefined = Reflect.getMetadata(
81
- "nestia/SwaggerExample/Response",
82
- ctx.function,
83
- );
84
- return {
85
- contentType,
86
- encrypted,
87
- status:
88
- getStatus(ctx.function) ?? (ctx.httpMethod === "POST" ? 201 : 200),
89
- type: ctx.metadata.success.type,
90
- ...schema.data,
91
- validate:
92
- contentType === "application/json" || encrypted === true
93
- ? JsonMetadataFactory.validate
94
- : contentType === "application/x-www-form-urlencoded"
95
- ? HttpQueryProgrammer.validate
96
- : contentType === "text/plain"
97
- ? TextPlainValidator.validate
98
- : (next) =>
99
- sizeOf(next.metadata) !== 0
100
- ? ["HEAD method must not have any return value."]
101
- : [],
102
- example: example?.example,
103
- examples: example?.examples,
104
- };
105
- };
106
-
107
- const getStatus = (func: Function): number | null => {
108
- const text = Reflect.getMetadata(HTTP_CODE_METADATA, func);
109
- if (text === undefined) return null;
110
- const value: number = Number(text);
111
- return isNaN(value) ? null : value;
112
- };
113
-
114
- const hasInterceptor = (props: {
115
- name: string;
116
- function: Function;
117
- }): boolean => {
118
- const meta = Reflect.getMetadata(INTERCEPTORS_METADATA, props.function);
119
- if (Array.isArray(meta) === false) return false;
120
- return meta.some((elem) => elem?.constructor?.name === props.name);
121
- };
122
-
123
- const isContentType = (
124
- input: string | null,
125
- ): input is IReflectHttpOperationSuccess["contentType"] =>
126
- input === null ||
127
- input === "application/json" ||
128
- input === "text/plain" ||
129
- input === "application/x-www-form-urlencoded";
130
- }
1
+ import { SwaggerExample } from "@nestia/core";
2
+ import {
3
+ HEADERS_METADATA,
4
+ HTTP_CODE_METADATA,
5
+ INTERCEPTORS_METADATA,
6
+ } from "@nestjs/common/constants";
7
+
8
+ import {
9
+ HttpQueryProgrammer,
10
+ JsonMetadataFactory,
11
+ sizeOf,
12
+ } from "../internal/legacy";
13
+ import { IOperationMetadata } from "../structures/IOperationMetadata";
14
+ import { IReflectController } from "../structures/IReflectController";
15
+ import { IReflectHttpOperationSuccess } from "../structures/IReflectHttpOperationSuccess";
16
+ import { IReflectOperationError } from "../structures/IReflectOperationError";
17
+ import { HttpResponseContentTypeUtil } from "../utils/HttpResponseContentTypeUtil";
18
+ import { TextPlainValidator } from "../validators/TextPlainValidator";
19
+
20
+ export namespace ReflectHttpOperationResponseAnalyzer {
21
+ export interface IContext {
22
+ controller: IReflectController;
23
+ function: Function;
24
+ functionName: string;
25
+ httpMethod: string;
26
+ metadata: IOperationMetadata;
27
+ errors: IReflectOperationError[];
28
+ }
29
+
30
+ export const analyze = (
31
+ ctx: IContext,
32
+ ): IReflectHttpOperationSuccess | null => {
33
+ const errors: Array<string | IOperationMetadata.IError> = [];
34
+ const report = () => {
35
+ ctx.errors.push({
36
+ file: ctx.controller.file,
37
+ class: ctx.controller.class.name,
38
+ function: ctx.functionName,
39
+ from: "return",
40
+ contents: errors,
41
+ });
42
+ return null;
43
+ };
44
+
45
+ const encrypted: boolean = hasInterceptor({
46
+ name: "EncryptedRouteInterceptor",
47
+ function: ctx.function,
48
+ });
49
+ const contentType: string | null = encrypted
50
+ ? "text/plain"
51
+ : hasInterceptor({
52
+ name: "TypedQueryRouteInterceptor",
53
+ function: ctx.function,
54
+ })
55
+ ? "application/x-www-form-urlencoded"
56
+ : (Reflect.getMetadata(HEADERS_METADATA, ctx.function)?.find(
57
+ (h: Record<string, string>) =>
58
+ typeof h?.name === "string" &&
59
+ typeof h?.value === "string" &&
60
+ h.name.toLowerCase() === "content-type",
61
+ )?.value ??
62
+ Reflect.getMetadata("swagger/apiProduces", ctx.function)?.[0] ??
63
+ (ctx.httpMethod === "HEAD" ? null : "application/json"));
64
+
65
+ const binary: boolean = HttpResponseContentTypeUtil.isBinary(contentType);
66
+ const schema = binary
67
+ ? { success: true as const, data: EMPTY_SCHEMA }
68
+ : contentType === "application/json"
69
+ ? ctx.metadata.success.primitive
70
+ : ctx.metadata.success.resolved;
71
+ if (schema.success === false) errors.push(...schema.errors);
72
+ if (ctx.httpMethod === "HEAD" && contentType !== null)
73
+ errors.push(`HEAD method must not have a content type.`);
74
+ if (HttpResponseContentTypeUtil.isSupported(contentType) === false)
75
+ errors.push(
76
+ `@nestia/sdk does not support ${JSON.stringify(contentType)} content type.`,
77
+ );
78
+
79
+ if (errors.length) return report();
80
+ else if (
81
+ (binary === false && ctx.metadata.success.type === null) ||
82
+ schema.success === false ||
83
+ !HttpResponseContentTypeUtil.isSupported(contentType)
84
+ )
85
+ return null;
86
+
87
+ const example: SwaggerExample.IData<any> | undefined = Reflect.getMetadata(
88
+ "nestia/SwaggerExample/Response",
89
+ ctx.function,
90
+ );
91
+ return {
92
+ contentType,
93
+ binary,
94
+ encrypted,
95
+ status:
96
+ getStatus(ctx.function) ?? (ctx.httpMethod === "POST" ? 201 : 200),
97
+ type: ctx.metadata.success.type ?? { name: "ReadableStream" },
98
+ ...schema.data,
99
+ validate:
100
+ binary === true
101
+ ? () => []
102
+ : contentType === "application/json" || encrypted === true
103
+ ? JsonMetadataFactory.validate
104
+ : contentType === "application/x-www-form-urlencoded"
105
+ ? HttpQueryProgrammer.validate
106
+ : contentType === "text/plain"
107
+ ? TextPlainValidator.validate
108
+ : (next) =>
109
+ sizeOf(next.metadata) !== 0
110
+ ? ["HEAD method must not have any return value."]
111
+ : [],
112
+ example: example?.example,
113
+ examples: example?.examples,
114
+ };
115
+ };
116
+
117
+ const getStatus = (func: Function): number | null => {
118
+ const text = Reflect.getMetadata(HTTP_CODE_METADATA, func);
119
+ if (text === undefined) return null;
120
+ const value: number = Number(text);
121
+ return isNaN(value) ? null : value;
122
+ };
123
+
124
+ const hasInterceptor = (props: {
125
+ name: string;
126
+ function: Function;
127
+ }): boolean => {
128
+ const meta = Reflect.getMetadata(INTERCEPTORS_METADATA, props.function);
129
+ if (Array.isArray(meta) === false) return false;
130
+ return meta.some((elem) => elem?.constructor?.name === props.name);
131
+ };
132
+
133
+ const EMPTY_SCHEMA: IOperationMetadata.ISchema = {
134
+ components: {
135
+ aliases: [],
136
+ arrays: [],
137
+ objects: [],
138
+ tuples: [],
139
+ },
140
+ metadata: {
141
+ aliases: [],
142
+ any: false,
143
+ arrays: [],
144
+ atomics: [],
145
+ constants: [],
146
+ escaped: null,
147
+ functions: [],
148
+ maps: [],
149
+ natives: [],
150
+ nullable: false,
151
+ objects: [],
152
+ optional: false,
153
+ required: true,
154
+ rest: null,
155
+ sets: [],
156
+ templates: [],
157
+ tuples: [],
158
+ size: 0,
159
+ name: "void",
160
+ empty: true,
161
+ } as IOperationMetadata.ISchema["metadata"],
162
+ };
163
+ }
@@ -0,0 +1,124 @@
1
+ import { METHOD_METADATA, PATH_METADATA } from "@nestjs/common/constants";
2
+
3
+ import { INestiaProject } from "../structures/INestiaProject";
4
+ import { IOperationMetadata } from "../structures/IOperationMetadata";
5
+ import { IReflectController } from "../structures/IReflectController";
6
+ import { IReflectImport } from "../structures/IReflectImport";
7
+ import { IReflectMcpOperation } from "../structures/IReflectMcpOperation";
8
+ import { IReflectMcpOperationParameter } from "../structures/IReflectMcpOperationParameter";
9
+ import { ImportAnalyzer } from "./ImportAnalyzer";
10
+
11
+ export namespace ReflectMcpOperationAnalyzer {
12
+ export interface IProps {
13
+ project: Omit<INestiaProject, "config">;
14
+ controller: IReflectController;
15
+ function: Function;
16
+ name: string;
17
+ metadata: IOperationMetadata;
18
+ }
19
+
20
+ export const analyze = (ctx: IProps): IReflectMcpOperation | null => {
21
+ const route:
22
+ | {
23
+ name: string;
24
+ title?: string;
25
+ description?: string;
26
+ inputSchema: object;
27
+ outputSchema?: object;
28
+ annotations?: IReflectMcpOperation.IAnnotations;
29
+ }
30
+ | undefined = Reflect.getMetadata("nestia/McpRoute", ctx.function);
31
+ if (route === undefined) return null;
32
+
33
+ const errors: string[] = [];
34
+ const hasHttpRoute: boolean =
35
+ Reflect.getMetadata(PATH_METADATA, ctx.function) !== undefined ||
36
+ Reflect.getMetadata(METHOD_METADATA, ctx.function) !== undefined;
37
+ const hasWebSocketRoute: boolean =
38
+ Reflect.getMetadata("nestia/WebSocketRoute", ctx.function) !== undefined;
39
+
40
+ if (hasHttpRoute || hasWebSocketRoute)
41
+ errors.push(
42
+ "@McpRoute must not be combined with HTTP or WebSocket route decorators on the same method.",
43
+ );
44
+
45
+ const preconfigured: IReflectMcpOperationParameter.IPreconfigured[] = (
46
+ (Reflect.getMetadata(
47
+ "nestia/McpRoute/Parameters",
48
+ ctx.controller.class.prototype,
49
+ ctx.name,
50
+ ) ?? []) as IReflectMcpOperationParameter.IPreconfigured[]
51
+ ).sort((a, b) => a.index - b.index);
52
+
53
+ if (preconfigured.length > 1)
54
+ errors.push(
55
+ "@McpRoute tools may declare at most one @McpRoute.Params() parameter.",
56
+ );
57
+ if (ctx.function.length > 1)
58
+ errors.push(
59
+ "@McpRoute tools must have 0 or 1 parameters (the MCP arguments object).",
60
+ );
61
+
62
+ const imports: IReflectImport[] = [];
63
+ const parameters: IReflectMcpOperationParameter[] = preconfigured
64
+ .map((p) => {
65
+ const matched: IOperationMetadata.IParameter | undefined =
66
+ ctx.metadata.parameters.find(
67
+ (m: IOperationMetadata.IParameter) => p.index === m.index,
68
+ );
69
+ if (matched === undefined) {
70
+ errors.push(
71
+ `Unable to find parameter type of the ${p.index} (th) argument.`,
72
+ );
73
+ return null;
74
+ }
75
+ if (matched.type === null) {
76
+ errors.push(
77
+ `Failed to analyze the parameter type of ${JSON.stringify(matched.name)}.`,
78
+ );
79
+ return null;
80
+ }
81
+ imports.push(...matched.imports);
82
+ return {
83
+ category: "params" as const,
84
+ name: matched.name,
85
+ index: p.index,
86
+ type: matched.type,
87
+ imports: matched.imports,
88
+ description: matched.description,
89
+ jsDocTags: matched.jsDocTags,
90
+ };
91
+ })
92
+ .filter((p): p is IReflectMcpOperationParameter => !!p);
93
+
94
+ if (ctx.metadata.success?.imports?.length)
95
+ imports.push(...ctx.metadata.success.imports);
96
+
97
+ if (errors.length) {
98
+ ctx.project.errors.push({
99
+ file: ctx.controller.file,
100
+ class: ctx.controller.class.name,
101
+ function: ctx.function.name,
102
+ from: ctx.name,
103
+ contents: errors,
104
+ });
105
+ return null;
106
+ }
107
+ return {
108
+ protocol: "mcp",
109
+ name: ctx.name,
110
+ toolName: route.name,
111
+ title: route.title ?? null,
112
+ toolDescription: route.description ?? null,
113
+ inputSchema: route.inputSchema,
114
+ outputSchema: route.outputSchema ?? null,
115
+ annotations: route.annotations ?? null,
116
+ function: ctx.function,
117
+ parameters,
118
+ returnType: ctx.metadata.success?.type ?? null,
119
+ imports: ImportAnalyzer.merge(imports),
120
+ description: ctx.metadata.description ?? null,
121
+ jsDocTags: ctx.metadata.jsDocTags,
122
+ };
123
+ };
124
+ }
@@ -1,44 +1,44 @@
1
- import { VERSION_NEUTRAL } from "@nestjs/common";
2
- import { PATH_METADATA, VERSION_METADATA } from "@nestjs/common/constants";
3
- import { VersionValue } from "@nestjs/common/interfaces";
4
-
5
- import { SecurityAnalyzer } from "./SecurityAnalyzer";
6
-
7
- export namespace ReflectMetadataAnalyzer {
8
- export const paths = (target: Function): string[] => {
9
- const value: string | string[] = Reflect.getMetadata(PATH_METADATA, target);
10
- if (typeof value === "string") return [value];
11
- else if (value.length === 0) return [""];
12
- else return value;
13
- };
14
-
15
- export const extensions = (value: any): Record<string, any> => {
16
- const entire: Record<string, any>[] | undefined = Reflect.getMetadata(
17
- "swagger/apiExtension",
18
- value,
19
- );
20
- return entire ?? {};
21
- };
22
-
23
- export const securities = (value: any): Record<string, string[]>[] => {
24
- const entire: Record<string, string[]>[] | undefined = Reflect.getMetadata(
25
- "swagger/apiSecurity",
26
- value,
27
- );
28
- return entire ? SecurityAnalyzer.merge(...entire) : [];
29
- };
30
-
31
- export const versions = (
32
- target: any,
33
- ): Array<string | typeof VERSION_NEUTRAL> | undefined => {
34
- const value: VersionValue | undefined = Reflect.getMetadata(
35
- VERSION_METADATA,
36
- target,
37
- );
38
- return value === undefined
39
- ? undefined
40
- : Array.isArray(value)
41
- ? value
42
- : [value];
43
- };
44
- }
1
+ import { VERSION_NEUTRAL } from "@nestjs/common";
2
+ import { PATH_METADATA, VERSION_METADATA } from "@nestjs/common/constants";
3
+ import { VersionValue } from "@nestjs/common/interfaces";
4
+
5
+ import { SecurityAnalyzer } from "./SecurityAnalyzer";
6
+
7
+ export namespace ReflectMetadataAnalyzer {
8
+ export const paths = (target: Function): string[] => {
9
+ const value: string | string[] = Reflect.getMetadata(PATH_METADATA, target);
10
+ if (typeof value === "string") return [value];
11
+ else if (value.length === 0) return [""];
12
+ else return value;
13
+ };
14
+
15
+ export const extensions = (value: any): Record<string, any> => {
16
+ const entire: Record<string, any>[] | undefined = Reflect.getMetadata(
17
+ "swagger/apiExtension",
18
+ value,
19
+ );
20
+ return entire ?? {};
21
+ };
22
+
23
+ export const securities = (value: any): Record<string, string[]>[] => {
24
+ const entire: Record<string, string[]>[] | undefined = Reflect.getMetadata(
25
+ "swagger/apiSecurity",
26
+ value,
27
+ );
28
+ return entire ? SecurityAnalyzer.merge(...entire) : [];
29
+ };
30
+
31
+ export const versions = (
32
+ target: any,
33
+ ): Array<string | typeof VERSION_NEUTRAL> | undefined => {
34
+ const value: VersionValue | undefined = Reflect.getMetadata(
35
+ VERSION_METADATA,
36
+ target,
37
+ );
38
+ return value === undefined
39
+ ? undefined
40
+ : Array.isArray(value)
41
+ ? value
42
+ : [value];
43
+ };
44
+ }
@@ -1,25 +1,25 @@
1
- import { MapUtil } from "../utils/MapUtil";
2
-
3
- export namespace SecurityAnalyzer {
4
- export const merge = (...entire: Record<string, string[]>[]) => {
5
- const dict: Map<string | typeof none, Set<string>> = new Map();
6
- for (const obj of entire) {
7
- const entries = Object.entries(obj);
8
- for (const [key, value] of entries) {
9
- const set = MapUtil.take(dict, key, () => new Set());
10
- for (const val of value) set.add(val);
11
- }
12
- if (entries.length === 0) MapUtil.take(dict, none, () => new Set());
13
- }
14
- const output: Record<string, string[]>[] = [];
15
- for (const [key, set] of dict)
16
- key === none
17
- ? output.push({})
18
- : output.push({
19
- [key]: [...set],
20
- });
21
- return output;
22
- };
23
-
24
- const none = Symbol("none");
25
- }
1
+ import { MapUtil } from "../utils/MapUtil";
2
+
3
+ export namespace SecurityAnalyzer {
4
+ export const merge = (...entire: Record<string, string[]>[]) => {
5
+ const dict: Map<string | typeof none, Set<string>> = new Map();
6
+ for (const obj of entire) {
7
+ const entries = Object.entries(obj);
8
+ for (const [key, value] of entries) {
9
+ const set = MapUtil.take(dict, key, () => new Set());
10
+ for (const val of value) set.add(val);
11
+ }
12
+ if (entries.length === 0) MapUtil.take(dict, none, () => new Set());
13
+ }
14
+ const output: Record<string, string[]>[] = [];
15
+ for (const [key, set] of dict)
16
+ key === none
17
+ ? output.push({})
18
+ : output.push({
19
+ [key]: [...set],
20
+ });
21
+ return output;
22
+ };
23
+
24
+ const none = Symbol("none");
25
+ }
@@ -0,0 +1,34 @@
1
+ import { IReflectController } from "../structures/IReflectController";
2
+ import { IReflectMcpOperation } from "../structures/IReflectMcpOperation";
3
+ import { ITypedMcpRoute } from "../structures/ITypedMcpRoute";
4
+
5
+ export namespace TypedMcpRouteAnalyzer {
6
+ export const analyze = (props: {
7
+ controller: IReflectController;
8
+ operation: IReflectMcpOperation;
9
+ }): ITypedMcpRoute[] => [
10
+ {
11
+ protocol: "mcp",
12
+ controller: props.controller,
13
+ name: props.operation.name,
14
+ toolName: props.operation.toolName,
15
+ title: props.operation.title,
16
+ toolDescription: props.operation.toolDescription,
17
+ accessor: accessor(props.operation.toolName),
18
+ function: props.operation.function,
19
+ input: props.operation.parameters[0] ?? null,
20
+ returnType: props.operation.returnType,
21
+ inputSchema: props.operation.inputSchema,
22
+ outputSchema: props.operation.outputSchema,
23
+ annotations: props.operation.annotations,
24
+ imports: props.operation.imports,
25
+ description: props.operation.description,
26
+ jsDocTags: props.operation.jsDocTags,
27
+ },
28
+ ];
29
+
30
+ const accessor = (toolName: string): string[] => {
31
+ const safe = toolName.replace(/[^A-Za-z0-9_$]/g, "_");
32
+ return ["mcp", safe];
33
+ };
34
+ }
@@ -1,29 +1,29 @@
1
- import { IOperationMetadata } from "../structures/IOperationMetadata";
2
-
3
- /**
4
- * Carries the compile-time operation metadata the SDK / Swagger / e2e
5
- * generators read through `Reflect.getMetadata("nestia/OperationMetadata")`.
6
- *
7
- * The `@nestia/sdk` native transform injects this decorator as a synthesized
8
- * AST node, so its argument is a single JSON string literal rather than an
9
- * object literal — keeping the constructed node tree minimal. The string is
10
- * parsed once here at module-evaluation time. A pre-parsed `IOperationMetadata`
11
- * object is still accepted for hand-written or test usage.
12
- */
13
- export function OperationMetadata(
14
- metadata: IOperationMetadata | string,
15
- ): MethodDecorator {
16
- const parsed: IOperationMetadata =
17
- typeof metadata === "string"
18
- ? (JSON.parse(metadata) as IOperationMetadata)
19
- : metadata;
20
- return function OperationMetadata(target, propertyKey, descriptor) {
21
- Reflect.defineMetadata(
22
- "nestia/OperationMetadata",
23
- parsed,
24
- target,
25
- propertyKey,
26
- );
27
- return descriptor;
28
- };
29
- }
1
+ import { IOperationMetadata } from "../structures/IOperationMetadata";
2
+
3
+ /**
4
+ * Carries the compile-time operation metadata the SDK / Swagger / e2e
5
+ * generators read through `Reflect.getMetadata("nestia/OperationMetadata")`.
6
+ *
7
+ * The `@nestia/sdk` native transform injects this decorator as a synthesized
8
+ * AST node, so its argument is a single JSON string literal rather than an
9
+ * object literal — keeping the constructed node tree minimal. The string is
10
+ * parsed once here at module-evaluation time. A pre-parsed `IOperationMetadata`
11
+ * object is still accepted for hand-written or test usage.
12
+ */
13
+ export function OperationMetadata(
14
+ metadata: IOperationMetadata | string,
15
+ ): MethodDecorator {
16
+ const parsed: IOperationMetadata =
17
+ typeof metadata === "string"
18
+ ? (JSON.parse(metadata) as IOperationMetadata)
19
+ : metadata;
20
+ return function OperationMetadata(target, propertyKey, descriptor) {
21
+ Reflect.defineMetadata(
22
+ "nestia/OperationMetadata",
23
+ parsed,
24
+ target,
25
+ propertyKey,
26
+ );
27
+ return descriptor;
28
+ };
29
+ }