@nestia/sdk 14.0.1 → 14.0.3

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 (377) hide show
  1. package/assets/bundle/distribute/build-sdk.cjs +28 -0
  2. package/assets/bundle/distribute/package.json +6 -2
  3. package/lib/INestiaConfig.d.ts +55 -24
  4. package/lib/NestiaSdkApplication.d.ts +60 -0
  5. package/lib/NestiaSdkApplication.js +63 -5
  6. package/lib/NestiaSdkApplication.js.map +1 -1
  7. package/lib/NestiaSwaggerComposer.d.ts +21 -0
  8. package/lib/NestiaSwaggerComposer.js +21 -3
  9. package/lib/NestiaSwaggerComposer.js.map +1 -1
  10. package/lib/analyses/AccessorAnalyzer.d.ts +26 -0
  11. package/lib/analyses/AccessorAnalyzer.js +26 -0
  12. package/lib/analyses/AccessorAnalyzer.js.map +1 -1
  13. package/lib/analyses/ConfigAnalyzer.d.ts +41 -0
  14. package/lib/analyses/ConfigAnalyzer.js +57 -80
  15. package/lib/analyses/ConfigAnalyzer.js.map +1 -1
  16. package/lib/analyses/ImportAnalyzer.d.ts +25 -0
  17. package/lib/analyses/ImportAnalyzer.js +25 -0
  18. package/lib/analyses/ImportAnalyzer.js.map +1 -1
  19. package/lib/analyses/ParameterNameAnalyzer.d.ts +24 -0
  20. package/lib/analyses/ParameterNameAnalyzer.js +15 -0
  21. package/lib/analyses/ParameterNameAnalyzer.js.map +1 -1
  22. package/lib/analyses/PathAnalyzer.d.ts +63 -1
  23. package/lib/analyses/PathAnalyzer.js +54 -9
  24. package/lib/analyses/PathAnalyzer.js.map +1 -1
  25. package/lib/analyses/ReflectControllerAnalyzer.d.ts +32 -0
  26. package/lib/analyses/ReflectControllerAnalyzer.js +22 -0
  27. package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -1
  28. package/lib/analyses/ReflectHttpOperationAnalyzer.d.ts +29 -0
  29. package/lib/analyses/ReflectHttpOperationAnalyzer.js +28 -17
  30. package/lib/analyses/ReflectHttpOperationAnalyzer.js.map +1 -1
  31. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.d.ts +31 -0
  32. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js +21 -0
  33. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js.map +1 -1
  34. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.d.ts +31 -0
  35. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js +21 -0
  36. package/lib/analyses/ReflectHttpOperationParameterAnalyzer.js.map +1 -1
  37. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.d.ts +32 -0
  38. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js +22 -0
  39. package/lib/analyses/ReflectHttpOperationResponseAnalyzer.js.map +1 -1
  40. package/lib/analyses/ReflectMcpOperationAnalyzer.d.ts +29 -0
  41. package/lib/analyses/ReflectMcpOperationAnalyzer.js +30 -9
  42. package/lib/analyses/ReflectMcpOperationAnalyzer.js.map +1 -1
  43. package/lib/analyses/ReflectMetadataAnalyzer.d.ts +47 -0
  44. package/lib/analyses/ReflectMetadataAnalyzer.js +47 -0
  45. package/lib/analyses/ReflectMetadataAnalyzer.js.map +1 -1
  46. package/lib/analyses/ReflectWebSocketOperationAnalyzer.d.ts +29 -0
  47. package/lib/analyses/ReflectWebSocketOperationAnalyzer.js +22 -5
  48. package/lib/analyses/ReflectWebSocketOperationAnalyzer.js.map +1 -1
  49. package/lib/analyses/SecurityAnalyzer.d.ts +15 -0
  50. package/lib/analyses/SecurityAnalyzer.js +15 -0
  51. package/lib/analyses/SecurityAnalyzer.js.map +1 -1
  52. package/lib/analyses/SwaggerExampleAnalyzer.d.ts +16 -0
  53. package/lib/analyses/SwaggerExampleAnalyzer.js +16 -0
  54. package/lib/analyses/SwaggerExampleAnalyzer.js.map +1 -1
  55. package/lib/analyses/TypedHttpRouteAnalyzer.d.ts +41 -3
  56. package/lib/analyses/TypedHttpRouteAnalyzer.js +172 -157
  57. package/lib/analyses/TypedHttpRouteAnalyzer.js.map +1 -1
  58. package/lib/analyses/TypedMcpRouteAnalyzer.d.ts +29 -0
  59. package/lib/analyses/TypedMcpRouteAnalyzer.js +152 -20
  60. package/lib/analyses/TypedMcpRouteAnalyzer.js.map +1 -1
  61. package/lib/analyses/TypedWebSocketRouteAnalyzer.d.ts +19 -0
  62. package/lib/analyses/TypedWebSocketRouteAnalyzer.js +19 -0
  63. package/lib/analyses/TypedWebSocketRouteAnalyzer.js.map +1 -1
  64. package/lib/decorators/OperationMetadata.d.ts +6 -0
  65. package/lib/decorators/OperationMetadata.js +6 -0
  66. package/lib/decorators/OperationMetadata.js.map +1 -1
  67. package/lib/executable/internal/CommandParser.d.ts +19 -0
  68. package/lib/executable/internal/CommandParser.js +19 -0
  69. package/lib/executable/internal/CommandParser.js.map +1 -1
  70. package/lib/executable/internal/NestiaConfigLoader.d.ts +56 -0
  71. package/lib/executable/internal/NestiaConfigLoader.js +48 -42
  72. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  73. package/lib/executable/internal/NestiaSdkCommand.d.ts +60 -0
  74. package/lib/executable/internal/NestiaSdkCommand.js +95 -3
  75. package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
  76. package/lib/executable/internal/NestiaSdkWatcher.d.ts +81 -0
  77. package/lib/executable/internal/NestiaSdkWatcher.js +122 -38
  78. package/lib/executable/internal/NestiaSdkWatcher.js.map +1 -1
  79. package/lib/executable/internal/NestiaSwaggerWatch.d.ts +80 -0
  80. package/lib/executable/internal/NestiaSwaggerWatch.js +308 -0
  81. package/lib/executable/internal/NestiaSwaggerWatch.js.map +1 -0
  82. package/lib/factories/ExpressionFactory.d.ts +17 -2
  83. package/lib/factories/ExpressionFactory.js +17 -2
  84. package/lib/factories/ExpressionFactory.js.map +1 -1
  85. package/lib/factories/IdentifierFactory.d.ts +24 -0
  86. package/lib/factories/IdentifierFactory.js +24 -0
  87. package/lib/factories/IdentifierFactory.js.map +1 -1
  88. package/lib/factories/LiteralFactory.d.ts +22 -4
  89. package/lib/factories/LiteralFactory.js +30 -10
  90. package/lib/factories/LiteralFactory.js.map +1 -1
  91. package/lib/factories/StatementFactory.d.ts +28 -1
  92. package/lib/factories/StatementFactory.js +28 -1
  93. package/lib/factories/StatementFactory.js.map +1 -1
  94. package/lib/factories/TypeFactory.d.ts +24 -0
  95. package/lib/factories/TypeFactory.js +15 -0
  96. package/lib/factories/TypeFactory.js.map +1 -1
  97. package/lib/generates/CloneGenerator.d.ts +22 -0
  98. package/lib/generates/CloneGenerator.js +26 -5
  99. package/lib/generates/CloneGenerator.js.map +1 -1
  100. package/lib/generates/E2eGenerator.d.ts +19 -0
  101. package/lib/generates/E2eGenerator.js +19 -0
  102. package/lib/generates/E2eGenerator.js.map +1 -1
  103. package/lib/generates/SdkGenerator.d.ts +38 -0
  104. package/lib/generates/SdkGenerator.js +40 -2
  105. package/lib/generates/SdkGenerator.js.map +1 -1
  106. package/lib/generates/SwaggerGenerator.d.ts +36 -6
  107. package/lib/generates/SwaggerGenerator.js +55 -13
  108. package/lib/generates/SwaggerGenerator.js.map +1 -1
  109. package/lib/generates/internal/E2eFileProgrammer.d.ts +19 -0
  110. package/lib/generates/internal/E2eFileProgrammer.js +20 -1
  111. package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
  112. package/lib/generates/internal/FilePrinter.d.ts +43 -0
  113. package/lib/generates/internal/FilePrinter.js +43 -0
  114. package/lib/generates/internal/FilePrinter.js.map +1 -1
  115. package/lib/generates/internal/ImportDictionary.d.ts +92 -2
  116. package/lib/generates/internal/ImportDictionary.js +91 -3
  117. package/lib/generates/internal/ImportDictionary.js.map +1 -1
  118. package/lib/generates/internal/SdkAliasCollection.d.ts +119 -0
  119. package/lib/generates/internal/SdkAliasCollection.js +124 -7
  120. package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
  121. package/lib/generates/internal/SdkDistributionComposer.d.ts +19 -0
  122. package/lib/generates/internal/SdkDistributionComposer.js +98 -59
  123. package/lib/generates/internal/SdkDistributionComposer.js.map +1 -1
  124. package/lib/generates/internal/SdkFileProgrammer.d.ts +18 -0
  125. package/lib/generates/internal/SdkFileProgrammer.js +18 -0
  126. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  127. package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +29 -0
  128. package/lib/generates/internal/SdkHttpCloneProgrammer.js +33 -0
  129. package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
  130. package/lib/generates/internal/SdkHttpCloneReferencer.d.ts +19 -0
  131. package/lib/generates/internal/SdkHttpCloneReferencer.js +78 -25
  132. package/lib/generates/internal/SdkHttpCloneReferencer.js.map +1 -1
  133. package/lib/generates/internal/SdkHttpFunctionProgrammer.d.ts +19 -0
  134. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +19 -0
  135. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  136. package/lib/generates/internal/SdkHttpNamespaceProgrammer.d.ts +19 -0
  137. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +19 -0
  138. package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
  139. package/lib/generates/internal/SdkHttpParameterProgrammer.d.ts +104 -2
  140. package/lib/generates/internal/SdkHttpParameterProgrammer.js +70 -0
  141. package/lib/generates/internal/SdkHttpParameterProgrammer.js.map +1 -1
  142. package/lib/generates/internal/SdkHttpRouteProgrammer.d.ts +20 -0
  143. package/lib/generates/internal/SdkHttpRouteProgrammer.js +20 -0
  144. package/lib/generates/internal/SdkHttpRouteProgrammer.js.map +1 -1
  145. package/lib/generates/internal/SdkHttpSimulationProgrammer.d.ts +38 -0
  146. package/lib/generates/internal/SdkHttpSimulationProgrammer.js +49 -5
  147. package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
  148. package/lib/generates/internal/SdkImportWizard.d.ts +63 -0
  149. package/lib/generates/internal/SdkImportWizard.js +63 -0
  150. package/lib/generates/internal/SdkImportWizard.js.map +1 -1
  151. package/lib/generates/internal/SdkMcpRouteProgrammer.d.ts +17 -2
  152. package/lib/generates/internal/SdkMcpRouteProgrammer.js +33 -13
  153. package/lib/generates/internal/SdkMcpRouteProgrammer.js.map +1 -1
  154. package/lib/generates/internal/SdkPathTemplate.d.ts +15 -0
  155. package/lib/generates/internal/SdkPathTemplate.js +15 -0
  156. package/lib/generates/internal/SdkPathTemplate.js.map +1 -1
  157. package/lib/generates/internal/SdkRouteDirectory.d.ts +10 -0
  158. package/lib/generates/internal/SdkRouteDirectory.js +10 -0
  159. package/lib/generates/internal/SdkRouteDirectory.js.map +1 -1
  160. package/lib/generates/internal/SdkTypeProgrammer.d.ts +54 -1
  161. package/lib/generates/internal/SdkTypeProgrammer.js +96 -12
  162. package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
  163. package/lib/generates/internal/SdkTypeTagProgrammer.d.ts +36 -3
  164. package/lib/generates/internal/SdkTypeTagProgrammer.js +28 -7
  165. package/lib/generates/internal/SdkTypeTagProgrammer.js.map +1 -1
  166. package/lib/generates/internal/SdkWebSocketCloneProgrammer.d.ts +40 -0
  167. package/lib/generates/internal/SdkWebSocketCloneProgrammer.js +149 -142
  168. package/lib/generates/internal/SdkWebSocketCloneProgrammer.js.map +1 -1
  169. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.d.ts +19 -0
  170. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +19 -0
  171. package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
  172. package/lib/generates/internal/SdkWebSocketParameterProgrammer.d.ts +81 -2
  173. package/lib/generates/internal/SdkWebSocketParameterProgrammer.js +48 -0
  174. package/lib/generates/internal/SdkWebSocketParameterProgrammer.js.map +1 -1
  175. package/lib/generates/internal/SdkWebSocketRouteProgrammer.d.ts +18 -0
  176. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +18 -0
  177. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  178. package/lib/generates/internal/SwaggerDescriptionComposer.d.ts +42 -0
  179. package/lib/generates/internal/SwaggerDescriptionComposer.js +44 -1
  180. package/lib/generates/internal/SwaggerDescriptionComposer.js.map +1 -1
  181. package/lib/generates/internal/SwaggerOperationComposer.d.ts +18 -0
  182. package/lib/generates/internal/SwaggerOperationComposer.js +18 -0
  183. package/lib/generates/internal/SwaggerOperationComposer.js.map +1 -1
  184. package/lib/generates/internal/SwaggerOperationParameterComposer.d.ts +39 -0
  185. package/lib/generates/internal/SwaggerOperationParameterComposer.js +31 -8
  186. package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
  187. package/lib/generates/internal/SwaggerOperationResponseComposer.d.ts +19 -0
  188. package/lib/generates/internal/SwaggerOperationResponseComposer.js +19 -0
  189. package/lib/generates/internal/SwaggerOperationResponseComposer.js.map +1 -1
  190. package/lib/internal/legacy.d.ts +296 -16
  191. package/lib/internal/legacy.js +127 -10
  192. package/lib/internal/legacy.js.map +1 -1
  193. package/lib/structures/INestiaProject.d.ts +10 -0
  194. package/lib/structures/INestiaSdkInput.d.ts +31 -1
  195. package/lib/structures/IOperationMetadata.d.ts +55 -0
  196. package/lib/structures/IReflectController.d.ts +11 -1
  197. package/lib/structures/IReflectHttpOperation.d.ts +11 -1
  198. package/lib/structures/IReflectHttpOperationException.d.ts +10 -0
  199. package/lib/structures/IReflectHttpOperationParameter.d.ts +47 -0
  200. package/lib/structures/IReflectHttpOperationSuccess.d.ts +11 -0
  201. package/lib/structures/IReflectImport.d.ts +10 -0
  202. package/lib/structures/IReflectMcpOperation.d.ts +19 -0
  203. package/lib/structures/IReflectMcpOperationParameter.d.ts +9 -0
  204. package/lib/structures/IReflectOperationError.d.ts +28 -0
  205. package/lib/structures/IReflectOperationError.js +22 -2
  206. package/lib/structures/IReflectOperationError.js.map +1 -1
  207. package/lib/structures/IReflectType.d.ts +9 -0
  208. package/lib/structures/IReflectWebSocketOperation.d.ts +10 -0
  209. package/lib/structures/IReflectWebSocketOperationParameter.d.ts +55 -0
  210. package/lib/structures/ITypedApplication.d.ts +10 -0
  211. package/lib/structures/ITypedHttpRoute.d.ts +10 -0
  212. package/lib/structures/ITypedHttpRouteException.d.ts +10 -0
  213. package/lib/structures/ITypedHttpRouteParameter.d.ts +45 -0
  214. package/lib/structures/ITypedHttpRouteSuccess.d.ts +10 -0
  215. package/lib/structures/ITypedMcpRoute.d.ts +11 -0
  216. package/lib/structures/ITypedWebSocketRoute.d.ts +10 -0
  217. package/lib/transform.d.ts +6 -0
  218. package/lib/transform.js +6 -0
  219. package/lib/transform.js.map +1 -1
  220. package/lib/utils/ArrayUtil.d.ts +31 -1
  221. package/lib/utils/ArrayUtil.js +32 -11
  222. package/lib/utils/ArrayUtil.js.map +1 -1
  223. package/lib/utils/EmittedJavaScriptPatcher.d.ts +20 -0
  224. package/lib/utils/EmittedJavaScriptPatcher.js +65 -46
  225. package/lib/utils/EmittedJavaScriptPatcher.js.map +1 -1
  226. package/lib/utils/FileRetriever.d.ts +29 -0
  227. package/lib/utils/FileRetriever.js +29 -0
  228. package/lib/utils/FileRetriever.js.map +1 -1
  229. package/lib/utils/HttpResponseContentTypeUtil.d.ts +41 -0
  230. package/lib/utils/HttpResponseContentTypeUtil.js +31 -0
  231. package/lib/utils/HttpResponseContentTypeUtil.js.map +1 -1
  232. package/lib/utils/MapUtil.d.ts +64 -1
  233. package/lib/utils/MapUtil.js +24 -3
  234. package/lib/utils/MapUtil.js.map +1 -1
  235. package/lib/utils/PathUtil.d.ts +31 -0
  236. package/lib/utils/PathUtil.js +38 -0
  237. package/lib/utils/PathUtil.js.map +1 -1
  238. package/lib/utils/SdkBundlePath.d.ts +2 -0
  239. package/lib/utils/SdkBundlePath.js +10 -0
  240. package/lib/utils/SdkBundlePath.js.map +1 -0
  241. package/lib/utils/SdkInputFilter.d.ts +31 -0
  242. package/lib/utils/SdkInputFilter.js +115 -0
  243. package/lib/utils/SdkInputFilter.js.map +1 -0
  244. package/lib/utils/SourceFinder.d.ts +35 -0
  245. package/lib/utils/SourceFinder.js +47 -12
  246. package/lib/utils/SourceFinder.js.map +1 -1
  247. package/lib/utils/StringUtil.d.ts +77 -2
  248. package/lib/utils/StringUtil.js +166 -4
  249. package/lib/utils/StringUtil.js.map +1 -1
  250. package/lib/utils/TemporaryDirectory.d.ts +60 -0
  251. package/lib/utils/TemporaryDirectory.js +112 -0
  252. package/lib/utils/TemporaryDirectory.js.map +1 -0
  253. package/lib/utils/TsConfigReader.d.ts +42 -0
  254. package/lib/utils/TsConfigReader.js +98 -14
  255. package/lib/utils/TsConfigReader.js.map +1 -1
  256. package/lib/utils/TtscExecutor.d.ts +23 -1
  257. package/lib/utils/TtscExecutor.js +22 -0
  258. package/lib/utils/TtscExecutor.js.map +1 -1
  259. package/lib/utils/VersioningStrategy.d.ts +27 -2
  260. package/lib/utils/VersioningStrategy.js +30 -9
  261. package/lib/utils/VersioningStrategy.js.map +1 -1
  262. package/lib/validators/TextPlainValidator.d.ts +19 -0
  263. package/lib/validators/TextPlainValidator.js +19 -0
  264. package/lib/validators/TextPlainValidator.js.map +1 -1
  265. package/native/go.mod +1 -1
  266. package/native/go.sum +2 -2
  267. package/native/sdk/register.go +12 -2
  268. package/native/sdk/sdk_metadata_json.go +6 -1
  269. package/native/sdk/sdk_transform.go +393 -403
  270. package/package.json +9 -7
  271. package/src/INestiaConfig.ts +55 -24
  272. package/src/NestiaSdkApplication.ts +66 -7
  273. package/src/NestiaSwaggerComposer.ts +21 -6
  274. package/src/analyses/AccessorAnalyzer.ts +26 -0
  275. package/src/analyses/ConfigAnalyzer.ts +59 -96
  276. package/src/analyses/ImportAnalyzer.ts +25 -0
  277. package/src/analyses/ParameterNameAnalyzer.ts +24 -0
  278. package/src/analyses/PathAnalyzer.ts +63 -11
  279. package/src/analyses/ReflectControllerAnalyzer.ts +32 -0
  280. package/src/analyses/ReflectHttpOperationAnalyzer.ts +32 -10
  281. package/src/analyses/ReflectHttpOperationExceptionAnalyzer.ts +31 -0
  282. package/src/analyses/ReflectHttpOperationParameterAnalyzer.ts +31 -0
  283. package/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +32 -0
  284. package/src/analyses/ReflectMcpOperationAnalyzer.ts +32 -1
  285. package/src/analyses/ReflectMetadataAnalyzer.ts +48 -1
  286. package/src/analyses/ReflectWebSocketOperationAnalyzer.ts +34 -14
  287. package/src/analyses/SecurityAnalyzer.ts +15 -0
  288. package/src/analyses/SwaggerExampleAnalyzer.ts +16 -0
  289. package/src/analyses/TypedHttpRouteAnalyzer.ts +240 -184
  290. package/src/analyses/TypedMcpRouteAnalyzer.ts +180 -20
  291. package/src/analyses/TypedWebSocketRouteAnalyzer.ts +19 -0
  292. package/src/decorators/OperationMetadata.ts +6 -0
  293. package/src/executable/internal/CommandParser.ts +19 -0
  294. package/src/executable/internal/NestiaConfigLoader.ts +66 -50
  295. package/src/executable/internal/NestiaSdkCommand.ts +96 -3
  296. package/src/executable/internal/NestiaSdkWatcher.ts +169 -41
  297. package/src/executable/internal/NestiaSwaggerWatch.ts +359 -0
  298. package/src/factories/ExpressionFactory.ts +17 -2
  299. package/src/factories/IdentifierFactory.ts +24 -0
  300. package/src/factories/LiteralFactory.ts +44 -11
  301. package/src/factories/StatementFactory.ts +28 -1
  302. package/src/factories/TypeFactory.ts +24 -0
  303. package/src/generates/CloneGenerator.ts +26 -5
  304. package/src/generates/E2eGenerator.ts +19 -0
  305. package/src/generates/SdkGenerator.ts +40 -9
  306. package/src/generates/SwaggerGenerator.ts +56 -14
  307. package/src/generates/internal/E2eFileProgrammer.ts +20 -0
  308. package/src/generates/internal/FilePrinter.ts +43 -0
  309. package/src/generates/internal/ImportDictionary.ts +110 -3
  310. package/src/generates/internal/SdkAliasCollection.ts +133 -11
  311. package/src/generates/internal/SdkDistributionComposer.ts +117 -66
  312. package/src/generates/internal/SdkFileProgrammer.ts +18 -0
  313. package/src/generates/internal/SdkHttpCloneProgrammer.ts +55 -0
  314. package/src/generates/internal/SdkHttpCloneReferencer.ts +97 -23
  315. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +19 -0
  316. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +19 -0
  317. package/src/generates/internal/SdkHttpParameterProgrammer.ts +104 -2
  318. package/src/generates/internal/SdkHttpRouteProgrammer.ts +20 -0
  319. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +72 -5
  320. package/src/generates/internal/SdkImportWizard.ts +63 -0
  321. package/src/generates/internal/SdkMcpRouteProgrammer.ts +38 -18
  322. package/src/generates/internal/SdkPathTemplate.ts +15 -0
  323. package/src/generates/internal/SdkRouteDirectory.ts +10 -0
  324. package/src/generates/internal/SdkTypeProgrammer.ts +118 -14
  325. package/src/generates/internal/SdkTypeTagProgrammer.ts +37 -7
  326. package/src/generates/internal/SdkWebSocketCloneProgrammer.ts +185 -142
  327. package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +19 -0
  328. package/src/generates/internal/SdkWebSocketParameterProgrammer.ts +81 -2
  329. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +18 -0
  330. package/src/generates/internal/SwaggerDescriptionComposer.ts +47 -1
  331. package/src/generates/internal/SwaggerOperationComposer.ts +18 -0
  332. package/src/generates/internal/SwaggerOperationParameterComposer.ts +41 -8
  333. package/src/generates/internal/SwaggerOperationResponseComposer.ts +19 -0
  334. package/src/internal/legacy-augmentation.d.ts +16 -0
  335. package/src/internal/legacy.ts +296 -26
  336. package/src/structures/INestiaProject.ts +10 -0
  337. package/src/structures/INestiaSdkInput.ts +31 -1
  338. package/src/structures/IOperationMetadata.ts +55 -0
  339. package/src/structures/IReflectController.ts +11 -1
  340. package/src/structures/IReflectHttpOperation.ts +11 -1
  341. package/src/structures/IReflectHttpOperationException.ts +10 -0
  342. package/src/structures/IReflectHttpOperationParameter.ts +47 -0
  343. package/src/structures/IReflectHttpOperationSuccess.ts +11 -0
  344. package/src/structures/IReflectImport.ts +10 -0
  345. package/src/structures/IReflectMcpOperation.ts +19 -0
  346. package/src/structures/IReflectMcpOperationParameter.ts +9 -0
  347. package/src/structures/IReflectOperationError.ts +31 -2
  348. package/src/structures/IReflectType.ts +9 -0
  349. package/src/structures/IReflectWebSocketOperation.ts +10 -0
  350. package/src/structures/IReflectWebSocketOperationParameter.ts +55 -0
  351. package/src/structures/ITypedApplication.ts +10 -0
  352. package/src/structures/ITypedHttpRoute.ts +10 -0
  353. package/src/structures/ITypedHttpRouteException.ts +10 -0
  354. package/src/structures/ITypedHttpRouteParameter.ts +45 -0
  355. package/src/structures/ITypedHttpRouteSuccess.ts +10 -0
  356. package/src/structures/ITypedMcpRoute.ts +12 -0
  357. package/src/structures/ITypedWebSocketRoute.ts +10 -0
  358. package/src/transform.ts +6 -0
  359. package/src/utils/ArrayUtil.ts +32 -13
  360. package/src/utils/EmittedJavaScriptPatcher.ts +70 -47
  361. package/src/utils/FileRetriever.ts +29 -0
  362. package/src/utils/HttpResponseContentTypeUtil.ts +41 -0
  363. package/src/utils/MapUtil.ts +68 -3
  364. package/src/utils/PathUtil.ts +38 -0
  365. package/src/utils/SdkBundlePath.ts +11 -0
  366. package/src/utils/SdkInputFilter.ts +108 -0
  367. package/src/utils/SourceFinder.ts +51 -14
  368. package/src/utils/StringUtil.ts +182 -5
  369. package/src/utils/TemporaryDirectory.ts +108 -0
  370. package/src/utils/TsConfigReader.ts +124 -26
  371. package/src/utils/TtscExecutor.ts +23 -1
  372. package/src/utils/VersioningStrategy.ts +37 -14
  373. package/src/validators/TextPlainValidator.ts +19 -0
  374. package/lib/generates/internal/SwaggerReadonlyArrayEmender.d.ts +0 -9
  375. package/lib/generates/internal/SwaggerReadonlyArrayEmender.js +0 -178
  376. package/lib/generates/internal/SwaggerReadonlyArrayEmender.js.map +0 -1
  377. package/src/generates/internal/SwaggerReadonlyArrayEmender.ts +0 -264
