@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,330 +1,330 @@
1
- /// <reference path="../typings/get-function-location.d.ts" />
2
- import { INestApplication, VersioningType } from "@nestjs/common";
3
- import { MODULE_PATH } from "@nestjs/common/constants";
4
- import { NestContainer } from "@nestjs/core";
5
- import { Module } from "@nestjs/core/injector/module";
6
- import fs from "fs";
7
- import getFunctionLocation from "get-function-location";
8
- import path from "path";
9
- import { HashMap, Pair, Singleton } from "tstl";
10
-
11
- import { INestiaConfig } from "../INestiaConfig";
12
- import { SdkGenerator } from "../generates/SdkGenerator";
13
- import { INestiaSdkInput } from "../structures/INestiaSdkInput";
14
- import { ArrayUtil } from "../utils/ArrayUtil";
15
- import { EmittedJavaScriptPatcher } from "../utils/EmittedJavaScriptPatcher";
16
- import { MapUtil } from "../utils/MapUtil";
17
- import { SourceFinder } from "../utils/SourceFinder";
18
- import { TsConfigReader } from "../utils/TsConfigReader";
19
- import { TtscExecutor } from "../utils/TtscExecutor";
20
-
21
- export namespace ConfigAnalyzer {
22
- export const input = async (
23
- config: INestiaConfig,
24
- ): Promise<INestiaSdkInput> => {
25
- return MapUtil.take(memory, config, async () => {
26
- if (typeof config.input === "function")
27
- return application(await config.input());
28
-
29
- const sources: string[] = await SourceFinder.find({
30
- include: Array.isArray(config.input)
31
- ? config.input
32
- : typeof config.input === "object"
33
- ? config.input.include
34
- : [config.input],
35
- exclude:
36
- typeof config.input === "object" && !Array.isArray(config.input)
37
- ? (config.input.exclude ?? [])
38
- : [],
39
- filter: filter(config),
40
- });
41
- const runtime: RuntimeCompiler = await RuntimeCompiler.compile(sources);
42
- const controllers: INestiaSdkInput.IController[] = [];
43
- for (const file of sources) {
44
- const external: any[] = await import(runtime.output(file));
45
- for (const key in external) {
46
- const instance: Function = external[key];
47
- if (Reflect.getMetadata("path", instance) !== undefined)
48
- controllers.push({
49
- class: instance,
50
- location: file,
51
- prefixes: [],
52
- });
53
- }
54
- }
55
- return {
56
- controllers,
57
- };
58
- });
59
- };
60
-
61
- export const application = async (
62
- app: INestApplication,
63
- ): Promise<INestiaSdkInput> => {
64
- const container: NestContainer = (app as any).container as NestContainer;
65
- const modules: Module[] = [...container.getModules().values()].filter(
66
- (m) => !!m.controllers.size,
67
- );
68
- const unique: HashMap<Function, Set<string>> = new HashMap();
69
-
70
- for (const m of modules) {
71
- const path: string =
72
- Reflect.getMetadata(
73
- MODULE_PATH + container.getModules().applicationId,
74
- m.metatype,
75
- ) ??
76
- Reflect.getMetadata(MODULE_PATH, m.metatype) ??
77
- "";
78
- for (const controller of [...m.controllers.keys()])
79
- if (typeof controller === "function")
80
- unique.take(controller, () => new Set()).add(path);
81
- }
82
- const controllers: INestiaSdkInput.IController[] = [];
83
- for (const it of unique) {
84
- const file: string | null =
85
- (await getFunctionLocation(it.first))?.source ?? null;
86
- if (file === null) continue;
87
- const location: string = normalize_file(file);
88
- if (location.length === 0) continue;
89
- controllers.push({
90
- class: it.first,
91
- prefixes: Array.from(it.second),
92
- location,
93
- });
94
- }
95
-
96
- const versioning = (app as any).config?.versioningOptions;
97
- return {
98
- controllers,
99
- globalPrefix:
100
- typeof (app as any).config?.globalPrefix === "string"
101
- ? {
102
- prefix: (app as any).config.globalPrefix,
103
- exclude: (app as any).config.globalPrefixOptions?.exclude ?? {},
104
- }
105
- : undefined,
106
- versioning:
107
- versioning === undefined || versioning.type !== VersioningType.URI
108
- ? undefined
109
- : {
110
- prefix:
111
- versioning.prefix === undefined || versioning.prefix === false
112
- ? "v"
113
- : versioning.prefix,
114
- defaultVersion: versioning.defaultVersion,
115
- },
116
- };
117
- };
118
- }
119
- const memory = new Map<INestiaConfig, Promise<INestiaSdkInput>>();
120
- class RuntimeCompiler {
121
- private constructor(
122
- private readonly cwd: string,
123
- private readonly outDir: string,
124
- ) {}
125
-
126
- public static async compile(sources: string[]): Promise<RuntimeCompiler> {
127
- const cwd: string = process.cwd();
128
- const runtimeRoot: string = path.join(
129
- cwd,
130
- "node_modules",
131
- ".nestia",
132
- "runtime",
133
- );
134
- await fs.promises.mkdir(runtimeRoot, { recursive: true });
135
- ensureRuntimeCleanup(runtimeRoot);
136
- const outDir: string = await fs.promises.mkdtemp(
137
- path.join(runtimeRoot, "run-"),
138
- );
139
- const project: string = path.join(
140
- cwd,
141
- `.nestia.runtime.${process.pid}.${Date.now()}.json`,
142
- );
143
- const relative = (file: string): string =>
144
- path.relative(cwd, file).split("\\").join("/");
145
- await fs.promises.writeFile(
146
- project,
147
- JSON.stringify(
148
- {
149
- extends: normalizeProjectPath(process.env.NESTIA_PROJECT),
150
- compilerOptions: {
151
- noEmit: false,
152
- noUnusedLocals: false,
153
- noUnusedParameters: false,
154
- outDir,
155
- plugins: await runtimePlugins(cwd),
156
- rootDir: ".",
157
- },
158
- include: sources.map(relative),
159
- },
160
- null,
161
- 2,
162
- ),
163
- "utf8",
164
- );
165
- try {
166
- TtscExecutor.run({
167
- cwd,
168
- env: sdkTransformEnv(),
169
- project,
170
- });
171
- } catch (error) {
172
- const output =
173
- error instanceof Error && "stderr" in error
174
- ? String((error as Error & { stderr?: Buffer }).stderr ?? "")
175
- : "";
176
- throw new Error(output || `Failed to compile Nestia runtime inputs.`);
177
- } finally {
178
- await fs.promises.rm(project, { force: true });
179
- }
180
- await EmittedJavaScriptPatcher.importMetaUrl(outDir);
181
- return new RuntimeCompiler(cwd, outDir);
182
- }
183
-
184
- public output(source: string): string {
185
- const relative: string = path.relative(this.cwd, source);
186
- const emitted: string = path.join(
187
- this.outDir,
188
- replaceExtension(relative, ".js"),
189
- );
190
- return emitted;
191
- }
192
- }
193
-
194
- const RUNTIME_ROOTS: Set<string> = new Set();
195
- let RUNTIME_CLEANUP_REGISTERED: boolean = false;
196
-
197
- const ensureRuntimeCleanup = (runtimeRoot: string): void => {
198
- RUNTIME_ROOTS.add(runtimeRoot);
199
- if (RUNTIME_CLEANUP_REGISTERED === true) return;
200
- RUNTIME_CLEANUP_REGISTERED = true;
201
- const sweep = (): void => {
202
- for (const location of RUNTIME_ROOTS)
203
- fs.rmSync(location, { force: true, recursive: true });
204
- };
205
- process.once("exit", sweep);
206
- // process.once("exit", …) does not fire on SIGINT/SIGTERM. Without these
207
- // handlers a Ctrl-C during codegen leaves `run-*` mkdtemp directories
208
- // behind under node_modules/.nestia/runtime/ until a subsequent clean exit.
209
- // The module-level RUNTIME_CLEANUP_REGISTERED flag above guards against
210
- // re-entrancy within this module; we deliberately do NOT gate on
211
- // `process.listenerCount(signal) > 0` because NestiaConfigLoader's parallel
212
- // sweep registers first, and that gate would skip our registration —
213
- // leaving RUNTIME_ROOTS unswept on Ctrl-C while config-loader cleans up.
214
- // Windows note: `process.kill(pid, "SIGINT")` calls TerminateProcess
215
- // rather than re-raising through the listener queue, so the handler
216
- // cascade documented above only holds on POSIX. On Windows, whichever
217
- // module registers FIRST runs its sweep and the second is skipped —
218
- // RUNTIME_ROOTS cleanup is best-effort there. SIGHUP is a no-op for
219
- // most common code paths on Windows (Node fires it on console-close
220
- // and exits within seconds).
221
- const onSignal = (signal: NodeJS.Signals): void => {
222
- sweep();
223
- process.kill(process.pid, signal);
224
- };
225
- for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"] as const) {
226
- process.once(signal, onSignal);
227
- }
228
- };
229
-
230
- type RuntimePlugin = Record<string, unknown> & { transform?: unknown };
231
-
232
- const sdkTransformEnv = (): NodeJS.ProcessEnv =>
233
- process.env.NESTIA_SDK_TRANSFORM === undefined
234
- ? { NESTIA_SDK_TRANSFORM: "1" }
235
- : {};
236
-
237
- const runtimePlugins = async (cwd: string): Promise<RuntimePlugin[]> => {
238
- const plugins: RuntimePlugin[] = await readProjectPlugins(cwd);
239
- const typia: RuntimePlugin | undefined = plugins.find((p) =>
240
- isTransform(p, "typia"),
241
- );
242
- const core: RuntimePlugin | undefined = plugins.find((p) =>
243
- isTransform(p, "@nestia/core"),
244
- );
245
- return [
246
- {
247
- ...(typia ?? {}),
248
- transform: "typia/lib/transform",
249
- enabled: false,
250
- },
251
- normalizeRuntimePlugin({
252
- ...(core ?? {}),
253
- transform: "@nestia/core/native/transform.cjs",
254
- }),
255
- ];
256
- };
257
-
258
- const readProjectPlugins = async (cwd: string): Promise<RuntimePlugin[]> => {
259
- const project: string = normalizeProjectPath(process.env.NESTIA_PROJECT);
260
- const file: string = path.isAbsolute(project)
261
- ? project
262
- : path.join(cwd, project);
263
- const config = await TsConfigReader.read(file);
264
- const options = config.compilerOptions as
265
- | { plugins?: RuntimePlugin[] }
266
- | undefined;
267
- return Array.isArray(options?.plugins)
268
- ? options.plugins
269
- .filter((p) => typeof p === "object" && p !== null)
270
- .map((p) => ({ ...(p as unknown as RuntimePlugin) }))
271
- : [];
272
- };
273
-
274
- const normalizeRuntimePlugin = (plugin: RuntimePlugin): RuntimePlugin => {
275
- const output: RuntimePlugin = { ...plugin };
276
- if (output.enabled === false) delete output.enabled;
277
- return output;
278
- };
279
-
280
- const isTransform = (plugin: RuntimePlugin, name: string): boolean =>
281
- typeof plugin.transform === "string" && plugin.transform.includes(name);
282
-
283
- const replaceExtension = (file: string, extension: string): string =>
284
- file.replace(/\.[cm]?tsx?$/i, extension);
285
-
286
- const normalizeProjectPath = (project: string | undefined): string => {
287
- const next: string = project ?? "tsconfig.json";
288
- return path.isAbsolute(next) || next.startsWith(".") ? next : `./${next}`;
289
- };
290
-
291
- const normalize_file = (str: string) =>
292
- str.substring(
293
- str.startsWith("file:///")
294
- ? process.cwd()[0] === "/"
295
- ? 7
296
- : 8
297
- : str.startsWith("file://")
298
- ? 7
299
- : 0,
300
- );
301
-
302
- const filter =
303
- (config: INestiaConfig) =>
304
- async (location: string): Promise<boolean> =>
305
- location.endsWith(".ts") &&
306
- !location.endsWith(".d.ts") &&
307
- (config.output === undefined ||
308
- (location.indexOf(path.join(config.output, "functional")) === -1 &&
309
- (await (
310
- await bundler.get(config.output)
311
- )(location))) === false);
312
-
313
- const bundler = new Singleton(async (output: string) => {
314
- const assets: string[] = await fs.promises.readdir(SdkGenerator.BUNDLE_PATH);
315
- const tuples: Pair<string, boolean>[] = await ArrayUtil.asyncMap(
316
- assets,
317
- async (file) => {
318
- const relative: string = path.join(output, file);
319
- const location: string = path.join(SdkGenerator.BUNDLE_PATH, file);
320
- const stats: fs.Stats = await fs.promises.stat(location);
321
- return new Pair(relative, stats.isDirectory());
322
- },
323
- );
324
- return async (file: string): Promise<boolean> => {
325
- for (const it of tuples)
326
- if (it.second === false && file === it.first) return true;
327
- else if (it.second === true && file.indexOf(it.first) === 0) return true;
328
- return false;
329
- };
330
- });
1
+ /// <reference path="../typings/get-function-location.d.ts" />
2
+ import { INestApplication, VersioningType } from "@nestjs/common";
3
+ import { MODULE_PATH } from "@nestjs/common/constants";
4
+ import { NestContainer } from "@nestjs/core";
5
+ import { Module } from "@nestjs/core/injector/module";
6
+ import fs from "fs";
7
+ import getFunctionLocation from "get-function-location";
8
+ import path from "path";
9
+ import { HashMap, Pair, Singleton } from "tstl";
10
+
11
+ import { INestiaConfig } from "../INestiaConfig";
12
+ import { SdkGenerator } from "../generates/SdkGenerator";
13
+ import { INestiaSdkInput } from "../structures/INestiaSdkInput";
14
+ import { ArrayUtil } from "../utils/ArrayUtil";
15
+ import { EmittedJavaScriptPatcher } from "../utils/EmittedJavaScriptPatcher";
16
+ import { MapUtil } from "../utils/MapUtil";
17
+ import { SourceFinder } from "../utils/SourceFinder";
18
+ import { TsConfigReader } from "../utils/TsConfigReader";
19
+ import { TtscExecutor } from "../utils/TtscExecutor";
20
+
21
+ export namespace ConfigAnalyzer {
22
+ export const input = async (
23
+ config: INestiaConfig,
24
+ ): Promise<INestiaSdkInput> => {
25
+ return MapUtil.take(memory, config, async () => {
26
+ if (typeof config.input === "function")
27
+ return application(await config.input());
28
+
29
+ const sources: string[] = await SourceFinder.find({
30
+ include: Array.isArray(config.input)
31
+ ? config.input
32
+ : typeof config.input === "object"
33
+ ? config.input.include
34
+ : [config.input],
35
+ exclude:
36
+ typeof config.input === "object" && !Array.isArray(config.input)
37
+ ? (config.input.exclude ?? [])
38
+ : [],
39
+ filter: filter(config),
40
+ });
41
+ const runtime: RuntimeCompiler = await RuntimeCompiler.compile(sources);
42
+ const controllers: INestiaSdkInput.IController[] = [];
43
+ for (const file of sources) {
44
+ const external: any[] = await import(runtime.output(file));
45
+ for (const key in external) {
46
+ const instance: Function = external[key];
47
+ if (Reflect.getMetadata("path", instance) !== undefined)
48
+ controllers.push({
49
+ class: instance,
50
+ location: file,
51
+ prefixes: [],
52
+ });
53
+ }
54
+ }
55
+ return {
56
+ controllers,
57
+ };
58
+ });
59
+ };
60
+
61
+ export const application = async (
62
+ app: INestApplication,
63
+ ): Promise<INestiaSdkInput> => {
64
+ const container: NestContainer = (app as any).container as NestContainer;
65
+ const modules: Module[] = [...container.getModules().values()].filter(
66
+ (m) => !!m.controllers.size,
67
+ );
68
+ const unique: HashMap<Function, Set<string>> = new HashMap();
69
+
70
+ for (const m of modules) {
71
+ const path: string =
72
+ Reflect.getMetadata(
73
+ MODULE_PATH + container.getModules().applicationId,
74
+ m.metatype,
75
+ ) ??
76
+ Reflect.getMetadata(MODULE_PATH, m.metatype) ??
77
+ "";
78
+ for (const controller of [...m.controllers.keys()])
79
+ if (typeof controller === "function")
80
+ unique.take(controller, () => new Set()).add(path);
81
+ }
82
+ const controllers: INestiaSdkInput.IController[] = [];
83
+ for (const it of unique) {
84
+ const file: string | null =
85
+ (await getFunctionLocation(it.first))?.source ?? null;
86
+ if (file === null) continue;
87
+ const location: string = normalize_file(file);
88
+ if (location.length === 0) continue;
89
+ controllers.push({
90
+ class: it.first,
91
+ prefixes: Array.from(it.second),
92
+ location,
93
+ });
94
+ }
95
+
96
+ const versioning = (app as any).config?.versioningOptions;
97
+ return {
98
+ controllers,
99
+ globalPrefix:
100
+ typeof (app as any).config?.globalPrefix === "string"
101
+ ? {
102
+ prefix: (app as any).config.globalPrefix,
103
+ exclude: (app as any).config.globalPrefixOptions?.exclude ?? [],
104
+ }
105
+ : undefined,
106
+ versioning:
107
+ versioning === undefined || versioning.type !== VersioningType.URI
108
+ ? undefined
109
+ : {
110
+ prefix:
111
+ versioning.prefix === undefined || versioning.prefix === false
112
+ ? "v"
113
+ : versioning.prefix,
114
+ defaultVersion: versioning.defaultVersion,
115
+ },
116
+ };
117
+ };
118
+ }
119
+ const memory = new Map<INestiaConfig, Promise<INestiaSdkInput>>();
120
+ class RuntimeCompiler {
121
+ private constructor(
122
+ private readonly cwd: string,
123
+ private readonly outDir: string,
124
+ ) {}
125
+
126
+ public static async compile(sources: string[]): Promise<RuntimeCompiler> {
127
+ const cwd: string = process.cwd();
128
+ const runtimeRoot: string = path.join(
129
+ cwd,
130
+ "node_modules",
131
+ ".nestia",
132
+ "runtime",
133
+ );
134
+ await fs.promises.mkdir(runtimeRoot, { recursive: true });
135
+ ensureRuntimeCleanup(runtimeRoot);
136
+ const outDir: string = await fs.promises.mkdtemp(
137
+ path.join(runtimeRoot, "run-"),
138
+ );
139
+ const project: string = path.join(
140
+ cwd,
141
+ `.nestia.runtime.${process.pid}.${Date.now()}.json`,
142
+ );
143
+ const relative = (file: string): string =>
144
+ path.relative(cwd, file).split("\\").join("/");
145
+ await fs.promises.writeFile(
146
+ project,
147
+ JSON.stringify(
148
+ {
149
+ extends: normalizeProjectPath(process.env.NESTIA_PROJECT),
150
+ compilerOptions: {
151
+ noEmit: false,
152
+ noUnusedLocals: false,
153
+ noUnusedParameters: false,
154
+ outDir,
155
+ plugins: await runtimePlugins(cwd),
156
+ rootDir: ".",
157
+ },
158
+ include: sources.map(relative),
159
+ },
160
+ null,
161
+ 2,
162
+ ),
163
+ "utf8",
164
+ );
165
+ try {
166
+ TtscExecutor.run({
167
+ cwd,
168
+ env: sdkTransformEnv(),
169
+ project,
170
+ });
171
+ } catch (error) {
172
+ const output =
173
+ error instanceof Error && "stderr" in error
174
+ ? String((error as Error & { stderr?: Buffer }).stderr ?? "")
175
+ : "";
176
+ throw new Error(output || `Failed to compile Nestia runtime inputs.`);
177
+ } finally {
178
+ await fs.promises.rm(project, { force: true });
179
+ }
180
+ await EmittedJavaScriptPatcher.importMetaUrl(outDir);
181
+ return new RuntimeCompiler(cwd, outDir);
182
+ }
183
+
184
+ public output(source: string): string {
185
+ const relative: string = path.relative(this.cwd, source);
186
+ const emitted: string = path.join(
187
+ this.outDir,
188
+ replaceExtension(relative, ".js"),
189
+ );
190
+ return emitted;
191
+ }
192
+ }
193
+
194
+ const RUNTIME_ROOTS: Set<string> = new Set();
195
+ let RUNTIME_CLEANUP_REGISTERED: boolean = false;
196
+
197
+ const ensureRuntimeCleanup = (runtimeRoot: string): void => {
198
+ RUNTIME_ROOTS.add(runtimeRoot);
199
+ if (RUNTIME_CLEANUP_REGISTERED === true) return;
200
+ RUNTIME_CLEANUP_REGISTERED = true;
201
+ const sweep = (): void => {
202
+ for (const location of RUNTIME_ROOTS)
203
+ fs.rmSync(location, { force: true, recursive: true });
204
+ };
205
+ process.once("exit", sweep);
206
+ // process.once("exit", …) does not fire on SIGINT/SIGTERM. Without these
207
+ // handlers a Ctrl-C during codegen leaves `run-*` mkdtemp directories
208
+ // behind under node_modules/.nestia/runtime/ until a subsequent clean exit.
209
+ // The module-level RUNTIME_CLEANUP_REGISTERED flag above guards against
210
+ // re-entrancy within this module; we deliberately do NOT gate on
211
+ // `process.listenerCount(signal) > 0` because NestiaConfigLoader's parallel
212
+ // sweep registers first, and that gate would skip our registration —
213
+ // leaving RUNTIME_ROOTS unswept on Ctrl-C while config-loader cleans up.
214
+ // Windows note: `process.kill(pid, "SIGINT")` calls TerminateProcess
215
+ // rather than re-raising through the listener queue, so the handler
216
+ // cascade documented above only holds on POSIX. On Windows, whichever
217
+ // module registers FIRST runs its sweep and the second is skipped —
218
+ // RUNTIME_ROOTS cleanup is best-effort there. SIGHUP is a no-op for
219
+ // most common code paths on Windows (Node fires it on console-close
220
+ // and exits within seconds).
221
+ const onSignal = (signal: NodeJS.Signals): void => {
222
+ sweep();
223
+ process.kill(process.pid, signal);
224
+ };
225
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"] as const) {
226
+ process.once(signal, onSignal);
227
+ }
228
+ };
229
+
230
+ type RuntimePlugin = Record<string, unknown> & { transform?: unknown };
231
+
232
+ const sdkTransformEnv = (): NodeJS.ProcessEnv =>
233
+ process.env.NESTIA_SDK_TRANSFORM === undefined
234
+ ? { NESTIA_SDK_TRANSFORM: "1" }
235
+ : {};
236
+
237
+ const runtimePlugins = async (cwd: string): Promise<RuntimePlugin[]> => {
238
+ const plugins: RuntimePlugin[] = await readProjectPlugins(cwd);
239
+ const typia: RuntimePlugin | undefined = plugins.find((p) =>
240
+ isTransform(p, "typia"),
241
+ );
242
+ const core: RuntimePlugin | undefined = plugins.find((p) =>
243
+ isTransform(p, "@nestia/core"),
244
+ );
245
+ return [
246
+ {
247
+ ...(typia ?? {}),
248
+ transform: "typia/lib/transform",
249
+ enabled: false,
250
+ },
251
+ normalizeRuntimePlugin({
252
+ ...(core ?? {}),
253
+ transform: "@nestia/core/native/transform.cjs",
254
+ }),
255
+ ];
256
+ };
257
+
258
+ const readProjectPlugins = async (cwd: string): Promise<RuntimePlugin[]> => {
259
+ const project: string = normalizeProjectPath(process.env.NESTIA_PROJECT);
260
+ const file: string = path.isAbsolute(project)
261
+ ? project
262
+ : path.join(cwd, project);
263
+ const config = await TsConfigReader.read(file);
264
+ const options = config.compilerOptions as
265
+ | { plugins?: RuntimePlugin[] }
266
+ | undefined;
267
+ return Array.isArray(options?.plugins)
268
+ ? options.plugins
269
+ .filter((p) => typeof p === "object" && p !== null)
270
+ .map((p) => ({ ...(p as unknown as RuntimePlugin) }))
271
+ : [];
272
+ };
273
+
274
+ const normalizeRuntimePlugin = (plugin: RuntimePlugin): RuntimePlugin => {
275
+ const output: RuntimePlugin = { ...plugin };
276
+ if (output.enabled === false) delete output.enabled;
277
+ return output;
278
+ };
279
+
280
+ const isTransform = (plugin: RuntimePlugin, name: string): boolean =>
281
+ typeof plugin.transform === "string" && plugin.transform.includes(name);
282
+
283
+ const replaceExtension = (file: string, extension: string): string =>
284
+ file.replace(/\.[cm]?tsx?$/i, extension);
285
+
286
+ const normalizeProjectPath = (project: string | undefined): string => {
287
+ const next: string = project ?? "tsconfig.json";
288
+ return path.isAbsolute(next) || next.startsWith(".") ? next : `./${next}`;
289
+ };
290
+
291
+ const normalize_file = (str: string) =>
292
+ str.substring(
293
+ str.startsWith("file:///")
294
+ ? process.cwd()[0] === "/"
295
+ ? 7
296
+ : 8
297
+ : str.startsWith("file://")
298
+ ? 7
299
+ : 0,
300
+ );
301
+
302
+ const filter =
303
+ (config: INestiaConfig) =>
304
+ async (location: string): Promise<boolean> =>
305
+ location.endsWith(".ts") &&
306
+ !location.endsWith(".d.ts") &&
307
+ (config.output === undefined ||
308
+ (location.indexOf(path.join(config.output, "functional")) === -1 &&
309
+ (await (
310
+ await bundler.get(config.output)
311
+ )(location))) === false);
312
+
313
+ const bundler = new Singleton(async (output: string) => {
314
+ const assets: string[] = await fs.promises.readdir(SdkGenerator.BUNDLE_PATH);
315
+ const tuples: Pair<string, boolean>[] = await ArrayUtil.asyncMap(
316
+ assets,
317
+ async (file) => {
318
+ const relative: string = path.join(output, file);
319
+ const location: string = path.join(SdkGenerator.BUNDLE_PATH, file);
320
+ const stats: fs.Stats = await fs.promises.stat(location);
321
+ return new Pair(relative, stats.isDirectory());
322
+ },
323
+ );
324
+ return async (file: string): Promise<boolean> => {
325
+ for (const it of tuples)
326
+ if (it.second === false && file === it.first) return true;
327
+ else if (it.second === true && file.indexOf(it.first) === 0) return true;
328
+ return false;
329
+ };
330
+ });