@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,350 +1,350 @@
1
- import { SwaggerExample } from "@nestia/core";
2
- import { ROUTE_ARGS_METADATA } from "@nestjs/common/constants";
3
- import { RouteParamtypes } from "@nestjs/common/enums/route-paramtypes.enum";
4
- import {
5
- HttpFormDataProgrammer,
6
- HttpHeadersProgrammer,
7
- HttpParameterProgrammer,
8
- HttpQueryProgrammer,
9
- JsonMetadataFactory,
10
- } from "../internal/legacy";
11
-
12
- import { IReflectController } from "../structures/IReflectController";
13
- import { IReflectHttpOperationParameter } from "../structures/IReflectHttpOperationParameter";
14
- import { IReflectOperationError } from "../structures/IReflectOperationError";
15
- import { IOperationMetadata } from "../structures/IOperationMetadata";
16
- import { TextPlainValidator } from "../validators/TextPlainValidator";
17
- import { HttpHeadersValidator } from "../validators/HttpHeadersValidator";
18
- import { HttpQueryValidator } from "../validators/HttpQueryValidator";
19
-
20
- export namespace ReflectHttpOperationParameterAnalyzer {
21
- export interface IContext {
22
- controller: IReflectController;
23
- function: Function;
24
- functionName: string;
25
- httpMethod: string;
26
- metadata: IOperationMetadata;
27
- errors: IReflectOperationError[];
28
- }
29
- export const analyze = (ctx: IContext): IReflectHttpOperationParameter[] => {
30
- const preconfigured: IReflectHttpOperationParameter.IPreconfigured[] =
31
- analyzePreconfigured(ctx);
32
- const errors: IReflectOperationError[] = [];
33
-
34
- //----
35
- // FIND CONTRADICTIONS
36
- //----
37
- // GET AND HEAD METHOD
38
- const contradictErrors: string[] = [];
39
- const contradict = (message: string) => {
40
- contradictErrors.push(message);
41
- };
42
- if (
43
- (ctx.httpMethod === "GET" || ctx.httpMethod === "HEAD") &&
44
- preconfigured.some((x) => x.category === "body")
45
- )
46
- contradict(`@Body() is not allowed in the ${ctx.httpMethod} method.`);
47
-
48
- // FIND DUPLICATED BODY
49
- if (
50
- preconfigured.filter(
51
- (x) => x.category === "body" && x.field === undefined,
52
- ).length > 1
53
- )
54
- contradict(`Duplicated @Body() is not allowed.`);
55
- if (
56
- preconfigured.filter(
57
- (x) => x.category === "query" && x.field === undefined,
58
- ).length > 1
59
- )
60
- contradict(`Duplicated @Query() without field name is not allowed.`);
61
- if (
62
- preconfigured.filter(
63
- (x) => x.category === "headers" && x.field === undefined,
64
- ).length > 1
65
- )
66
- contradict(`Duplicated @Headers() without field name is not allowed.`);
67
-
68
- // FIND DUPLICATED FIELDS
69
- if (
70
- isUnique(
71
- preconfigured
72
- .filter((x) => x.category === "param")
73
- .map((x) => x.field)
74
- .filter((field) => field !== undefined),
75
- ) === false
76
- )
77
- contradict(`Duplicated field names of path are not allowed.`);
78
- if (
79
- isUnique(
80
- preconfigured
81
- .filter((x) => x.category === "query")
82
- .map((x) => x.field)
83
- .filter((field) => field !== undefined),
84
- ) === false
85
- )
86
- contradict(`Duplicated field names of query are not allowed.`);
87
- if (
88
- isUnique(
89
- preconfigured
90
- .filter((x) => x.category === "headers")
91
- .map((x) => x.field)
92
- .filter((field) => field !== undefined),
93
- ) === false
94
- )
95
- contradict(`Duplicated field names of headers are not allowed.`);
96
- if (contradictErrors.length)
97
- errors.push({
98
- file: ctx.controller.file,
99
- class: ctx.controller.class.name,
100
- function: ctx.functionName,
101
- from: "",
102
- contents: contradictErrors,
103
- });
104
-
105
- //----
106
- // COMPOSE PARAMETERS
107
- //----
108
- const parameters: IReflectHttpOperationParameter[] = preconfigured
109
- .map((p): IReflectHttpOperationParameter | null => {
110
- // METADATA INFO
111
- const pErrorContents: Array<string | IOperationMetadata.IError> = [];
112
- const matched: IOperationMetadata.IParameter | undefined =
113
- ctx.metadata.parameters.find((x) => x.index === p.index);
114
- const report = () => {
115
- errors.push({
116
- file: ctx.controller.file,
117
- class: ctx.controller.class.name,
118
- function: ctx.functionName,
119
- from: `parameter ${matched ? JSON.stringify(matched.name) : `of ${p.index} th`}`,
120
- contents: pErrorContents,
121
- });
122
- return null;
123
- };
124
-
125
- // VALIDATE TYPE
126
- if (matched === undefined)
127
- pErrorContents.push(`Unable to find parameter type.`);
128
- else if (matched.type === null)
129
- pErrorContents.push(`Failed to get the type info.`);
130
-
131
- // CONSIDER KIND
132
- const schema: IOperationMetadata.ISchema | null = (() => {
133
- if (matched === undefined) return null;
134
- const result =
135
- p.category === "body" &&
136
- (p.contentType === "application/json" || p.encrypted === true)
137
- ? matched.primitive
138
- : matched.resolved;
139
- return result.success ? result.data : null;
140
- })();
141
- if (p.category === "body" && p.field !== undefined)
142
- pErrorContents.push(`@Body() must not have a field name.`);
143
- else if (p.category === "param" && p.field === undefined)
144
- pErrorContents.push(`@Param() must have a field name.`);
145
-
146
- if (pErrorContents.length) return report();
147
- else if (
148
- matched === undefined ||
149
- matched.type === null ||
150
- schema === null
151
- )
152
- return null; // unreachable
153
-
154
- const example: SwaggerExample.IData<any> | undefined = (
155
- Reflect.getMetadata(
156
- "nestia/SwaggerExample/Parameters",
157
- ctx.controller.class.prototype,
158
- ctx.functionName,
159
- ) ?? []
160
- ).find((x: SwaggerExample.IData<any>) => x.index === matched.index);
161
-
162
- // COMPOSITION
163
- if (p.category === "param")
164
- return {
165
- category: p.category,
166
- index: p.index,
167
- field: p.field!,
168
- name: matched.name,
169
- type: matched.type,
170
- validate: HttpParameterProgrammer.validate,
171
- description: matched.description,
172
- jsDocTags: matched.jsDocTags,
173
- example: example?.example,
174
- examples: example?.examples,
175
- ...schema,
176
- };
177
- else if (p.category === "query")
178
- return {
179
- category: p.category,
180
- index: p.index,
181
- field: p.field ?? null,
182
- name: matched.name,
183
- type: matched.type,
184
- validate: p.field
185
- ? HttpQueryValidator.validate
186
- : HttpQueryProgrammer.validate,
187
- description: matched.description,
188
- jsDocTags: matched.jsDocTags,
189
- example: example?.example,
190
- examples: example?.examples,
191
- ...schema,
192
- };
193
- else if (p.category === "headers")
194
- return {
195
- category: p.category,
196
- index: p.index,
197
- field: p.field ?? null,
198
- name: matched.name,
199
- type: matched.type,
200
- validate: p.field
201
- ? HttpHeadersValidator.validate
202
- : HttpHeadersProgrammer.validate,
203
- description: matched.description,
204
- jsDocTags: matched.jsDocTags,
205
- example: example?.example,
206
- examples: example?.examples,
207
- ...schema,
208
- };
209
- else if (p.category === "body")
210
- return {
211
- category: p.category,
212
- index: p.index,
213
- encrypted: !!p.encrypted,
214
- contentType: p.contentType,
215
- name: matched.name,
216
- type: matched.type,
217
- validate:
218
- p.contentType === "application/json" || p.encrypted === true
219
- ? JsonMetadataFactory.validate
220
- : p.contentType === "application/x-www-form-urlencoded"
221
- ? HttpQueryProgrammer.validate
222
- : p.contentType === "multipart/form-data"
223
- ? HttpFormDataProgrammer.validate
224
- : TextPlainValidator.validate,
225
- description: matched.description,
226
- jsDocTags: matched.jsDocTags,
227
- example: example?.example,
228
- examples: example?.examples,
229
- ...schema,
230
- };
231
- else {
232
- pErrorContents.push(`Unknown kind of the parameter.`);
233
- return report();
234
- }
235
- })
236
- .filter((x): x is IReflectHttpOperationParameter => x !== null);
237
-
238
- if (errors.length) ctx.errors.push(...errors);
239
- return parameters;
240
- };
241
-
242
- const analyzePreconfigured = (
243
- props: IContext,
244
- ): IReflectHttpOperationParameter.IPreconfigured[] => {
245
- const dict: NestParameters | undefined = Reflect.getMetadata(
246
- ROUTE_ARGS_METADATA,
247
- props.controller.class,
248
- props.functionName,
249
- );
250
- if (dict === undefined) return [];
251
- return Object.entries(dict)
252
- .map(([key, param]) => analyzeHttpParameter(key, param))
253
- .filter(
254
- (x): x is IReflectHttpOperationParameter.IPreconfigured => x !== null,
255
- )
256
- .sort((x, y) => x.index - y.index);
257
- };
258
-
259
- const analyzeHttpParameter = (
260
- key: string,
261
- param: INestParam,
262
- ): IReflectHttpOperationParameter.IPreconfigured | null => {
263
- const symbol: string = key.split(":")[0]!;
264
- if (symbol.indexOf("__custom") !== -1) return analyzeCustomParameter(param);
265
-
266
- const category:
267
- | IReflectHttpOperationParameter.IPreconfigured["category"]
268
- | null = getNestParamType(Number(symbol[0]) as RouteParamtypes);
269
- if (category === null) return null;
270
- if (category === "body")
271
- return {
272
- category: "body",
273
- index: param.index,
274
- field: param.data,
275
- contentType: "application/json",
276
- };
277
- else
278
- return {
279
- category,
280
- index: param.index,
281
- field: param.data,
282
- };
283
- };
284
-
285
- const analyzeCustomParameter = (
286
- param: INestParam,
287
- ): IReflectHttpOperationParameter.IPreconfigured | null => {
288
- if (param.factory === undefined) return null;
289
- else if (
290
- param.factory.name === "EncryptedBody" ||
291
- param.factory.name === "PlainBody" ||
292
- param.factory.name === "TypedQueryBody" ||
293
- param.factory.name === "TypedBody" ||
294
- param.factory.name === "TypedFormDataBody"
295
- )
296
- return {
297
- category: "body",
298
- index: param.index,
299
- encrypted: param.factory.name === "EncryptedBody",
300
- contentType:
301
- param.factory.name === "PlainBody" ||
302
- param.factory.name === "EncryptedBody"
303
- ? "text/plain"
304
- : param.factory.name === "TypedQueryBody"
305
- ? "application/x-www-form-urlencoded"
306
- : param.factory.name === "TypedFormDataBody"
307
- ? "multipart/form-data"
308
- : "application/json",
309
- };
310
- else if (param.factory.name === "TypedHeaders")
311
- return {
312
- category: "headers",
313
- index: param.index,
314
- field: param.data,
315
- };
316
- else if (param.factory.name === "TypedParam")
317
- return {
318
- category: "param",
319
- index: param.index,
320
- field: param.data,
321
- };
322
- else if (param.factory.name === "TypedQuery")
323
- return {
324
- category: "query",
325
- index: param.index,
326
- field: undefined,
327
- };
328
- else return null;
329
- };
330
-
331
- const isUnique = (values: string[]) => new Set(values).size === values.length;
332
- }
333
-
334
- type NestParameters = {
335
- [key: string]: INestParam;
336
- };
337
- interface INestParam {
338
- name: string;
339
- index: number;
340
- factory?: (...args: any) => any;
341
- data: string | undefined;
342
- }
343
-
344
- const getNestParamType = (value: RouteParamtypes) => {
345
- if (value === RouteParamtypes.BODY) return "body";
346
- else if (value === RouteParamtypes.HEADERS) return "headers";
347
- else if (value === RouteParamtypes.QUERY) return "query";
348
- else if (value === RouteParamtypes.PARAM) return "param";
349
- return null;
350
- };
1
+ import { SwaggerExample } from "@nestia/core";
2
+ import { ROUTE_ARGS_METADATA } from "@nestjs/common/constants";
3
+ import { RouteParamtypes } from "@nestjs/common/enums/route-paramtypes.enum";
4
+ import {
5
+ HttpFormDataProgrammer,
6
+ HttpHeadersProgrammer,
7
+ HttpParameterProgrammer,
8
+ HttpQueryProgrammer,
9
+ JsonMetadataFactory,
10
+ } from "../internal/legacy";
11
+
12
+ import { IReflectController } from "../structures/IReflectController";
13
+ import { IReflectHttpOperationParameter } from "../structures/IReflectHttpOperationParameter";
14
+ import { IReflectOperationError } from "../structures/IReflectOperationError";
15
+ import { IOperationMetadata } from "../structures/IOperationMetadata";
16
+ import { TextPlainValidator } from "../validators/TextPlainValidator";
17
+ import { HttpHeadersValidator } from "../validators/HttpHeadersValidator";
18
+ import { HttpQueryValidator } from "../validators/HttpQueryValidator";
19
+
20
+ export namespace ReflectHttpOperationParameterAnalyzer {
21
+ export interface IContext {
22
+ controller: IReflectController;
23
+ function: Function;
24
+ functionName: string;
25
+ httpMethod: string;
26
+ metadata: IOperationMetadata;
27
+ errors: IReflectOperationError[];
28
+ }
29
+ export const analyze = (ctx: IContext): IReflectHttpOperationParameter[] => {
30
+ const preconfigured: IReflectHttpOperationParameter.IPreconfigured[] =
31
+ analyzePreconfigured(ctx);
32
+ const errors: IReflectOperationError[] = [];
33
+
34
+ //----
35
+ // FIND CONTRADICTIONS
36
+ //----
37
+ // GET AND HEAD METHOD
38
+ const contradictErrors: string[] = [];
39
+ const contradict = (message: string) => {
40
+ contradictErrors.push(message);
41
+ };
42
+ if (
43
+ (ctx.httpMethod === "GET" || ctx.httpMethod === "HEAD") &&
44
+ preconfigured.some((x) => x.category === "body")
45
+ )
46
+ contradict(`@Body() is not allowed in the ${ctx.httpMethod} method.`);
47
+
48
+ // FIND DUPLICATED BODY
49
+ if (
50
+ preconfigured.filter(
51
+ (x) => x.category === "body" && x.field === undefined,
52
+ ).length > 1
53
+ )
54
+ contradict(`Duplicated @Body() is not allowed.`);
55
+ if (
56
+ preconfigured.filter(
57
+ (x) => x.category === "query" && x.field === undefined,
58
+ ).length > 1
59
+ )
60
+ contradict(`Duplicated @Query() without field name is not allowed.`);
61
+ if (
62
+ preconfigured.filter(
63
+ (x) => x.category === "headers" && x.field === undefined,
64
+ ).length > 1
65
+ )
66
+ contradict(`Duplicated @Headers() without field name is not allowed.`);
67
+
68
+ // FIND DUPLICATED FIELDS
69
+ if (
70
+ isUnique(
71
+ preconfigured
72
+ .filter((x) => x.category === "param")
73
+ .map((x) => x.field)
74
+ .filter((field) => field !== undefined),
75
+ ) === false
76
+ )
77
+ contradict(`Duplicated field names of path are not allowed.`);
78
+ if (
79
+ isUnique(
80
+ preconfigured
81
+ .filter((x) => x.category === "query")
82
+ .map((x) => x.field)
83
+ .filter((field) => field !== undefined),
84
+ ) === false
85
+ )
86
+ contradict(`Duplicated field names of query are not allowed.`);
87
+ if (
88
+ isUnique(
89
+ preconfigured
90
+ .filter((x) => x.category === "headers")
91
+ .map((x) => x.field)
92
+ .filter((field) => field !== undefined),
93
+ ) === false
94
+ )
95
+ contradict(`Duplicated field names of headers are not allowed.`);
96
+ if (contradictErrors.length)
97
+ errors.push({
98
+ file: ctx.controller.file,
99
+ class: ctx.controller.class.name,
100
+ function: ctx.functionName,
101
+ from: "",
102
+ contents: contradictErrors,
103
+ });
104
+
105
+ //----
106
+ // COMPOSE PARAMETERS
107
+ //----
108
+ const parameters: IReflectHttpOperationParameter[] = preconfigured
109
+ .map((p): IReflectHttpOperationParameter | null => {
110
+ // METADATA INFO
111
+ const pErrorContents: Array<string | IOperationMetadata.IError> = [];
112
+ const matched: IOperationMetadata.IParameter | undefined =
113
+ ctx.metadata.parameters.find((x) => x.index === p.index);
114
+ const report = () => {
115
+ errors.push({
116
+ file: ctx.controller.file,
117
+ class: ctx.controller.class.name,
118
+ function: ctx.functionName,
119
+ from: `parameter ${matched ? JSON.stringify(matched.name) : `of ${p.index} th`}`,
120
+ contents: pErrorContents,
121
+ });
122
+ return null;
123
+ };
124
+
125
+ // VALIDATE TYPE
126
+ if (matched === undefined)
127
+ pErrorContents.push(`Unable to find parameter type.`);
128
+ else if (matched.type === null)
129
+ pErrorContents.push(`Failed to get the type info.`);
130
+
131
+ // CONSIDER KIND
132
+ const schema: IOperationMetadata.ISchema | null = (() => {
133
+ if (matched === undefined) return null;
134
+ const result =
135
+ p.category === "body" &&
136
+ (p.contentType === "application/json" || p.encrypted === true)
137
+ ? matched.primitive
138
+ : matched.resolved;
139
+ return result.success ? result.data : null;
140
+ })();
141
+ if (p.category === "body" && p.field !== undefined)
142
+ pErrorContents.push(`@Body() must not have a field name.`);
143
+ else if (p.category === "param" && p.field === undefined)
144
+ pErrorContents.push(`@Param() must have a field name.`);
145
+
146
+ if (pErrorContents.length) return report();
147
+ else if (
148
+ matched === undefined ||
149
+ matched.type === null ||
150
+ schema === null
151
+ )
152
+ return null; // unreachable
153
+
154
+ const example: SwaggerExample.IData<any> | undefined = (
155
+ Reflect.getMetadata(
156
+ "nestia/SwaggerExample/Parameters",
157
+ ctx.controller.class.prototype,
158
+ ctx.functionName,
159
+ ) ?? []
160
+ ).find((x: SwaggerExample.IData<any>) => x.index === matched.index);
161
+
162
+ // COMPOSITION
163
+ if (p.category === "param")
164
+ return {
165
+ category: p.category,
166
+ index: p.index,
167
+ field: p.field!,
168
+ name: matched.name,
169
+ type: matched.type,
170
+ validate: HttpParameterProgrammer.validate,
171
+ description: matched.description,
172
+ jsDocTags: matched.jsDocTags,
173
+ example: example?.example,
174
+ examples: example?.examples,
175
+ ...schema,
176
+ };
177
+ else if (p.category === "query")
178
+ return {
179
+ category: p.category,
180
+ index: p.index,
181
+ field: p.field ?? null,
182
+ name: matched.name,
183
+ type: matched.type,
184
+ validate: p.field
185
+ ? HttpQueryValidator.validate
186
+ : HttpQueryProgrammer.validate,
187
+ description: matched.description,
188
+ jsDocTags: matched.jsDocTags,
189
+ example: example?.example,
190
+ examples: example?.examples,
191
+ ...schema,
192
+ };
193
+ else if (p.category === "headers")
194
+ return {
195
+ category: p.category,
196
+ index: p.index,
197
+ field: p.field ?? null,
198
+ name: matched.name,
199
+ type: matched.type,
200
+ validate: p.field
201
+ ? HttpHeadersValidator.validate
202
+ : HttpHeadersProgrammer.validate,
203
+ description: matched.description,
204
+ jsDocTags: matched.jsDocTags,
205
+ example: example?.example,
206
+ examples: example?.examples,
207
+ ...schema,
208
+ };
209
+ else if (p.category === "body")
210
+ return {
211
+ category: p.category,
212
+ index: p.index,
213
+ encrypted: !!p.encrypted,
214
+ contentType: p.contentType,
215
+ name: matched.name,
216
+ type: matched.type,
217
+ validate:
218
+ p.contentType === "application/json" || p.encrypted === true
219
+ ? JsonMetadataFactory.validate
220
+ : p.contentType === "application/x-www-form-urlencoded"
221
+ ? HttpQueryProgrammer.validate
222
+ : p.contentType === "multipart/form-data"
223
+ ? HttpFormDataProgrammer.validate
224
+ : TextPlainValidator.validate,
225
+ description: matched.description,
226
+ jsDocTags: matched.jsDocTags,
227
+ example: example?.example,
228
+ examples: example?.examples,
229
+ ...schema,
230
+ };
231
+ else {
232
+ pErrorContents.push(`Unknown kind of the parameter.`);
233
+ return report();
234
+ }
235
+ })
236
+ .filter((x): x is IReflectHttpOperationParameter => x !== null);
237
+
238
+ if (errors.length) ctx.errors.push(...errors);
239
+ return parameters;
240
+ };
241
+
242
+ const analyzePreconfigured = (
243
+ props: IContext,
244
+ ): IReflectHttpOperationParameter.IPreconfigured[] => {
245
+ const dict: NestParameters | undefined = Reflect.getMetadata(
246
+ ROUTE_ARGS_METADATA,
247
+ props.controller.class,
248
+ props.functionName,
249
+ );
250
+ if (dict === undefined) return [];
251
+ return Object.entries(dict)
252
+ .map(([key, param]) => analyzeHttpParameter(key, param))
253
+ .filter(
254
+ (x): x is IReflectHttpOperationParameter.IPreconfigured => x !== null,
255
+ )
256
+ .sort((x, y) => x.index - y.index);
257
+ };
258
+
259
+ const analyzeHttpParameter = (
260
+ key: string,
261
+ param: INestParam,
262
+ ): IReflectHttpOperationParameter.IPreconfigured | null => {
263
+ const symbol: string = key.split(":")[0]!;
264
+ if (symbol.indexOf("__custom") !== -1) return analyzeCustomParameter(param);
265
+
266
+ const category:
267
+ | IReflectHttpOperationParameter.IPreconfigured["category"]
268
+ | null = getNestParamType(Number(symbol[0]) as RouteParamtypes);
269
+ if (category === null) return null;
270
+ if (category === "body")
271
+ return {
272
+ category: "body",
273
+ index: param.index,
274
+ field: param.data,
275
+ contentType: "application/json",
276
+ };
277
+ else
278
+ return {
279
+ category,
280
+ index: param.index,
281
+ field: param.data,
282
+ };
283
+ };
284
+
285
+ const analyzeCustomParameter = (
286
+ param: INestParam,
287
+ ): IReflectHttpOperationParameter.IPreconfigured | null => {
288
+ if (param.factory === undefined) return null;
289
+ else if (
290
+ param.factory.name === "EncryptedBody" ||
291
+ param.factory.name === "PlainBody" ||
292
+ param.factory.name === "TypedQueryBody" ||
293
+ param.factory.name === "TypedBody" ||
294
+ param.factory.name === "TypedFormDataBody"
295
+ )
296
+ return {
297
+ category: "body",
298
+ index: param.index,
299
+ encrypted: param.factory.name === "EncryptedBody",
300
+ contentType:
301
+ param.factory.name === "PlainBody" ||
302
+ param.factory.name === "EncryptedBody"
303
+ ? "text/plain"
304
+ : param.factory.name === "TypedQueryBody"
305
+ ? "application/x-www-form-urlencoded"
306
+ : param.factory.name === "TypedFormDataBody"
307
+ ? "multipart/form-data"
308
+ : "application/json",
309
+ };
310
+ else if (param.factory.name === "TypedHeaders")
311
+ return {
312
+ category: "headers",
313
+ index: param.index,
314
+ field: param.data,
315
+ };
316
+ else if (param.factory.name === "TypedParam")
317
+ return {
318
+ category: "param",
319
+ index: param.index,
320
+ field: param.data,
321
+ };
322
+ else if (param.factory.name === "TypedQuery")
323
+ return {
324
+ category: "query",
325
+ index: param.index,
326
+ field: undefined,
327
+ };
328
+ else return null;
329
+ };
330
+
331
+ const isUnique = (values: string[]) => new Set(values).size === values.length;
332
+ }
333
+
334
+ type NestParameters = {
335
+ [key: string]: INestParam;
336
+ };
337
+ interface INestParam {
338
+ name: string;
339
+ index: number;
340
+ factory?: (...args: any) => any;
341
+ data: string | undefined;
342
+ }
343
+
344
+ const getNestParamType = (value: RouteParamtypes) => {
345
+ if (value === RouteParamtypes.BODY) return "body";
346
+ else if (value === RouteParamtypes.HEADERS) return "headers";
347
+ else if (value === RouteParamtypes.QUERY) return "query";
348
+ else if (value === RouteParamtypes.PARAM) return "param";
349
+ return null;
350
+ };