@@ -4,14 +4,96 @@ import path from "path";
4
4
  import { INestiaConfig } from "../../INestiaConfig";
5
5
  import { SourceFinder } from "../../utils/SourceFinder";
6
6
 
7
+ /**
8
+ * Regenerates the Swagger document when the sources or the configuration
9
+ * change.
10
+ *
11
+ * @evidence contracts/common.md#principled-implementation A session watches the directories of the inputs and the configuration files, ignores the outputs and dependency directories, debounces changes, and queues a change that arrives during a generation.
12
+ * @evidence contracts/common.md#clear-and-simple-design One public function over a session class and private path helpers.
13
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The watchers are installed before each generation so no change between generation and watching is lost, and every watcher is closed on stop.
14
+ * @evidence contracts/common.md#meaningful-documentation The comment states its purpose.
15
+ * @evidence contracts/portability.md#os-neutral-implementation One non-recursive `fs.watch` is installed per directory, which every supported platform provides, in place of the `recursive` option that older Linux releases lack. The event's file name can be missing on some platforms and the directory then stands for the change, and a rename without an extension is read as a possible directory change because platforms report directory creation as a rename. Locations are compared by filesystem identity: every ignored path and every event target is resolved to the real path of its nearest existing ancestor, which carries the case and links the volume keeps, so no operating-system name decides a case policy. Remaining assumptions: `fs.watch` event semantics differ per platform, and only SIGINT and SIGTERM are handled, so an abrupt termination ends the watchers with the process.
16
+ * efficient algorithms: Each regeneration walks the watched trees once, one `readdir` and one real-path resolution per directory, and does so twice, before the generation so no edit is lost and after it to see what it wrote, so the cost grows with the number of watched directories and their entries and repeats for every debounced regeneration. A watched directory can appear at any time, so an incremental plan would still have to rescan, and the full rebuild is kept because regeneration is itself far costlier than a scan.
17
+ * reuse equivalent work: Changes inside the debounce window collapse into one regeneration and a change during a running generation sets one pending reason, so equivalent triggers share a run. Each run reloads the configurations because the configuration file is an input, so no result is reused across runs.
18
+ * bound retention and release resources: The session owns one watcher per planned directory, one debounce timer and one pending reason; sync, errors and stop release those handles. Its optional finalizer releases caller-owned generation resources on success, failure and stop. CLI regeneration loads configurations/controllers inside one disposable child whose temporary outputs and module realm end after that generation. Arbitrary programmatic callbacks retain their own module caches and resources; the scheduler cannot release caller-owned caches or objects retained outside their callbacks.
19
+ */
7
20
  export namespace NestiaSdkWatcher {
21
+ /**
22
+ * The input of the watcher: the configuration file, the configuration loader,
23
+ * the generator, and the project file.
24
+ *
25
+ * @evidence contracts/common.md#principled-implementation The record holds the loaders and the generator the session calls.
26
+ * @evidence contracts/common.md#clear-and-simple-design Native configuration/project paths sit beside the configuration, generation and optional finalization callbacks that own their respective phases.
27
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
28
+ * @evidence contracts/common.md#meaningful-documentation The comment states what the type describes and the meaning of its members.
29
+ * @evidence contracts/portability.md#os-neutral-implementation The two file fields are native paths of the project, resolved with `path.resolve` before any comparison.
30
+ * efficient algorithms: The record has no computation.
31
+ * reuse equivalent work: The record coordinates no work.
32
+ * bound retention and release resources: The record owns no handle or task; the session that holds it owns the resources.
33
+ */
8
34
  export interface IProps {
9
35
  configFile: string;
36
+ /**
37
+ * Loads the current configurations; it is called again at every
38
+ * regeneration so a changed file is read.
39
+ *
40
+ * @evidence contracts/common.md#principled-implementation The loader is a function, not a value, because the configuration file itself is watched.
41
+ * @evidence contracts/common.md#clear-and-simple-design One callback.
42
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It is caller code.
43
+ * @evidence contracts/common.md#meaningful-documentation The comment states when it is called.
44
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation A caller callback owns no filesystem or process access here; the loader it wraps owns those decisions.
45
+ * efficient algorithms: The signature performs no computation.
46
+ * reuse equivalent work: The signature coordinates nothing; the session decides when to call it.
47
+ * bound retention and release resources: The signature retains nothing; the session drops the returned configurations after each run.
48
+ */
10
49
  configurations: () => Promise<INestiaConfig[]>;
50
+ /**
51
+ * Runs the generation for the loaded configurations.
52
+ *
53
+ * @evidence contracts/common.md#principled-implementation The watcher only schedules the call and reports its errors.
54
+ * @evidence contracts/common.md#clear-and-simple-design One callback.
55
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It is caller code.
56
+ * @evidence contracts/common.md#meaningful-documentation The comment states what it does.
57
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation A caller callback owns no filesystem or process access here; the generator it wraps owns those decisions.
58
+ * efficient algorithms: The signature performs no computation.
59
+ * reuse equivalent work: The signature coordinates nothing; the session serializes its calls.
60
+ * bound retention and release resources: The signature retains nothing.
61
+ */
11
62
  generate: (configurations: INestiaConfig[]) => Promise<void>;
63
+
64
+ /**
65
+ * Releases caller-owned per-generation resources after success or failure,
66
+ * and when the session is stopped. It may overlap an in-flight generation
67
+ * during stop, so its implementation must make release idempotent.
68
+ *
69
+ * @evidence contracts/common.md#principled-implementation The hook lets the caller release generation-owned resources on completion, failure and stop, including overlap with an active generation.
70
+ * @evidence contracts/common.md#clear-and-simple-design One optional finalizer avoids making the scheduler depend on a particular generator resource representation.
71
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Resource release is delegated to its actual owner rather than changing foreign caches or callbacks.
72
+ * @evidence contracts/common.md#meaningful-documentation The comment states call timing and the idempotency required when stop overlaps work.
73
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation This callback signature exposes no native path or process representation; the caller’s finalizer owns that boundary.
74
+ * efficient algorithms: The signature performs no release computation; its caller supplies the implementation.
75
+ * reuse equivalent work: The signature shares no results; the session determines finalization timing.
76
+ * bound retention and release resources: The signature owns no retained state or handle; the session joins the caller’s release operation and the caller owns external resources.
77
+ */
78
+ finalize?: () => Promise<void>;
12
79
  projectFile: string;
13
80
  }
14
81
 
82
+ /**
83
+ * Starts the watch session, generates once, and never resolves until the
84
+ * process ends.
85
+ *
86
+ * The session closes its watchers and exits on SIGINT and SIGTERM.
87
+ *
88
+ * @evidence contracts/common.md#principled-implementation The first generation runs before the promise that never settles, and a failed generation is printed with its causes and does not stop the session.
89
+ * @evidence contracts/common.md#clear-and-simple-design One function that creates the session and blocks.
90
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The watchers are released by the signal handlers.
91
+ * @evidence contracts/common.md#meaningful-documentation The comment states the blocking and the signals.
92
+ * @evidence contracts/portability.md#os-neutral-implementation The signal handlers are registered with `process.once` for SIGINT and SIGTERM and exit with status 0 after closing the watchers; SIGINT is delivered on every platform while Windows never delivers SIGTERM, so a termination request there ends the process without the handler.
93
+ * efficient algorithms: The function creates one session and awaits one generation; its cost is that of the first regeneration described by the namespace.
94
+ * reuse equivalent work: The first generation is the only work the function itself requests, and later regenerations are coordinated by the session, which collapses equivalent triggers.
95
+ * bound retention and release resources: The returned promise never settles by design, so the session lives until the process ends; the handlers release its watchers and timer on SIGINT and SIGTERM, and the process exit releases them otherwise.
96
+ */
15
97
  export const watch = async (props: IProps): Promise<void> => {
16
98
  const session = new WatchSession(props);
17
99
  session.registerSignals();
@@ -33,7 +115,15 @@ class WatchSession {
33
115
  public registerSignals(): void {
34
116
  const stop = (): void => {
35
117
  this.dispose();
36
- process.exit(0);
118
+ void (async () => {
119
+ try {
120
+ await this.props.finalize?.();
121
+ process.exit(0);
122
+ } catch (error) {
123
+ printError(error);
124
+ process.exit(1);
125
+ }
126
+ })();
37
127
  };
38
128
  process.once("SIGINT", stop);
39
129
  process.once("SIGTERM", stop);
@@ -47,36 +137,58 @@ class WatchSession {
47
137
  }
48
138
 
49
139
  this.running = true;
50
- let nextReason: string | null = reason;
51
- do {
52
- const current: string = nextReason;
53
- nextReason = null;
54
- this.pending = null;
55
- let configurations: INestiaConfig[] = [];
56
- try {
57
- if (current === "initial generation")
58
- console.log("Starting nestia swagger watch mode");
59
- else console.log(`Change detected (${current}); regenerating swagger`);
60
-
61
- configurations = await this.props.configurations();
62
- // Watchers must be live before artifacts are written: consumers react
63
- // to the artifact appearing, and an edit arriving between the write
64
- // and a later watcher installation would be lost forever. Changes
65
- // during generation queue through `pending`.
66
- await this.refresh(configurations);
67
- await this.props.generate(configurations);
68
- await this.refresh(configurations);
69
- console.log(
70
- `Watching ${this.watchers.size} directories. Press Ctrl+C to stop.`,
71
- );
72
- } catch (error) {
73
- await this.refresh(configurations);
74
- console.error("Nestia swagger watch generation failed:");
75
- printError(error);
76
- }
77
- nextReason = this.pending;
78
- } while (nextReason !== null && !this.stopped);
79
- this.running = false;
140
+ try {
141
+ let nextReason: string | null = reason;
142
+ do {
143
+ const current: string = nextReason;
144
+ nextReason = null;
145
+ this.pending = null;
146
+ let configurations: INestiaConfig[] = [];
147
+ let generationError: unknown;
148
+ try {
149
+ if (current === "initial generation")
150
+ console.log("Starting nestia swagger watch mode");
151
+ else
152
+ console.log(`Change detected (${current}); regenerating swagger`);
153
+
154
+ configurations = await this.props.configurations();
155
+ // Watchers must be live before artifacts are written: consumers react
156
+ // to the artifact appearing, and an edit arriving between the write
157
+ // and a later watcher installation would be lost forever. Changes
158
+ // during generation queue through `pending`.
159
+ await this.refresh(configurations);
160
+ await this.props.generate(configurations);
161
+ await this.refresh(configurations);
162
+ console.log(
163
+ `Watching ${this.watchers.size} directories. Press Ctrl+C to stop.`,
164
+ );
165
+ } catch (error) {
166
+ generationError = error;
167
+ if (!this.stopped) {
168
+ console.error("Nestia swagger watch generation failed:");
169
+ printError(error);
170
+ try {
171
+ await this.refresh(configurations);
172
+ } catch (refreshError) {
173
+ console.error("Nestia swagger watch refresh failed:");
174
+ printError(refreshError);
175
+ }
176
+ }
177
+ } finally {
178
+ try {
179
+ await this.props.finalize?.();
180
+ } catch (error) {
181
+ if (!this.stopped && error !== generationError) {
182
+ console.error("Nestia swagger watch cleanup failed:");
183
+ printError(error);
184
+ }
185
+ }
186
+ }
187
+ nextReason = this.pending;
188
+ } while (nextReason !== null && !this.stopped);
189
+ } finally {
190
+ this.running = false;
191
+ }
80
192
  }
81
193
 
82
194
  private schedule(reason: string): void {
@@ -89,6 +201,7 @@ class WatchSession {
89
201
  }
90
202
 
91
203
  private async refresh(configurations: INestiaConfig[]): Promise<void> {
204
+ if (this.stopped) return;
92
205
  const next = await collectWatchPlan({
93
206
  configurations,
94
207
  configFile: this.props.configFile,
@@ -107,6 +220,7 @@ class WatchSession {
107
220
  }
108
221
 
109
222
  private sync(next: Set<string>): void {
223
+ if (this.stopped) return;
110
224
  for (const [directory, watcher] of this.watchers)
111
225
  if (next.has(directory) === false) {
112
226
  watcher.close();
@@ -169,7 +283,7 @@ const collectWatchPlan = async (props: {
169
283
  for (const target of outputTargets(config)) ignored.add(target);
170
284
  }
171
285
  return {
172
- ignored: [...ignored],
286
+ ignored: [...ignored].map(canonical),
173
287
  targets: [...targets],
174
288
  };
175
289
  };
@@ -280,18 +394,32 @@ const shouldReact = (props: { event: string; target: string }): boolean => {
280
394
  return props.event === "rename" && ext.length === 0;
281
395
  };
282
396
 
283
- const shouldIgnore = (location: string, ignored: string[]): boolean =>
284
- ignored.some((elem) => isSameOrInside(location, elem));
285
-
286
- const isSameOrInside = (child: string, parent: string): boolean => {
287
- const left: string = comparable(child);
288
- const right: string = comparable(parent);
289
- return left === right || left.startsWith(`${right}${path.sep}`);
397
+ // `ignored` holds canonical paths, see `canonical`.
398
+ const shouldIgnore = (location: string, ignored: string[]): boolean => {
399
+ const target: string = canonical(location);
400
+ return ignored.some(
401
+ (elem) => target === elem || target.startsWith(`${elem}${path.sep}`),
402
+ );
290
403
  };
291
404
 
292
- const comparable = (location: string): string => {
405
+ // The filesystem decides which spellings name one location, so the nearest
406
+ // existing ancestor is resolved to its real path, which holds the case and the
407
+ // links the filesystem keeps, and the part that does not exist yet is appended
408
+ // as written. An operating-system name says nothing about the case policy of a
409
+ // volume, which a mount or a directory may set apart from its neighbors.
410
+ const canonical = (location: string): string => {
293
411
  const resolved: string = path.resolve(location);
294
- return process.platform === "win32" ? resolved.toLowerCase() : resolved;
412
+ const rest: string[] = [];
413
+ for (let current: string = resolved; ; ) {
414
+ try {
415
+ return path.join(fs.realpathSync.native(current), ...[...rest].reverse());
416
+ } catch {
417
+ const parent: string = path.dirname(current);
418
+ if (parent === current) return resolved;
419
+ rest.push(path.basename(current));
420
+ current = parent;
421
+ }
422
+ }
295
423
  };
296
424
 
297
425
  const staticRoot = (pattern: string): string => {
@@ -0,0 +1,359 @@
1
+ import cp from "child_process";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ import { INestiaConfig } from "../../INestiaConfig";
6
+ import { NestiaSdkApplication } from "../../NestiaSdkApplication";
7
+ import { TemporaryDirectory } from "../../utils/TemporaryDirectory";
8
+ import { NestiaConfigLoader } from "./NestiaConfigLoader";
9
+
10
+ /**
11
+ * Owns one disposable Swagger generation process and its two-phase protocol.
12
+ *
13
+ * Configuration functions and controller classes stay in their original Node
14
+ * realm. Only path information reaches the watcher; generation waits until the
15
+ * watcher has installed its watches and explicitly starts the second phase.
16
+ *
17
+ * @evidence contracts/common.md#principled-implementation A child loads configuration and controllers in one realm, sends only a path projection, and waits for the parent's generate message before writing artifacts. Ending that realm releases both CommonJS and ESM module retention without altering a loader cache.
18
+ * @evidence contracts/common.md#clear-and-simple-design One open operation returns the prepared watch plan and generation/close callbacks; the same emitted module owns the child entry so source and installed builds share one protocol.
19
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Arbitrary configuration functions execute normally in the child; none is stringified, cloned or replaced. No foreign module cache or resolver is changed.
20
+ * @evidence contracts/common.md#meaningful-documentation The comment explains the realm boundary and why artifact generation waits for the watcher handshake.
21
+ * @evidence contracts/portability.md#os-neutral-implementation Node launches this emitted module with its own executable, argument arrays, explicit cwd, IPC and windowsHide. Paths remain native filesystem values and no executable shim or shell command is constructed.
22
+ * efficient algorithms: Each generation creates one child and projects only the configuration paths required by watcher planning; no controller/module graph is copied into the parent.
23
+ * reuse equivalent work: Configuration loading and generation share one child and its loaded configuration objects. Changed inputs require a new realm, while the inherited native compiler caches remain reusable outside its disposable outputs.
24
+ * bound retention and release resources: The parent owns one child per opened generation and awaits its exit on success, failure or close. The child explicitly releases its registered temporary outputs before exit; process exit also releases its module realm.
25
+ */
26
+ export namespace NestiaSwaggerWatch {
27
+ /**
28
+ * A prepared child whose configurations contain only watcher path data.
29
+ *
30
+ * @evidence contracts/common.md#principled-implementation The projection is sufficient for watch planning, while callbacks retain the actual child that owns nonserializable configuration functions and controller classes.
31
+ * @evidence contracts/common.md#clear-and-simple-design The record exposes the prepared plan, the explicit generation phase and idempotent release.
32
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The projection is never passed to a generator as a replacement configuration; the child's original objects drive generation.
33
+ * @evidence contracts/common.md#meaningful-documentation Member comments distinguish watcher-only data, phase ordering and release ownership.
34
+ * @evidence contracts/portability.md#os-neutral-implementation The configuration projection carries native input/output paths; the callbacks hide Node's IPC and process representation from the watcher instead of exposing a shell or executable shim.
35
+ * efficient algorithms: The record performs no computation; open and its callbacks own projection and process coordination.
36
+ * reuse equivalent work: The record carries a prepared generation but makes no reuse decision; open keeps its configuration and generator in the same child.
37
+ * bound retention and release resources: The record transfers one prepared child's lifetime to its caller, which must invoke generate or close and finalize on errors. close is idempotent and waits for worker resource release.
38
+ */
39
+ export interface IGeneration {
40
+ /** Paths used only to install watches, never to generate artifacts. */
41
+ configurations: INestiaConfig[];
42
+
43
+ /**
44
+ * Starts generation after the caller installs its watchers.
45
+ *
46
+ * @evidence contracts/common.md#principled-implementation The callback starts the prepared child’s second phase and resolves only after the result and child exit are observed.
47
+ * @evidence contracts/common.md#clear-and-simple-design One argument-free phase transition uses the configuration already held by the child.
48
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It invokes the actual child generator without substituting projected watcher data for its configuration.
49
+ * @evidence contracts/common.md#meaningful-documentation The comment states the required watcher-installation ordering.
50
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation This callback signature hides the process representation; open owns the Node fork and IPC boundary.
51
+ * efficient algorithms: The signature selects no computation; open and the child generator own it.
52
+ * reuse equivalent work: The signature decides no sharing policy; the prepared child retains the actual configuration.
53
+ * bound retention and release resources: The signature acquires no resource; the record’s owner must invoke this operation or close as documented.
54
+ */
55
+ generate: () => Promise<void>;
56
+
57
+ /**
58
+ * Ends the child and waits for its owned resources to be released. A
59
+ * synchronous compiler or user callback delays processing the disconnect;
60
+ * release waits for that work rather than abandoning its outputs.
61
+ *
62
+ * @evidence contracts/common.md#principled-implementation The callback disconnects an active child once and joins its actual exit, including a reported cleanup failure.
63
+ * @evidence contracts/common.md#clear-and-simple-design One release operation is shared by cancellation and failure paths.
64
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It waits for owned child cleanup rather than changing foreign loader caches.
65
+ * @evidence contracts/common.md#meaningful-documentation The comment states release timing and the limitation imposed by synchronous child work.
66
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation This callback signature hides Node IPC disconnection; open owns its platform boundary.
67
+ * efficient algorithms: The signature performs no cleanup algorithm itself; open defines the implementation.
68
+ * reuse equivalent work: The signature coordinates no producer reuse; open makes release idempotent.
69
+ * bound retention and release resources: The signature acquires no resource itself; the prepared record and open operation define child lifetime transfer and release.
70
+ */
71
+ close: () => Promise<void>;
72
+ }
73
+
74
+ /**
75
+ * Loads one watch plan in a fresh child without starting generation.
76
+ *
77
+ * @evidence contracts/common.md#principled-implementation A prepared IPC message resolves the plan; generate sends the second-phase request and awaits both its result and actual process exit. An early exit or process/IPC error rejects rather than certifying generation.
78
+ * @evidence contracts/common.md#clear-and-simple-design Preparation, generation result and exit have distinct promises, and one close callback joins resource release on every path.
79
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The emitted child entry executes real loader and generator operations once. Failures retain their cause messages; no retry or cached-success substitution occurs.
80
+ * @evidence contracts/common.md#meaningful-documentation The comment states that preparation does not write generated artifacts and the returned callbacks define the two-phase lifetime.
81
+ * @evidence contracts/portability.md#os-neutral-implementation Node launches the existing emitted __filename with its own executable, inherited runtime arguments, explicit cwd, windowsHide and IPC; cancellation uses channel disconnection and awaits actual close without platform shell commands.
82
+ * efficient algorithms: One child is opened for one generation and one path-only projection is delivered; retained parent protocol state is constant apart from that configuration list and bounded error causes.
83
+ * reuse equivalent work: The child's loaded configuration is reused for the second phase after watches are installed, so callbacks and controller dependencies are not reconstructed or recompiled between preparation and generation. A changed-input generation needs a fresh realm; compiler disk caches are inherited separately.
84
+ * bound retention and release resources: Preparation errors close the child before rejection; generation awaits its result and close, and the explicit close callback joins cleanup on cancellation or failure before the second phase. Watcher finalization releases the record after every run and on stop.
85
+ */
86
+ export const open = async (props: {
87
+ configFile: string;
88
+ projectFile: string;
89
+ signal?: AbortSignal;
90
+ }): Promise<IGeneration> => {
91
+ const child = cp.spawn(
92
+ process.execPath,
93
+ [...workerExecArgv(), __filename],
94
+ {
95
+ cwd: process.cwd(),
96
+ stdio: ["inherit", "inherit", "inherit", "ipc"],
97
+ windowsHide: true,
98
+ env: { ...process.env, NESTIA_WATCH_CHILD: "1" },
99
+ },
100
+ );
101
+ let resolvePrepared!: (value: INestiaConfig[]) => void;
102
+ let rejectPrepared!: (error: Error) => void;
103
+ let resolveGenerated!: () => void;
104
+ let rejectGenerated!: (error: Error) => void;
105
+ const prepared = new Promise<INestiaConfig[]>((resolve, reject) => {
106
+ resolvePrepared = resolve;
107
+ rejectPrepared = reject;
108
+ });
109
+ const generated = new Promise<void>((resolve, reject) => {
110
+ resolveGenerated = resolve;
111
+ rejectGenerated = reject;
112
+ });
113
+ // Preparation can fail before the caller awaits the generation phase.
114
+ generated.catch(() => {});
115
+ let ended = false;
116
+ let closing = false;
117
+ let spawned = false;
118
+ let failure: Error | undefined;
119
+ let closeFailure: Error | undefined;
120
+ const fail = (error: Error): void => {
121
+ failure ??= error;
122
+ rejectPrepared(error);
123
+ rejectGenerated(error);
124
+ };
125
+ const exited = new Promise<void>((resolve) => {
126
+ child.once("spawn", () => {
127
+ spawned = true;
128
+ });
129
+ child.once("error", () => {
130
+ if (!spawned) {
131
+ ended = true;
132
+ resolve();
133
+ }
134
+ });
135
+ child.once("exit", (code, signal) => {
136
+ ended = true;
137
+ if (
138
+ closing &&
139
+ failure === undefined &&
140
+ (code !== 0 || signal !== null)
141
+ ) {
142
+ closeFailure = new Error(
143
+ `Swagger generation cleanup exited: ${signal ?? code}`,
144
+ );
145
+ fail(closeFailure);
146
+ } else if (!closing && (code !== 0 || signal !== null))
147
+ fail(
148
+ new Error(`Swagger generation process exited: ${signal ?? code}`),
149
+ );
150
+ else if (!closing) {
151
+ rejectPrepared(
152
+ new Error("Swagger generation exited before preparation."),
153
+ );
154
+ rejectGenerated(
155
+ new Error("Swagger generation exited before reporting its result."),
156
+ );
157
+ }
158
+ resolve();
159
+ });
160
+ });
161
+ child.on("error", fail);
162
+ child.on("message", (message: any) => {
163
+ if (message?.type === "prepared") resolvePrepared(message.configurations);
164
+ else if (message?.type === "complete") resolveGenerated();
165
+ else if (message?.type === "failed")
166
+ fail(deserializeError(message.error));
167
+ });
168
+ const send = (message: object): void => {
169
+ if (!child.connected) {
170
+ fail(new Error("Swagger generation IPC channel is closed."));
171
+ return;
172
+ }
173
+ child.send(message, (error) => {
174
+ if (error) fail(error);
175
+ });
176
+ };
177
+ const close = async (): Promise<void> => {
178
+ if (!ended && !closing) {
179
+ closing = true;
180
+ rejectGenerated(new Error("Swagger generation was cancelled."));
181
+ // Disconnect is the child's cancellation boundary, including failure
182
+ // between watch-plan preparation and the generation handshake.
183
+ if (child.connected) child.disconnect();
184
+ }
185
+ await exited;
186
+ if (closeFailure) throw closeFailure;
187
+ };
188
+ const abort = (): void => {
189
+ const error = new Error("Swagger generation was cancelled.");
190
+ error.name = "AbortError";
191
+ rejectPrepared(error);
192
+ rejectGenerated(error);
193
+ void close().catch(fail);
194
+ };
195
+ props.signal?.addEventListener("abort", abort, { once: true });
196
+ void exited.then(() => props.signal?.removeEventListener("abort", abort));
197
+ if (props.signal?.aborted) abort();
198
+ else
199
+ send({
200
+ type: "prepare",
201
+ configFile: props.configFile,
202
+ projectFile: props.projectFile,
203
+ });
204
+ try {
205
+ const configurations = await prepared;
206
+ return {
207
+ configurations,
208
+ generate: async () => {
209
+ send({ type: "generate" });
210
+ try {
211
+ await generated;
212
+ await exited;
213
+ if (failure) throw failure;
214
+ } finally {
215
+ await close();
216
+ }
217
+ },
218
+ close,
219
+ };
220
+ } catch (error) {
221
+ await close();
222
+ throw error;
223
+ }
224
+ };
225
+ }
226
+
227
+ const serializeError = (error: unknown, depth = 0): any => ({
228
+ message: error instanceof Error ? error.message : String(error),
229
+ cause:
230
+ error instanceof Error && error.cause !== undefined && depth < 10
231
+ ? serializeError(error.cause, depth + 1)
232
+ : undefined,
233
+ });
234
+
235
+ const deserializeError = (error: any): Error =>
236
+ new Error(error?.message ?? "Swagger generation failed.", {
237
+ cause:
238
+ error?.cause === undefined ? undefined : deserializeError(error.cause),
239
+ });
240
+
241
+ const projectConfigurations = (
242
+ configurations: INestiaConfig[],
243
+ ): INestiaConfig[] =>
244
+ configurations.map((config) => ({
245
+ input:
246
+ typeof config.input === "function"
247
+ ? fs.existsSync(path.resolve("src"))
248
+ ? path.resolve("src")
249
+ : process.cwd()
250
+ : config.input,
251
+ output: config.output,
252
+ e2e: config.e2e,
253
+ distribute: config.distribute,
254
+ swagger:
255
+ config.swagger === undefined
256
+ ? undefined
257
+ : { output: config.swagger.output },
258
+ }));
259
+
260
+ // Preserve runtime flags and preloads. Eval/print/input-mode switches select
261
+ // the parent's entry rather than this emitted child file. Inspector flags are
262
+ // negated last, including those inherited through NODE_OPTIONS, so children do
263
+ // not compete for the parent's debug port or wait for another debugger.
264
+ const workerExecArgv = (): string[] => {
265
+ const output: string[] = [];
266
+ for (let index = 0; index < process.execArgv.length; ++index) {
267
+ const argument = process.execArgv[index]!;
268
+ if (["-e", "--eval", "-p", "--print", "--input-type"].includes(argument)) {
269
+ ++index;
270
+ continue;
271
+ }
272
+ if (/^--(?:eval|print|input-type)=/.test(argument)) continue;
273
+ if (["-c", "--check", "--test"].includes(argument)) continue;
274
+ output.push(argument);
275
+ }
276
+ return [
277
+ ...output,
278
+ ...["--no-inspect", "--no-inspect-brk", "--no-inspect-wait"].filter(
279
+ (flag) => process.allowedNodeEnvironmentFlags.has(flag),
280
+ ),
281
+ ];
282
+ };
283
+
284
+ const childMain = (): void => {
285
+ let configurations: INestiaConfig[] | undefined;
286
+ let running = false;
287
+ const finish = (code: number): never => {
288
+ try {
289
+ TemporaryDirectory.dispose();
290
+ } catch (error) {
291
+ console.error(error);
292
+ code = 1;
293
+ }
294
+ process.exit(code);
295
+ };
296
+ const reply = (message: object, exitCode?: number): void => {
297
+ if (!process.connected) finish(0);
298
+ process.send!(message, (error) => {
299
+ if (error) {
300
+ if (!process.connected) finish(0);
301
+ console.error(error);
302
+ finish(1);
303
+ }
304
+ if (exitCode !== undefined) finish(exitCode);
305
+ });
306
+ };
307
+ process.once("disconnect", () => finish(0));
308
+ process.on("message", (message: any) => {
309
+ if (running) return;
310
+ running = true;
311
+ void (async () => {
312
+ try {
313
+ if (message?.type === "prepare") {
314
+ process.env.NESTIA_PROJECT = message.projectFile;
315
+ const options = await NestiaConfigLoader.compilerOptions(
316
+ message.projectFile,
317
+ );
318
+ configurations = await NestiaConfigLoader.configurations(
319
+ message.configFile,
320
+ options.raw.compilerOptions ?? {},
321
+ );
322
+ reply({
323
+ type: "prepared",
324
+ configurations: projectConfigurations(configurations),
325
+ });
326
+ } else if (
327
+ message?.type === "generate" &&
328
+ configurations !== undefined
329
+ ) {
330
+ if (
331
+ configurations.length > 1 &&
332
+ !configurations.some((config) => !!config.swagger?.output)
333
+ )
334
+ throw new Error(
335
+ "Every configurations are invalid to generate Swagger Document, configure INestiaConfig.swagger property.",
336
+ );
337
+ for (const config of configurations) {
338
+ if (configurations.length > 1 && !config.swagger?.output) continue;
339
+ await new NestiaSdkApplication(config).swagger();
340
+ }
341
+ TemporaryDirectory.dispose();
342
+ reply({ type: "complete" }, 0);
343
+ } else throw new Error("Invalid Swagger watch generation protocol.");
344
+ } catch (error) {
345
+ try {
346
+ TemporaryDirectory.dispose();
347
+ } catch (cleanup) {
348
+ console.error(cleanup);
349
+ }
350
+ reply({ type: "failed", error: serializeError(error) }, 1);
351
+ } finally {
352
+ running = false;
353
+ }
354
+ })();
355
+ });
356
+ };
357
+
358
+ if (require.main === module && process.env.NESTIA_WATCH_CHILD === "1")
359
+ childMain();
@@ -10,10 +10,25 @@ import {
10
10
  * `MinusToken` prefix unary, matching how the TypeScript factory itself emits
11
11
  * negative numeric literals.
12
12
  *
13
- * Infinity is written `1e999`, the literal that evaluates to it and the only
14
- * spelling that is also a literal type; `Infinity` names a value, not a type.
13
+ * Infinity is written `1e999`, a numeric literal that evaluates to it and can
14
+ * also appear in a literal type; `Infinity` names a value, not a type.
15
+ *
16
+ * @evidence contracts/common.md#principled-implementation The namespace holds the number literal builder.
17
+ * @evidence contracts/common.md#clear-and-simple-design One function.
18
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It only builds nodes.
19
+ * @evidence contracts/common.md#meaningful-documentation The comment states its purpose.
20
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation ExpressionFactory constructs TypeScript syntax nodes; it does not resolve native file identity or launch a process. Source resolution and file emission belong to their filesystem owners.
15
21
  */
16
22
  export namespace ExpressionFactory {
23
+ /**
24
+ * Builds a numeric literal, with a prefix minus for a negative value.
25
+ *
26
+ * @evidence contracts/common.md#principled-implementation A negative literal is a prefix unary minus on a positive literal in the syntax tree, so the builder produces that shape.
27
+ * @evidence contracts/common.md#clear-and-simple-design One conditional.
28
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts It follows the grammar.
29
+ * @evidence contracts/common.md#meaningful-documentation The comment states the negative case.
30
+ * @evidenceExclude contracts/portability.md#os-neutral-implementation ExpressionFactory.number constructs TypeScript syntax nodes; it does not resolve native file identity or launch a process. Source resolution and file emission belong to their filesystem owners.
31
+ */
17
32
  export const number = (
18
33
  value: number,
19
34
  ): NumericLiteral | PrefixUnaryExpression =>