@trapi/metadata 1.3.0 → 2.0.0-beta.0

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 (350) hide show
  1. package/README.md +63 -16
  2. package/dist/index.d.mts +1718 -0
  3. package/dist/index.d.mts.map +1 -0
  4. package/dist/index.mjs +3310 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +25 -13
  7. package/dist/cache/client.d.ts +0 -15
  8. package/dist/cache/client.d.ts.map +0 -1
  9. package/dist/cache/client.js +0 -98
  10. package/dist/cache/client.js.map +0 -1
  11. package/dist/cache/index.d.ts +0 -4
  12. package/dist/cache/index.d.ts.map +0 -1
  13. package/dist/cache/index.js +0 -26
  14. package/dist/cache/index.js.map +0 -1
  15. package/dist/cache/type.d.ts +0 -33
  16. package/dist/cache/type.d.ts.map +0 -1
  17. package/dist/cache/type.js +0 -9
  18. package/dist/cache/type.js.map +0 -1
  19. package/dist/cache/utils.d.ts +0 -4
  20. package/dist/cache/utils.d.ts.map +0 -1
  21. package/dist/cache/utils.js +0 -52
  22. package/dist/cache/utils.js.map +0 -1
  23. package/dist/config/index.d.ts +0 -2
  24. package/dist/config/index.d.ts.map +0 -1
  25. package/dist/config/index.js +0 -24
  26. package/dist/config/index.js.map +0 -1
  27. package/dist/config/type.d.ts +0 -37
  28. package/dist/config/type.d.ts.map +0 -1
  29. package/dist/config/type.js +0 -9
  30. package/dist/config/type.js.map +0 -1
  31. package/dist/decorator/constants.d.ts +0 -41
  32. package/dist/decorator/constants.d.ts.map +0 -1
  33. package/dist/decorator/constants.js +0 -53
  34. package/dist/decorator/constants.js.map +0 -1
  35. package/dist/decorator/index.d.ts +0 -7
  36. package/dist/decorator/index.d.ts.map +0 -1
  37. package/dist/decorator/index.js +0 -29
  38. package/dist/decorator/index.js.map +0 -1
  39. package/dist/decorator/preset/index.d.ts +0 -3
  40. package/dist/decorator/preset/index.d.ts.map +0 -1
  41. package/dist/decorator/preset/index.js +0 -25
  42. package/dist/decorator/preset/index.js.map +0 -1
  43. package/dist/decorator/preset/type.d.ts +0 -6
  44. package/dist/decorator/preset/type.d.ts.map +0 -1
  45. package/dist/decorator/preset/type.js +0 -9
  46. package/dist/decorator/preset/type.js.map +0 -1
  47. package/dist/decorator/preset/utils/check.d.ts +0 -3
  48. package/dist/decorator/preset/utils/check.d.ts.map +0 -1
  49. package/dist/decorator/preset/utils/check.js +0 -17
  50. package/dist/decorator/preset/utils/check.js.map +0 -1
  51. package/dist/decorator/preset/utils/index.d.ts +0 -4
  52. package/dist/decorator/preset/utils/index.d.ts.map +0 -1
  53. package/dist/decorator/preset/utils/index.js +0 -26
  54. package/dist/decorator/preset/utils/index.js.map +0 -1
  55. package/dist/decorator/preset/utils/load.d.ts +0 -3
  56. package/dist/decorator/preset/utils/load.d.ts.map +0 -1
  57. package/dist/decorator/preset/utils/load.js +0 -50
  58. package/dist/decorator/preset/utils/load.js.map +0 -1
  59. package/dist/decorator/preset/utils/normalize.d.ts +0 -2
  60. package/dist/decorator/preset/utils/normalize.d.ts.map +0 -1
  61. package/dist/decorator/preset/utils/normalize.js +0 -26
  62. package/dist/decorator/preset/utils/normalize.js.map +0 -1
  63. package/dist/decorator/property-manager/index.d.ts +0 -3
  64. package/dist/decorator/property-manager/index.d.ts.map +0 -1
  65. package/dist/decorator/property-manager/index.js +0 -25
  66. package/dist/decorator/property-manager/index.js.map +0 -1
  67. package/dist/decorator/property-manager/module.d.ts +0 -17
  68. package/dist/decorator/property-manager/module.d.ts.map +0 -1
  69. package/dist/decorator/property-manager/module.js +0 -59
  70. package/dist/decorator/property-manager/module.js.map +0 -1
  71. package/dist/decorator/property-manager/utils.d.ts +0 -6
  72. package/dist/decorator/property-manager/utils.d.ts.map +0 -1
  73. package/dist/decorator/property-manager/utils.js +0 -91
  74. package/dist/decorator/property-manager/utils.js.map +0 -1
  75. package/dist/decorator/resolver/index.d.ts +0 -3
  76. package/dist/decorator/resolver/index.d.ts.map +0 -1
  77. package/dist/decorator/resolver/index.js +0 -25
  78. package/dist/decorator/resolver/index.js.map +0 -1
  79. package/dist/decorator/resolver/module.d.ts +0 -27
  80. package/dist/decorator/resolver/module.d.ts.map +0 -1
  81. package/dist/decorator/resolver/module.js +0 -72
  82. package/dist/decorator/resolver/module.js.map +0 -1
  83. package/dist/decorator/resolver/type.d.ts +0 -10
  84. package/dist/decorator/resolver/type.d.ts.map +0 -1
  85. package/dist/decorator/resolver/type.js +0 -3
  86. package/dist/decorator/resolver/type.js.map +0 -1
  87. package/dist/decorator/sets/class.d.ts +0 -7
  88. package/dist/decorator/sets/class.d.ts.map +0 -1
  89. package/dist/decorator/sets/class.js +0 -9
  90. package/dist/decorator/sets/class.js.map +0 -1
  91. package/dist/decorator/sets/index.d.ts +0 -8
  92. package/dist/decorator/sets/index.d.ts.map +0 -1
  93. package/dist/decorator/sets/index.js +0 -29
  94. package/dist/decorator/sets/index.js.map +0 -1
  95. package/dist/decorator/sets/method.d.ts +0 -14
  96. package/dist/decorator/sets/method.d.ts.map +0 -1
  97. package/dist/decorator/sets/method.js +0 -9
  98. package/dist/decorator/sets/method.js.map +0 -1
  99. package/dist/decorator/sets/mixed.d.ts +0 -12
  100. package/dist/decorator/sets/mixed.d.ts.map +0 -1
  101. package/dist/decorator/sets/mixed.js +0 -9
  102. package/dist/decorator/sets/mixed.js.map +0 -1
  103. package/dist/decorator/sets/parameter.d.ts +0 -21
  104. package/dist/decorator/sets/parameter.d.ts.map +0 -1
  105. package/dist/decorator/sets/parameter.js +0 -9
  106. package/dist/decorator/sets/parameter.js.map +0 -1
  107. package/dist/decorator/sets/request.d.ts +0 -6
  108. package/dist/decorator/sets/request.d.ts.map +0 -1
  109. package/dist/decorator/sets/request.js +0 -9
  110. package/dist/decorator/sets/request.js.map +0 -1
  111. package/dist/decorator/sets/response.d.ts +0 -17
  112. package/dist/decorator/sets/response.d.ts.map +0 -1
  113. package/dist/decorator/sets/response.js +0 -9
  114. package/dist/decorator/sets/response.js.map +0 -1
  115. package/dist/decorator/sets/type.d.ts +0 -4
  116. package/dist/decorator/sets/type.d.ts.map +0 -1
  117. package/dist/decorator/sets/type.js +0 -3
  118. package/dist/decorator/sets/type.js.map +0 -1
  119. package/dist/decorator/type.d.ts +0 -32
  120. package/dist/decorator/type.d.ts.map +0 -1
  121. package/dist/decorator/type.js +0 -9
  122. package/dist/decorator/type.js.map +0 -1
  123. package/dist/error/base.d.ts +0 -3
  124. package/dist/error/base.d.ts.map +0 -1
  125. package/dist/error/base.js +0 -13
  126. package/dist/error/base.js.map +0 -1
  127. package/dist/error/index.d.ts +0 -2
  128. package/dist/error/index.d.ts.map +0 -1
  129. package/dist/error/index.js +0 -24
  130. package/dist/error/index.js.map +0 -1
  131. package/dist/generator/abstract.d.ts +0 -19
  132. package/dist/generator/abstract.d.ts.map +0 -1
  133. package/dist/generator/abstract.js +0 -151
  134. package/dist/generator/abstract.js.map +0 -1
  135. package/dist/generator/controller/index.d.ts +0 -3
  136. package/dist/generator/controller/index.d.ts.map +0 -1
  137. package/dist/generator/controller/index.js +0 -25
  138. package/dist/generator/controller/index.js.map +0 -1
  139. package/dist/generator/controller/module.d.ts +0 -13
  140. package/dist/generator/controller/module.d.ts.map +0 -1
  141. package/dist/generator/controller/module.js +0 -68
  142. package/dist/generator/controller/module.js.map +0 -1
  143. package/dist/generator/controller/type.d.ts +0 -47
  144. package/dist/generator/controller/type.d.ts.map +0 -1
  145. package/dist/generator/controller/type.js +0 -3
  146. package/dist/generator/controller/type.js.map +0 -1
  147. package/dist/generator/index.d.ts +0 -7
  148. package/dist/generator/index.d.ts.map +0 -1
  149. package/dist/generator/index.js +0 -29
  150. package/dist/generator/index.js.map +0 -1
  151. package/dist/generator/metadata/index.d.ts +0 -4
  152. package/dist/generator/metadata/index.d.ts.map +0 -1
  153. package/dist/generator/metadata/index.js +0 -26
  154. package/dist/generator/metadata/index.js.map +0 -1
  155. package/dist/generator/metadata/module.d.ts +0 -39
  156. package/dist/generator/metadata/module.d.ts.map +0 -1
  157. package/dist/generator/metadata/module.js +0 -140
  158. package/dist/generator/metadata/module.js.map +0 -1
  159. package/dist/generator/metadata/type.d.ts +0 -25
  160. package/dist/generator/metadata/type.d.ts.map +0 -1
  161. package/dist/generator/metadata/type.js +0 -3
  162. package/dist/generator/metadata/type.js.map +0 -1
  163. package/dist/generator/metadata/utils.d.ts +0 -3
  164. package/dist/generator/metadata/utils.d.ts.map +0 -1
  165. package/dist/generator/metadata/utils.js +0 -18
  166. package/dist/generator/metadata/utils.js.map +0 -1
  167. package/dist/generator/method/constants.d.ts +0 -11
  168. package/dist/generator/method/constants.d.ts.map +0 -1
  169. package/dist/generator/method/constants.js +0 -21
  170. package/dist/generator/method/constants.js.map +0 -1
  171. package/dist/generator/method/index.d.ts +0 -4
  172. package/dist/generator/method/index.d.ts.map +0 -1
  173. package/dist/generator/method/index.js +0 -26
  174. package/dist/generator/method/index.js.map +0 -1
  175. package/dist/generator/method/module.d.ts +0 -19
  176. package/dist/generator/method/module.d.ts.map +0 -1
  177. package/dist/generator/method/module.js +0 -188
  178. package/dist/generator/method/module.js.map +0 -1
  179. package/dist/generator/method/type.d.ts +0 -23
  180. package/dist/generator/method/type.d.ts.map +0 -1
  181. package/dist/generator/method/type.js +0 -9
  182. package/dist/generator/method/type.js.map +0 -1
  183. package/dist/generator/parameter/constants.d.ts +0 -19
  184. package/dist/generator/parameter/constants.d.ts.map +0 -1
  185. package/dist/generator/parameter/constants.js +0 -30
  186. package/dist/generator/parameter/constants.js.map +0 -1
  187. package/dist/generator/parameter/error.d.ts +0 -35
  188. package/dist/generator/parameter/error.d.ts.map +0 -1
  189. package/dist/generator/parameter/error.js +0 -68
  190. package/dist/generator/parameter/error.js.map +0 -1
  191. package/dist/generator/parameter/index.d.ts +0 -5
  192. package/dist/generator/parameter/index.d.ts.map +0 -1
  193. package/dist/generator/parameter/index.js +0 -27
  194. package/dist/generator/parameter/index.js.map +0 -1
  195. package/dist/generator/parameter/module.d.ts +0 -29
  196. package/dist/generator/parameter/module.d.ts.map +0 -1
  197. package/dist/generator/parameter/module.js +0 -566
  198. package/dist/generator/parameter/module.js.map +0 -1
  199. package/dist/generator/parameter/type.d.ts +0 -25
  200. package/dist/generator/parameter/type.d.ts.map +0 -1
  201. package/dist/generator/parameter/type.js +0 -9
  202. package/dist/generator/parameter/type.js.map +0 -1
  203. package/dist/generator/type.d.ts +0 -20
  204. package/dist/generator/type.d.ts.map +0 -1
  205. package/dist/generator/type.js +0 -9
  206. package/dist/generator/type.js.map +0 -1
  207. package/dist/index.d.ts +0 -10
  208. package/dist/index.d.ts.map +0 -1
  209. package/dist/index.js +0 -32
  210. package/dist/index.js.map +0 -1
  211. package/dist/module.d.ts +0 -5
  212. package/dist/module.d.ts.map +0 -1
  213. package/dist/module.js +0 -40
  214. package/dist/module.js.map +0 -1
  215. package/dist/resolver/constants.d.ts +0 -37
  216. package/dist/resolver/constants.d.ts.map +0 -1
  217. package/dist/resolver/constants.js +0 -48
  218. package/dist/resolver/constants.js.map +0 -1
  219. package/dist/resolver/error.d.ts +0 -8
  220. package/dist/resolver/error.d.ts.map +0 -1
  221. package/dist/resolver/error.js +0 -41
  222. package/dist/resolver/error.js.map +0 -1
  223. package/dist/resolver/extension/index.d.ts +0 -3
  224. package/dist/resolver/extension/index.d.ts.map +0 -1
  225. package/dist/resolver/extension/index.js +0 -25
  226. package/dist/resolver/extension/index.js.map +0 -1
  227. package/dist/resolver/extension/module.d.ts +0 -5
  228. package/dist/resolver/extension/module.d.ts.map +0 -1
  229. package/dist/resolver/extension/module.js +0 -26
  230. package/dist/resolver/extension/module.js.map +0 -1
  231. package/dist/resolver/extension/type.d.ts +0 -8
  232. package/dist/resolver/extension/type.d.ts.map +0 -1
  233. package/dist/resolver/extension/type.js +0 -9
  234. package/dist/resolver/extension/type.js.map +0 -1
  235. package/dist/resolver/index.d.ts +0 -6
  236. package/dist/resolver/index.d.ts.map +0 -1
  237. package/dist/resolver/index.js +0 -28
  238. package/dist/resolver/index.js.map +0 -1
  239. package/dist/resolver/module.d.ts +0 -56
  240. package/dist/resolver/module.d.ts.map +0 -1
  241. package/dist/resolver/module.js +0 -1023
  242. package/dist/resolver/module.js.map +0 -1
  243. package/dist/resolver/sub/base.d.ts +0 -7
  244. package/dist/resolver/sub/base.d.ts.map +0 -1
  245. package/dist/resolver/sub/base.js +0 -50
  246. package/dist/resolver/sub/base.js.map +0 -1
  247. package/dist/resolver/sub/index.d.ts +0 -4
  248. package/dist/resolver/sub/index.d.ts.map +0 -1
  249. package/dist/resolver/sub/index.js +0 -26
  250. package/dist/resolver/sub/index.js.map +0 -1
  251. package/dist/resolver/sub/primitive.d.ts +0 -11
  252. package/dist/resolver/sub/primitive.d.ts.map +0 -1
  253. package/dist/resolver/sub/primitive.js +0 -124
  254. package/dist/resolver/sub/primitive.js.map +0 -1
  255. package/dist/resolver/sub/reference.d.ts +0 -15
  256. package/dist/resolver/sub/reference.d.ts.map +0 -1
  257. package/dist/resolver/sub/reference.js +0 -141
  258. package/dist/resolver/sub/reference.js.map +0 -1
  259. package/dist/resolver/type.d.ts +0 -143
  260. package/dist/resolver/type.d.ts.map +0 -1
  261. package/dist/resolver/type.js +0 -135
  262. package/dist/resolver/type.js.map +0 -1
  263. package/dist/resolver/utils.d.ts +0 -4
  264. package/dist/resolver/utils.d.ts.map +0 -1
  265. package/dist/resolver/utils.js +0 -37
  266. package/dist/resolver/utils.js.map +0 -1
  267. package/dist/type.d.ts +0 -2
  268. package/dist/type.d.ts.map +0 -1
  269. package/dist/type.js +0 -9
  270. package/dist/type.js.map +0 -1
  271. package/dist/utils/array.d.ts +0 -2
  272. package/dist/utils/array.d.ts.map +0 -1
  273. package/dist/utils/array.js +0 -21
  274. package/dist/utils/array.js.map +0 -1
  275. package/dist/utils/index.d.ts +0 -10
  276. package/dist/utils/index.d.ts.map +0 -1
  277. package/dist/utils/index.js +0 -32
  278. package/dist/utils/index.js.map +0 -1
  279. package/dist/utils/initializer.d.ts +0 -5
  280. package/dist/utils/initializer.d.ts.map +0 -1
  281. package/dist/utils/initializer.js +0 -141
  282. package/dist/utils/initializer.js.map +0 -1
  283. package/dist/utils/js-doc/constants.d.ts +0 -19
  284. package/dist/utils/js-doc/constants.d.ts.map +0 -1
  285. package/dist/utils/js-doc/constants.js +0 -30
  286. package/dist/utils/js-doc/constants.js.map +0 -1
  287. package/dist/utils/js-doc/index.d.ts +0 -4
  288. package/dist/utils/js-doc/index.d.ts.map +0 -1
  289. package/dist/utils/js-doc/index.js +0 -26
  290. package/dist/utils/js-doc/index.js.map +0 -1
  291. package/dist/utils/js-doc/module.d.ts +0 -9
  292. package/dist/utils/js-doc/module.d.ts.map +0 -1
  293. package/dist/utils/js-doc/module.js +0 -97
  294. package/dist/utils/js-doc/module.js.map +0 -1
  295. package/dist/utils/js-doc/utils.d.ts +0 -3
  296. package/dist/utils/js-doc/utils.d.ts.map +0 -1
  297. package/dist/utils/js-doc/utils.js +0 -28
  298. package/dist/utils/js-doc/utils.js.map +0 -1
  299. package/dist/utils/node/index.d.ts +0 -3
  300. package/dist/utils/node/index.d.ts.map +0 -1
  301. package/dist/utils/node/index.js +0 -25
  302. package/dist/utils/node/index.js.map +0 -1
  303. package/dist/utils/node/module.d.ts +0 -10
  304. package/dist/utils/node/module.d.ts.map +0 -1
  305. package/dist/utils/node/module.js +0 -51
  306. package/dist/utils/node/module.js.map +0 -1
  307. package/dist/utils/node/type.d.ts +0 -6
  308. package/dist/utils/node/type.d.ts.map +0 -1
  309. package/dist/utils/node/type.js +0 -9
  310. package/dist/utils/node/type.js.map +0 -1
  311. package/dist/utils/object.d.ts +0 -2
  312. package/dist/utils/object.d.ts.map +0 -1
  313. package/dist/utils/object.js +0 -14
  314. package/dist/utils/object.js.map +0 -1
  315. package/dist/utils/path-normalize.d.ts +0 -2
  316. package/dist/utils/path-normalize.d.ts.map +0 -1
  317. package/dist/utils/path-normalize.js +0 -16
  318. package/dist/utils/path-normalize.js.map +0 -1
  319. package/dist/utils/source-files.d.ts +0 -3
  320. package/dist/utils/source-files.d.ts.map +0 -1
  321. package/dist/utils/source-files.js +0 -31
  322. package/dist/utils/source-files.js.map +0 -1
  323. package/dist/utils/tsconfig/index.d.ts +0 -3
  324. package/dist/utils/tsconfig/index.d.ts.map +0 -1
  325. package/dist/utils/tsconfig/index.js +0 -25
  326. package/dist/utils/tsconfig/index.js.map +0 -1
  327. package/dist/utils/tsconfig/module.d.ts +0 -4
  328. package/dist/utils/tsconfig/module.d.ts.map +0 -1
  329. package/dist/utils/tsconfig/module.js +0 -53
  330. package/dist/utils/tsconfig/module.js.map +0 -1
  331. package/dist/utils/tsconfig/type.d.ts +0 -11
  332. package/dist/utils/tsconfig/type.d.ts.map +0 -1
  333. package/dist/utils/tsconfig/type.js +0 -9
  334. package/dist/utils/tsconfig/type.js.map +0 -1
  335. package/dist/utils/validator/constants.d.ts +0 -13
  336. package/dist/utils/validator/constants.d.ts.map +0 -1
  337. package/dist/utils/validator/constants.js +0 -23
  338. package/dist/utils/validator/constants.js.map +0 -1
  339. package/dist/utils/validator/index.d.ts +0 -4
  340. package/dist/utils/validator/index.d.ts.map +0 -1
  341. package/dist/utils/validator/index.js +0 -26
  342. package/dist/utils/validator/index.js.map +0 -1
  343. package/dist/utils/validator/module.d.ts +0 -4
  344. package/dist/utils/validator/module.d.ts.map +0 -1
  345. package/dist/utils/validator/module.js +0 -141
  346. package/dist/utils/validator/module.js.map +0 -1
  347. package/dist/utils/validator/type.d.ts +0 -6
  348. package/dist/utils/validator/type.d.ts.map +0 -1
  349. package/dist/utils/validator/type.js +0 -9
  350. package/dist/utils/validator/type.js.map +0 -1
package/dist/index.mjs ADDED
@@ -0,0 +1,3310 @@
1
+ import path, { normalize } from "node:path";
2
+ import { BaseError, isBaseError } from "@ebec/core";
3
+ import * as ts from "typescript";
4
+ import { NodeBuilderFlags, NodeFlags, SymbolFlags, SyntaxKind, canHaveDecorators, canHaveModifiers, convertCompilerOptionsFromJson, createProgram, displayPartsToString, forEachChild, getDecorators, getModifiers, isCallExpression, isClassDeclaration, isEnumDeclaration, isEnumMember, isJSDocParameterTag, isMethodDeclaration, isModuleBlock, isModuleDeclaration, isNumericLiteral, isStringLiteral } from "typescript";
5
+ import { buildFilePath, hasOwnProperty as hasOwnProperty$1, isObject, load, locateMany } from "locter";
6
+ import { Container } from "validup";
7
+ import { createValidator } from "@validup/adapter-zod";
8
+ import { z } from "zod";
9
+ import process from "node:process";
10
+ import { parse, stringify } from "flatted";
11
+ import crypto from "node:crypto";
12
+ import fs from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { minimatch } from "minimatch";
15
+ //#region src/core/resolver/constants.ts
16
+ let TypeName = /* @__PURE__ */ function(TypeName) {
17
+ TypeName["STRING"] = "string";
18
+ TypeName["BOOLEAN"] = "boolean";
19
+ TypeName["BIGINT"] = "bigint";
20
+ TypeName["DOUBLE"] = "double";
21
+ TypeName["FLOAT"] = "float";
22
+ TypeName["FILE"] = "file";
23
+ TypeName["INTEGER"] = "integer";
24
+ TypeName["LONG"] = "long";
25
+ TypeName["ENUM"] = "enum";
26
+ TypeName["ARRAY"] = "array";
27
+ TypeName["DATETIME"] = "datetime";
28
+ TypeName["DATE"] = "date";
29
+ TypeName["BINARY"] = "binary";
30
+ TypeName["BUFFER"] = "buffer";
31
+ TypeName["BYTE"] = "byte";
32
+ TypeName["VOID"] = "void";
33
+ TypeName["OBJECT"] = "object";
34
+ TypeName["ANY"] = "any";
35
+ TypeName["UNDEFINED"] = "undefined";
36
+ TypeName["NEVER"] = "never";
37
+ TypeName["REF_ENUM"] = "refEnum";
38
+ TypeName["REF_OBJECT"] = "refObject";
39
+ TypeName["REF_ALIAS"] = "refAlias";
40
+ TypeName["NESTED_OBJECT_LITERAL"] = "nestedObjectLiteral";
41
+ TypeName["UNION"] = "union";
42
+ TypeName["INTERSECTION"] = "intersection";
43
+ TypeName["TUPLE"] = "tuple";
44
+ return TypeName;
45
+ }({});
46
+ let UtilityTypeName = /* @__PURE__ */ function(UtilityTypeName) {
47
+ UtilityTypeName["NON_NULLABLE"] = "NonNullable";
48
+ UtilityTypeName["OMIT"] = "Omit";
49
+ UtilityTypeName["PARTIAL"] = "Partial";
50
+ UtilityTypeName["READONLY"] = "Readonly";
51
+ UtilityTypeName["RECORD"] = "Record";
52
+ UtilityTypeName["REQUIRED"] = "Required";
53
+ UtilityTypeName["PICK"] = "Pick";
54
+ UtilityTypeName["EXTRACT"] = "Extract";
55
+ UtilityTypeName["EXCLUDE"] = "Exclude";
56
+ UtilityTypeName["RETURN_TYPE"] = "ReturnType";
57
+ UtilityTypeName["PARAMETERS"] = "Parameters";
58
+ UtilityTypeName["AWAITED"] = "Awaited";
59
+ UtilityTypeName["INSTANCE_TYPE"] = "InstanceType";
60
+ UtilityTypeName["CONSTRUCTOR_PARAMETERS"] = "ConstructorParameters";
61
+ return UtilityTypeName;
62
+ }({});
63
+ //#endregion
64
+ //#region src/core/resolver/type-guards.ts
65
+ function isAnyType(param) {
66
+ return param.typeName === "any";
67
+ }
68
+ function isUndefinedType(param) {
69
+ return param.typeName === "undefined";
70
+ }
71
+ function isStringType(param) {
72
+ return param.typeName === "string";
73
+ }
74
+ function isBooleanType(param) {
75
+ return param.typeName === "boolean";
76
+ }
77
+ function isBigintType(param) {
78
+ return param.typeName === "bigint";
79
+ }
80
+ function isDoubleType(param) {
81
+ return param.typeName === "double";
82
+ }
83
+ function isFloatType(param) {
84
+ return param.typeName === "float";
85
+ }
86
+ function isIntegerType(param) {
87
+ return param.typeName === "integer";
88
+ }
89
+ function isLongType(param) {
90
+ return param.typeName === "long";
91
+ }
92
+ function isVoidType(param) {
93
+ return typeof param === "undefined" || param.typeName === "void";
94
+ }
95
+ function isNeverType(param) {
96
+ return param.typeName === "never";
97
+ }
98
+ function isDateType(param) {
99
+ return param.typeName === "date";
100
+ }
101
+ function isFileType(param) {
102
+ return param.typeName === "file";
103
+ }
104
+ function isDateTimeType(param) {
105
+ return param.typeName === "datetime";
106
+ }
107
+ function isBinaryType(param) {
108
+ return param.typeName === "binary";
109
+ }
110
+ function isBufferType(param) {
111
+ return param.typeName === "buffer";
112
+ }
113
+ function isByteType(param) {
114
+ return param.typeName === "byte";
115
+ }
116
+ function isObjectType(param) {
117
+ return param.typeName === "object";
118
+ }
119
+ function isEnumType(param) {
120
+ return param.typeName === "enum";
121
+ }
122
+ function isArrayType(param) {
123
+ return param.typeName === "array";
124
+ }
125
+ function isNestedObjectLiteralType(param) {
126
+ return param.typeName === "nestedObjectLiteral";
127
+ }
128
+ function isIntersectionType(param) {
129
+ return param.typeName === "intersection";
130
+ }
131
+ function isUnionType(param) {
132
+ return param.typeName === "union";
133
+ }
134
+ function isTupleType(param) {
135
+ return param.typeName === "tuple";
136
+ }
137
+ function isRefEnumType(param) {
138
+ return param.typeName === "refEnum";
139
+ }
140
+ function isRefObjectType(param) {
141
+ return param.typeName === "refObject";
142
+ }
143
+ function isRefAliasType(param) {
144
+ return param.typeName === "refAlias";
145
+ }
146
+ function isReferenceType(param) {
147
+ return param.typeName === "refAlias" || param.typeName === "refEnum" || param.typeName === "refObject";
148
+ }
149
+ function isPrimitiveType(type) {
150
+ return isAnyType(type) || isBinaryType(type) || isBooleanType(type) || isBufferType(type) || isByteType(type) || isDateType(type) || isDateTimeType(type) || isBigintType(type) || isDoubleType(type) || isFloatType(type) || isFileType(type) || isIntegerType(type) || isLongType(type) || isObjectType(type) || isStringType(type) || isUndefinedType(type);
151
+ }
152
+ //#endregion
153
+ //#region src/core/error/base.ts
154
+ var MetadataError = class extends BaseError {};
155
+ //#endregion
156
+ //#region src/core/resolver/error.ts
157
+ var ResolverError = class extends MetadataError {
158
+ file;
159
+ line;
160
+ constructor(message, node, options) {
161
+ const opts = typeof options === "boolean" ? { onlyCurrent: options } : options;
162
+ const onlyCurrent = opts?.onlyCurrent ?? false;
163
+ const parts = [message];
164
+ let file;
165
+ let line;
166
+ if (node) {
167
+ const location = prettyLocationOfNode(node);
168
+ if (location) {
169
+ parts.push(location.text);
170
+ file = location.file;
171
+ line = location.line;
172
+ }
173
+ parts.push(prettyTroubleCause(node, onlyCurrent));
174
+ }
175
+ super({
176
+ message: parts.join("\n"),
177
+ cause: opts?.cause
178
+ });
179
+ this.file = file;
180
+ this.line = line;
181
+ }
182
+ };
183
+ function isResolverError(input) {
184
+ if (!isBaseError(input)) return false;
185
+ return "file" in input && "line" in input;
186
+ }
187
+ function prettyLocationOfNode(node) {
188
+ try {
189
+ const sourceFile = node.getSourceFile();
190
+ if (!sourceFile) return void 0;
191
+ const token = node.getFirstToken() || node.parent?.getFirstToken();
192
+ const start = token ? sourceFile.getLineAndCharacterOfPosition(token.getStart()).line + 1 : void 0;
193
+ const end = token ? sourceFile.getLineAndCharacterOfPosition(token.getEnd()).line + 1 : void 0;
194
+ return {
195
+ text: `At: ${normalize(sourceFile.fileName)}${start ? `:${start}` : ""}${end ? `:${end}` : ""}.`,
196
+ file: sourceFile.fileName,
197
+ line: start
198
+ };
199
+ } catch {
200
+ return;
201
+ }
202
+ }
203
+ function prettyTroubleCause(node, onlyCurrent = false) {
204
+ try {
205
+ let name;
206
+ if (onlyCurrent || !node.parent) name = node.pos !== -1 ? node.getText() : node.name.text;
207
+ else name = node.parent.pos !== -1 ? node.parent.getText() : node.parent.name.text;
208
+ return `This was caused by '${name}'`;
209
+ } catch {
210
+ return "This was caused by an unknown node";
211
+ }
212
+ }
213
+ //#endregion
214
+ //#region src/core/method/constants.ts
215
+ const MethodName = {
216
+ ALL: "ALL",
217
+ GET: "GET",
218
+ POST: "POST",
219
+ PUT: "PUT",
220
+ DELETE: "DELETE",
221
+ PATCH: "PATCH",
222
+ OPTIONS: "OPTIONS",
223
+ HEAD: "HEAD"
224
+ };
225
+ //#endregion
226
+ //#region src/core/parameter/constants.ts
227
+ const ParameterSource = {
228
+ BODY: "body",
229
+ BODY_PROP: "bodyProp",
230
+ CONTEXT: "context",
231
+ COOKIE: "cookie",
232
+ HEADER: "header",
233
+ FORM_DATA: "formData",
234
+ QUERY: "query",
235
+ QUERY_PROP: "queryProp",
236
+ PATH: "path"
237
+ };
238
+ const CollectionFormat = {
239
+ CSV: "csv",
240
+ SSV: "ssv",
241
+ TSV: "tsv",
242
+ PIPES: "pipes",
243
+ MULTI: "multi"
244
+ };
245
+ const ParameterErrorCode = {
246
+ TYPE_UNSUPPORTED: "PARAMETER_TYPE_UNSUPPORTED",
247
+ METHOD_UNSUPPORTED: "PARAMETER_METHOD_UNSUPPORTED",
248
+ PATH_MISMATCH: "PARAMETER_PATH_MISMATCH",
249
+ SCOPE_REQUIRED: "PARAMETER_SCOPE_REQUIRED",
250
+ INVALID_EXAMPLE: "PARAMETER_INVALID_EXAMPLE"
251
+ };
252
+ //#endregion
253
+ //#region src/core/parameter/error.ts
254
+ var ParameterError = class ParameterError extends MetadataError {
255
+ static typeUnsupported(context) {
256
+ const location = context.node ? ParameterError.getCurrentLocation(context.node) : void 0;
257
+ return new ParameterError({
258
+ message: `@${context.decoratorName}('${context.propertyName}') does not support '${context.type.typeName}' type${location ? ` at ${location}` : ""}.`,
259
+ code: ParameterErrorCode.TYPE_UNSUPPORTED
260
+ });
261
+ }
262
+ static methodUnsupported(context) {
263
+ const location = context.node ? ParameterError.getCurrentLocation(context.node) : void 0;
264
+ return new ParameterError({
265
+ message: `@${context.decoratorName}('${context.propertyName}') does not support method '${context.method}'${location ? ` at ${location}` : ""}.`,
266
+ code: ParameterErrorCode.METHOD_UNSUPPORTED
267
+ });
268
+ }
269
+ static invalidPathMatch(context) {
270
+ const location = context.node ? ParameterError.getCurrentLocation(context.node) : void 0;
271
+ return new ParameterError({
272
+ message: `@${context.decoratorName}('${context.propertyName}') does not exist in path '${context.path}'${location ? ` at ${location}` : ""}.`,
273
+ code: ParameterErrorCode.PATH_MISMATCH
274
+ });
275
+ }
276
+ static scopeRequired(context) {
277
+ const location = context.node ? ParameterError.getCurrentLocation(context.node) : void 0;
278
+ return new ParameterError({
279
+ message: `@${context.decoratorName}() requires a scope argument${location ? ` at ${location}` : ""}.`,
280
+ code: ParameterErrorCode.SCOPE_REQUIRED
281
+ });
282
+ }
283
+ static invalidExampleSchema() {
284
+ return new ParameterError({
285
+ message: "The @example JSDoc tag contains invalid JSON.",
286
+ code: ParameterErrorCode.INVALID_EXAMPLE
287
+ });
288
+ }
289
+ static getCurrentLocation(node) {
290
+ const parts = [];
291
+ if (isMethodDeclaration(node.parent)) {
292
+ parts.push(node.parent.name.getText());
293
+ if (isClassDeclaration(node.parent.parent)) parts.unshift(node.parent.parent.name.text);
294
+ }
295
+ return parts.join(".");
296
+ }
297
+ };
298
+ //#endregion
299
+ //#region src/core/generator/error.ts
300
+ var GeneratorError = class extends MetadataError {};
301
+ function isGeneratorError(input) {
302
+ if (!isBaseError(input)) return false;
303
+ return typeof input.code === "string";
304
+ }
305
+ //#endregion
306
+ //#region src/core/generator/constants.ts
307
+ const GeneratorErrorCode = {
308
+ CONTROLLER_NO_SOURCE_FILE: "GENERATOR_CONTROLLER_NO_SOURCE_FILE",
309
+ CONTROLLER_NO_NAME: "GENERATOR_CONTROLLER_NO_NAME",
310
+ PARAMETER_GENERATION_FAILED: "GENERATOR_PARAMETER_GENERATION_FAILED",
311
+ BODY_PARAMETER_DUPLICATE: "GENERATOR_BODY_PARAMETER_DUPLICATE",
312
+ BODY_FORM_CONFLICT: "GENERATOR_BODY_FORM_CONFLICT"
313
+ };
314
+ //#endregion
315
+ //#region src/core/validator/error.ts
316
+ var ValidatorError = class extends MetadataError {};
317
+ //#endregion
318
+ //#region src/core/validator/constants.ts
319
+ let ValidatorName = /* @__PURE__ */ function(ValidatorName) {
320
+ ValidatorName["UNIQUE_ITEMS"] = "uniqueItems";
321
+ ValidatorName["MINIMUM"] = "minimum";
322
+ ValidatorName["MAXIMUM"] = "maximum";
323
+ ValidatorName["MIN_ITEMS"] = "minItems";
324
+ ValidatorName["MAX_ITEMS"] = "maxItems";
325
+ ValidatorName["MIN_LENGTH"] = "minLength";
326
+ ValidatorName["MAX_LENGTH"] = "maxLength";
327
+ ValidatorName["MIN_DATE"] = "minDate";
328
+ ValidatorName["MAX_DATE"] = "maxDate";
329
+ ValidatorName["PATTERN"] = "pattern";
330
+ return ValidatorName;
331
+ }({});
332
+ const ValidatorErrorCode = {
333
+ EXPECTED_NUMBER: "VALIDATOR_EXPECTED_NUMBER",
334
+ EXPECTED_DATE: "VALIDATOR_EXPECTED_DATE",
335
+ EXPECTED_STRING: "VALIDATOR_EXPECTED_STRING"
336
+ };
337
+ //#endregion
338
+ //#region src/core/error/config.ts
339
+ var ConfigError = class extends MetadataError {};
340
+ //#endregion
341
+ //#region src/core/error/config-codes.ts
342
+ const ConfigErrorCode = {
343
+ TSCONFIG_MALFORMED: "CONFIG_TSCONFIG_MALFORMED",
344
+ PRESET_NOT_FOUND: "CONFIG_PRESET_NOT_FOUND",
345
+ PRESET_MISSING: "CONFIG_PRESET_MISSING"
346
+ };
347
+ //#endregion
348
+ //#region src/adapters/decorator/constants.ts
349
+ const ParamKind = {
350
+ Body: "body",
351
+ BodyProp: "bodyProp",
352
+ Context: "context",
353
+ Cookie: "cookie",
354
+ Header: "header",
355
+ FormData: "formData",
356
+ Query: "query",
357
+ QueryProp: "queryProp",
358
+ Path: "path"
359
+ };
360
+ const CollectionKind = {
361
+ Csv: "csv",
362
+ Ssv: "ssv",
363
+ Tsv: "tsv",
364
+ Pipes: "pipes",
365
+ Multi: "multi"
366
+ };
367
+ const DecoratorTargetKind = {
368
+ Class: "class",
369
+ Method: "method",
370
+ Parameter: "parameter",
371
+ Property: "property"
372
+ };
373
+ const DecoratorArgumentKindName = {
374
+ Literal: "literal",
375
+ Object: "object",
376
+ Array: "array",
377
+ Identifier: "identifier",
378
+ Unresolvable: "unresolvable"
379
+ };
380
+ const MarkerName = {
381
+ Hidden: "hidden",
382
+ Deprecated: "deprecated",
383
+ Extension: "extension"
384
+ };
385
+ const NumericKind = {
386
+ Int: "int",
387
+ Long: "long",
388
+ Float: "float",
389
+ Double: "double"
390
+ };
391
+ //#endregion
392
+ //#region src/adapters/decorator/utils.ts
393
+ function matches(match, source) {
394
+ if (match.name !== source.name) return false;
395
+ if (match.on && match.on !== source.target) return false;
396
+ return true;
397
+ }
398
+ function matchesJsDoc(match, source) {
399
+ if (match.tag !== source.tag) return false;
400
+ if (match.on && match.on !== source.target) return false;
401
+ return true;
402
+ }
403
+ function newControllerDraft(input) {
404
+ return {
405
+ name: input.name,
406
+ location: input.location,
407
+ hidden: false,
408
+ consumes: [],
409
+ produces: [],
410
+ tags: [],
411
+ responses: [],
412
+ security: [],
413
+ extensions: []
414
+ };
415
+ }
416
+ function newMethodDraft(input) {
417
+ return {
418
+ name: input.name,
419
+ path: "",
420
+ description: "",
421
+ hidden: false,
422
+ consumes: [],
423
+ produces: [],
424
+ tags: [],
425
+ responses: [],
426
+ security: [],
427
+ extensions: [],
428
+ parameters: [],
429
+ defaultResponseExamples: []
430
+ };
431
+ }
432
+ function newParameterDraft(input) {
433
+ return {
434
+ parameterName: input.parameterName,
435
+ name: input.parameterName,
436
+ description: "",
437
+ required: true,
438
+ examples: [],
439
+ exampleLabels: [],
440
+ extensions: [],
441
+ validators: {}
442
+ };
443
+ }
444
+ function createRegistry() {
445
+ return {
446
+ controllers: [],
447
+ methods: [],
448
+ parameters: [],
449
+ controllerJsDoc: [],
450
+ methodJsDoc: [],
451
+ parameterJsDoc: []
452
+ };
453
+ }
454
+ function generatePresetLookupPaths(input) {
455
+ if (path.isAbsolute(input) || input.startsWith("./") || input.startsWith("../")) return [input];
456
+ if (input.startsWith("module:")) return [input.substring(7)];
457
+ if (!input.startsWith("@")) return [input, `@trapi/${input}`];
458
+ return [input];
459
+ }
460
+ /**
461
+ * Collect the unique decorator names of every handler whose `marker` matches
462
+ * the given predicate. Lets the type resolver discover preset-renamed
463
+ * decorators without hard-coding canonical names.
464
+ */
465
+ function namesForMarker(registry, predicate) {
466
+ const names = /* @__PURE__ */ new Set();
467
+ const all = [
468
+ ...registry.controllers,
469
+ ...registry.methods,
470
+ ...registry.parameters
471
+ ];
472
+ for (const handler of all) if (handler.marker !== void 0 && predicate(handler.marker)) names.add(handler.match.name);
473
+ return names;
474
+ }
475
+ /**
476
+ * Collect the unique JSDoc tag names of every JSDoc handler whose `marker`
477
+ * matches the given predicate. JSDoc analogue of `namesForMarker`.
478
+ */
479
+ function tagsForMarker(registry, predicate) {
480
+ const tags = /* @__PURE__ */ new Set();
481
+ const all = [
482
+ ...registry.controllerJsDoc,
483
+ ...registry.methodJsDoc,
484
+ ...registry.parameterJsDoc
485
+ ];
486
+ for (const handler of all) if (handler.marker !== void 0 && predicate(handler.marker)) tags.add(handler.match.tag);
487
+ return tags;
488
+ }
489
+ function isHiddenMarker(marker) {
490
+ return marker === "hidden";
491
+ }
492
+ function isDeprecatedMarker(marker) {
493
+ return marker === "deprecated";
494
+ }
495
+ function isExtensionMarker(marker) {
496
+ return marker === "extension";
497
+ }
498
+ function numericMarkerKind(marker) {
499
+ if (typeof marker === "object" && marker !== null && "numeric" in marker) return marker.numeric;
500
+ }
501
+ const controller = (handler) => handler;
502
+ const method = (handler) => handler;
503
+ const parameter = (handler) => handler;
504
+ const controllerJsDoc = (handler) => handler;
505
+ const methodJsDoc = (handler) => handler;
506
+ const parameterJsDoc = (handler) => handler;
507
+ function isLiteralLike(kind) {
508
+ return kind === "literal" || kind === "identifier";
509
+ }
510
+ function readArray(draft, key) {
511
+ const record = draft;
512
+ const existing = record[key];
513
+ if (Array.isArray(existing)) return existing;
514
+ if (typeof existing !== "undefined") throw new TypeError(`append(): cannot append to draft key "${key}": existing value is not an array (got ${typeof existing}).`);
515
+ const created = [];
516
+ record[key] = created;
517
+ return created;
518
+ }
519
+ function into(key) {
520
+ return {
521
+ positional(index) {
522
+ return (ctx, draft) => {
523
+ const arg = ctx.argument(index);
524
+ if (arg && isLiteralLike(arg.kind)) draft[key] = arg.raw;
525
+ };
526
+ },
527
+ typeArgument(index = 0) {
528
+ return (ctx, draft) => {
529
+ const ta = ctx.typeArgument(index);
530
+ if (ta) draft[key] = ta.resolve();
531
+ };
532
+ }
533
+ };
534
+ }
535
+ function append(key) {
536
+ return {
537
+ positional(index) {
538
+ return (ctx, draft) => {
539
+ const arg = ctx.argument(index);
540
+ if (!arg) return;
541
+ const target = readArray(draft, key);
542
+ if (arg.kind === "array" && Array.isArray(arg.raw)) target.push(...arg.raw);
543
+ else if (isLiteralLike(arg.kind)) target.push(arg.raw);
544
+ };
545
+ },
546
+ positionalAll() {
547
+ return (ctx, draft) => {
548
+ const target = readArray(draft, key);
549
+ for (const arg of ctx.arguments()) if (arg.kind === "array" && Array.isArray(arg.raw)) target.push(...arg.raw);
550
+ else if (isLiteralLike(arg.kind)) target.push(arg.raw);
551
+ };
552
+ }
553
+ };
554
+ }
555
+ function flag(key, value = true) {
556
+ return (_ctx, draft) => {
557
+ draft[key] = value;
558
+ };
559
+ }
560
+ //#endregion
561
+ //#region src/adapters/decorator/validation/module.ts
562
+ const decoratorTargetSchema = z.enum([
563
+ "class",
564
+ "method",
565
+ "parameter",
566
+ "property"
567
+ ]);
568
+ const replacesPolicySchema = z.union([z.literal(true), z.string().min(1)]);
569
+ function matchSchemaForKind(allowedOn) {
570
+ return z.object({
571
+ name: z.string().min(1),
572
+ on: decoratorTargetSchema.optional()
573
+ }).refine((m) => m.on === void 0 || m.on === allowedOn, {
574
+ message: `match.on is incompatible with the handler array it lives in — expected '${allowedOn}' or omit 'on' entirely.`,
575
+ path: ["on"]
576
+ });
577
+ }
578
+ function jsDocMatchSchemaForKind(allowedOn) {
579
+ return z.object({
580
+ tag: z.string().min(1),
581
+ on: decoratorTargetSchema.optional()
582
+ }).refine((m) => m.on === void 0 || m.on === allowedOn, {
583
+ message: `match.on is incompatible with the JSDoc handler array it lives in — expected '${allowedOn}' or omit 'on' entirely.`,
584
+ path: ["on"]
585
+ });
586
+ }
587
+ const matchSchema = z.object({
588
+ name: z.string().min(1),
589
+ on: decoratorTargetSchema.optional()
590
+ });
591
+ const jsDocMatchSchema = z.object({
592
+ tag: z.string().min(1),
593
+ on: decoratorTargetSchema.optional()
594
+ });
595
+ const numericMarkerSchema = z.object({ numeric: z.enum([
596
+ "int",
597
+ "long",
598
+ "float",
599
+ "double"
600
+ ]) });
601
+ const resolverMarkerSchema = z.union([
602
+ z.literal("hidden"),
603
+ z.literal("deprecated"),
604
+ z.literal("extension"),
605
+ numericMarkerSchema
606
+ ]);
607
+ const handlerBaseShape = {
608
+ replaces: replacesPolicySchema.optional(),
609
+ marker: resolverMarkerSchema.optional(),
610
+ apply: z.custom((value) => typeof value === "function", { message: "apply must be a function" })
611
+ };
612
+ const controllerHandlerSchema = z.object({
613
+ match: matchSchemaForKind("class"),
614
+ ...handlerBaseShape
615
+ });
616
+ const methodHandlerSchema = z.object({
617
+ match: matchSchemaForKind("method"),
618
+ ...handlerBaseShape
619
+ });
620
+ const parameterHandlerSchema = z.object({
621
+ match: matchSchemaForKind("parameter"),
622
+ ...handlerBaseShape
623
+ });
624
+ const controllerJsDocHandlerSchema = z.object({
625
+ match: jsDocMatchSchemaForKind("class"),
626
+ ...handlerBaseShape
627
+ });
628
+ const methodJsDocHandlerSchema = z.object({
629
+ match: jsDocMatchSchemaForKind("method"),
630
+ ...handlerBaseShape
631
+ });
632
+ const parameterJsDocHandlerSchema = z.object({
633
+ match: jsDocMatchSchemaForKind("parameter"),
634
+ ...handlerBaseShape
635
+ });
636
+ const presetSchema = z.object({
637
+ name: z.string().min(1),
638
+ extends: z.array(z.string().min(1)).optional(),
639
+ controllers: z.array(controllerHandlerSchema).optional(),
640
+ methods: z.array(methodHandlerSchema).optional(),
641
+ parameters: z.array(parameterHandlerSchema).optional(),
642
+ controllerJsDoc: z.array(controllerJsDocHandlerSchema).optional(),
643
+ methodJsDoc: z.array(methodJsDocHandlerSchema).optional(),
644
+ parameterJsDoc: z.array(parameterJsDocHandlerSchema).optional()
645
+ });
646
+ function createPresetContainer() {
647
+ const container = new Container();
648
+ container.mount("name", createValidator(presetSchema.shape.name));
649
+ container.mount("extends", { optional: true }, createValidator(presetSchema.shape.extends));
650
+ container.mount("controllers", { optional: true }, createValidator(presetSchema.shape.controllers));
651
+ container.mount("methods", { optional: true }, createValidator(presetSchema.shape.methods));
652
+ container.mount("parameters", { optional: true }, createValidator(presetSchema.shape.parameters));
653
+ container.mount("controllerJsDoc", { optional: true }, createValidator(presetSchema.shape.controllerJsDoc));
654
+ container.mount("methodJsDoc", { optional: true }, createValidator(presetSchema.shape.methodJsDoc));
655
+ container.mount("parameterJsDoc", { optional: true }, createValidator(presetSchema.shape.parameterJsDoc));
656
+ return container;
657
+ }
658
+ const sharedContainer = createPresetContainer();
659
+ async function validatePreset(input) {
660
+ if (input === null || typeof input !== "object" || Array.isArray(input)) throw new TypeError("preset input must be an object");
661
+ return sharedContainer.run(input);
662
+ }
663
+ //#endregion
664
+ //#region src/adapters/decorator/module.ts
665
+ const decoratorKinds = [
666
+ "controllers",
667
+ "methods",
668
+ "parameters"
669
+ ];
670
+ const jsDocKinds = [
671
+ "controllerJsDoc",
672
+ "methodJsDoc",
673
+ "parameterJsDoc"
674
+ ];
675
+ function emptyTaggedRegistry() {
676
+ return {
677
+ controllers: [],
678
+ methods: [],
679
+ parameters: [],
680
+ controllerJsDoc: [],
681
+ methodJsDoc: [],
682
+ parameterJsDoc: []
683
+ };
684
+ }
685
+ async function loadRegistry(preset, options) {
686
+ return stripOrigins(await loadTaggedRegistry(preset, options, /* @__PURE__ */ new Set()));
687
+ }
688
+ async function loadTaggedRegistry(preset, options, visited) {
689
+ const validated = await validatePreset(preset);
690
+ if (visited.has(validated.name)) throw new MetadataError({ message: `Preset cycle detected: ${[...visited, validated.name].join(" -> ")}` });
691
+ const nextVisited = new Set(visited);
692
+ nextVisited.add(validated.name);
693
+ const merged = emptyTaggedRegistry();
694
+ for (const extendsName of validated.extends ?? []) appendTagged(merged, await loadTaggedRegistry(await options.resolver(extendsName), options, nextVisited));
695
+ applyOwnHandlers(merged, validated, !!options.strict);
696
+ return merged;
697
+ }
698
+ function applyOwnHandlers(merged, preset, strict) {
699
+ for (const kind of decoratorKinds) {
700
+ const handlers = preset[kind] ?? [];
701
+ for (const handler of handlers) {
702
+ if (handler.replaces) applyReplacesDecorator(merged, kind, handler, preset.name, strict);
703
+ merged[kind].push({
704
+ origin: preset.name,
705
+ handler
706
+ });
707
+ }
708
+ }
709
+ for (const kind of jsDocKinds) {
710
+ const handlers = preset[kind] ?? [];
711
+ for (const handler of handlers) {
712
+ if (handler.replaces) applyReplacesJsDoc(merged, kind, handler, preset.name, strict);
713
+ merged[kind].push({
714
+ origin: preset.name,
715
+ handler
716
+ });
717
+ }
718
+ }
719
+ }
720
+ function applyReplacesDecorator(merged, kind, handler, presetName, strict) {
721
+ const list = merged[kind];
722
+ const remaining = [];
723
+ let removed = 0;
724
+ for (const entry of list) {
725
+ if (entry.origin !== presetName && handlerMatches(handler, entry.handler.match.name, entry.handler.match.on) && originMatches(handler.replaces, entry.origin)) {
726
+ removed += 1;
727
+ continue;
728
+ }
729
+ remaining.push(entry);
730
+ }
731
+ if (removed === 0 && strict) throw new MetadataError({ message: `Preset '${presetName}': handler with replaces=${describeReplaces(handler.replaces)} on '${handler.match.name}' did not match any parent handler` });
732
+ merged[kind] = remaining;
733
+ }
734
+ function applyReplacesJsDoc(merged, kind, handler, presetName, strict) {
735
+ const list = merged[kind];
736
+ const remaining = [];
737
+ let removed = 0;
738
+ for (const entry of list) {
739
+ if (entry.origin !== presetName && handlerMatches(handler, entry.handler.match.tag, entry.handler.match.on) && originMatches(handler.replaces, entry.origin)) {
740
+ removed += 1;
741
+ continue;
742
+ }
743
+ remaining.push(entry);
744
+ }
745
+ if (removed === 0 && strict) throw new MetadataError({ message: `Preset '${presetName}': JSDoc handler with replaces=${describeReplaces(handler.replaces)} on '@${handler.match.tag}' did not match any parent handler` });
746
+ merged[kind] = remaining;
747
+ }
748
+ function handlerMatches(handler, targetName, targetOn) {
749
+ if (("name" in handler.match ? handler.match.name : handler.match.tag) !== targetName) return false;
750
+ if (handler.match.on && handler.match.on !== targetOn) return false;
751
+ return true;
752
+ }
753
+ function originMatches(replaces, origin) {
754
+ if (replaces === true) return true;
755
+ return replaces === origin;
756
+ }
757
+ function describeReplaces(replaces) {
758
+ return replaces === true ? "true" : `'${replaces}'`;
759
+ }
760
+ function appendTagged(target, source) {
761
+ for (const kind of decoratorKinds) target[kind].push(...source[kind]);
762
+ for (const kind of jsDocKinds) target[kind].push(...source[kind]);
763
+ }
764
+ function stripOrigins(tagged) {
765
+ const registry = createRegistry();
766
+ registry.controllers = tagged.controllers.map((e) => e.handler);
767
+ registry.methods = tagged.methods.map((e) => e.handler);
768
+ registry.parameters = tagged.parameters.map((e) => e.handler);
769
+ registry.controllerJsDoc = tagged.controllerJsDoc.map((e) => e.handler);
770
+ registry.methodJsDoc = tagged.methodJsDoc.map((e) => e.handler);
771
+ registry.parameterJsDoc = tagged.parameterJsDoc.map((e) => e.handler);
772
+ return registry;
773
+ }
774
+ /**
775
+ * Resolve a preset by string identifier (npm package, relative path, etc.) and
776
+ * return the v2 Preset object. Looks for a `preset` named export, then the
777
+ * default export, then the module itself.
778
+ */
779
+ async function resolvePresetByName(input) {
780
+ const lookupPaths = generatePresetLookupPaths(input);
781
+ let lastError;
782
+ for (const lookupPath of lookupPaths) try {
783
+ const moduleExport = await load(lookupPath);
784
+ const candidates = [
785
+ moduleExport.preset,
786
+ moduleExport.default,
787
+ moduleExport
788
+ ];
789
+ for (const candidate of candidates) if (isV2Preset(candidate)) return candidate;
790
+ } catch (e) {
791
+ lastError = e;
792
+ }
793
+ throw new ConfigError({
794
+ message: `Preset '${input}' could not be resolved.`,
795
+ code: ConfigErrorCode.PRESET_NOT_FOUND,
796
+ cause: lastError
797
+ });
798
+ }
799
+ /**
800
+ * Resolve a preset by name and immediately materialize its registry, recursively
801
+ * loading `extends` parents through the same resolver.
802
+ */
803
+ async function loadRegistryByName(input) {
804
+ return loadRegistry(await resolvePresetByName(input), { resolver: resolvePresetByName });
805
+ }
806
+ function isV2Preset(input) {
807
+ return typeof input === "object" && input !== null && typeof input.name === "string" && !("items" in input);
808
+ }
809
+ //#endregion
810
+ //#region src/adapters/typescript/js-doc/constants.ts
811
+ let JSDocTagName = /* @__PURE__ */ function(JSDocTagName) {
812
+ JSDocTagName["ABSTRACT"] = "abstract";
813
+ JSDocTagName["ACCESS"] = "access";
814
+ JSDocTagName["ALIAS"] = "alias";
815
+ JSDocTagName["ASYNC"] = "async";
816
+ /**
817
+ * Alias for @extends
818
+ */
819
+ JSDocTagName["AUGMENTS"] = "augments";
820
+ JSDocTagName["AUTHOR"] = "author";
821
+ JSDocTagName["DEFAULT"] = "default";
822
+ JSDocTagName["DEPRECATED"] = "deprecated";
823
+ JSDocTagName["DESCRIPTION"] = "description";
824
+ JSDocTagName["EXAMPLE"] = "example";
825
+ JSDocTagName["FORMAT"] = "format";
826
+ JSDocTagName["IGNORE"] = "ignore";
827
+ JSDocTagName["SUMMARY"] = "summary";
828
+ return JSDocTagName;
829
+ }({});
830
+ //#endregion
831
+ //#region src/core/utils/array.ts
832
+ function isStringArray(input) {
833
+ if (!Array.isArray(input)) return false;
834
+ for (const element of input) if (typeof element !== "string") return false;
835
+ return true;
836
+ }
837
+ //#endregion
838
+ //#region src/core/utils/object.ts
839
+ function hasOwnProperty(obj, prop) {
840
+ return Object.prototype.hasOwnProperty.call(obj, prop);
841
+ }
842
+ //#endregion
843
+ //#region src/core/utils/path-normalize.ts
844
+ function normalizePath(str) {
845
+ str = str.replace(/^[/\\\s]+|[/\\\s]+$/g, "");
846
+ str = str.replace(/([^:]\/)\/+/g, "$1");
847
+ return str;
848
+ }
849
+ //#endregion
850
+ //#region src/adapters/typescript/js-doc/utils.ts
851
+ function transformJSDocComment(input) {
852
+ if (typeof input === "string") return input;
853
+ if (!input || input.length === 0) return;
854
+ const comment = input[0];
855
+ if (typeof comment === "string") return comment;
856
+ if (isObject(comment) && typeof comment.text === "string") return comment.text;
857
+ }
858
+ //#endregion
859
+ //#region src/adapters/typescript/js-doc/module.ts
860
+ function getJSDocDescription(node, index) {
861
+ const jsDoc = getJSDoc(node, index);
862
+ if (!jsDoc) return;
863
+ return transformJSDocComment(jsDoc.comment);
864
+ }
865
+ function getJSDoc(node, index) {
866
+ if (!hasOwnProperty(node, "jsDoc")) return;
867
+ const jsDoc = node.jsDoc;
868
+ if (!jsDoc || !Array.isArray(jsDoc) || !jsDoc.length) return;
869
+ index = index ?? 0;
870
+ return jsDoc.length > index && index >= 0 ? jsDoc[index] : void 0;
871
+ }
872
+ function getJSDocTags(node, isMatching) {
873
+ const jsDoc = getJSDoc(node);
874
+ if (typeof jsDoc === "undefined") return [];
875
+ const jsDocTags = jsDoc.tags;
876
+ if (typeof jsDocTags === "undefined") return [];
877
+ if (typeof isMatching === "undefined") return jsDocTags;
878
+ if (typeof isMatching === "function") return jsDocTags.filter(isMatching);
879
+ const tagNames = Array.isArray(isMatching) ? isMatching : [isMatching];
880
+ return jsDocTags.filter((tag) => tagNames.includes(tag.tagName.text));
881
+ }
882
+ function hasJSDocTag(node, tagName) {
883
+ const tags = getJSDocTags(node, tagName);
884
+ return !(!tags || !tags.length);
885
+ }
886
+ function getJSDocTagComment(node, tagName) {
887
+ const tags = getJSDocTags(node, tagName);
888
+ if (!tags || !tags.length || typeof tags[0].comment !== "string") return;
889
+ return tags[0].comment;
890
+ }
891
+ function getJSDocTagNames(node, requireTagName = false) {
892
+ let tags;
893
+ /* istanbul ignore next */
894
+ if (node.kind === SyntaxKind.Parameter) {
895
+ const parameterName = node.name.text;
896
+ tags = getJSDocTags(node.parent, (tag) => {
897
+ if (isJSDocParameterTag(tag)) return false;
898
+ if (tag.comment === void 0) throw new MetadataError(`Orphan tag: @${String(tag.tagName.text || tag.tagName.escapedText)} must be followed by a parameter name.`);
899
+ return typeof tag.comment === "string" ? tag.comment.startsWith(parameterName) : false;
900
+ });
901
+ } else tags = getJSDocTags(node, (tag) => requireTagName ? tag.comment !== void 0 : true);
902
+ return tags.map((tag) => tag.tagName.text);
903
+ }
904
+ //#endregion
905
+ //#region src/adapters/typescript/initializer.ts
906
+ function getInitializerValue(initializer, typeChecker, type) {
907
+ if (!initializer) return;
908
+ switch (initializer.kind) {
909
+ case ts.SyntaxKind.ArrayLiteralExpression: return initializer.elements.map((element) => getInitializerValue(element, typeChecker));
910
+ case ts.SyntaxKind.StringLiteral:
911
+ case ts.SyntaxKind.NoSubstitutionTemplateLiteral: return initializer.text;
912
+ case ts.SyntaxKind.TrueKeyword: return true;
913
+ case ts.SyntaxKind.FalseKeyword: return false;
914
+ case ts.SyntaxKind.PrefixUnaryExpression: {
915
+ const prefixUnary = initializer;
916
+ switch (prefixUnary.operator) {
917
+ case ts.SyntaxKind.PlusToken: return Number(prefixUnary.operand.text);
918
+ case ts.SyntaxKind.MinusToken: return Number(`-${prefixUnary.operand.text}`);
919
+ default: throw new MetadataError(`Unsupported prefix operator token: ${prefixUnary.operator}`);
920
+ }
921
+ }
922
+ case ts.SyntaxKind.NumberKeyword:
923
+ case ts.SyntaxKind.FirstLiteralToken: return Number(initializer.text);
924
+ case ts.SyntaxKind.NewExpression: {
925
+ const newExpression = initializer;
926
+ if (newExpression.expression.text === "Date") {
927
+ let date = /* @__PURE__ */ new Date();
928
+ if (newExpression.arguments) {
929
+ const argsValue = newExpression.arguments.filter((args) => args.kind !== void 0).map((args) => getInitializerValue(args, typeChecker));
930
+ if (argsValue.length > 0) date = new Date(argsValue);
931
+ }
932
+ const dateString = date.toISOString();
933
+ if (type && type.typeName === "date") return dateString.split("T")[0];
934
+ return dateString;
935
+ }
936
+ return;
937
+ }
938
+ case ts.SyntaxKind.NullKeyword: return null;
939
+ case ts.SyntaxKind.ObjectLiteralExpression: {
940
+ const objectLiteral = initializer;
941
+ const nestedObject = {};
942
+ objectLiteral.properties.forEach((p) => {
943
+ nestedObject[p.name.text] = getInitializerValue(p.initializer, typeChecker);
944
+ });
945
+ return nestedObject;
946
+ }
947
+ case ts.SyntaxKind.ImportSpecifier: {
948
+ if (typeof typeChecker === "undefined") return;
949
+ const importSpecifier = initializer;
950
+ const importSymbol = typeChecker.getSymbolAtLocation(importSpecifier.name);
951
+ if (!importSymbol) return;
952
+ const declarations = typeChecker.getAliasedSymbol(importSymbol).getDeclarations();
953
+ return getInitializerValue(extractInitializer(declarations && declarations.length > 0 ? declarations[0] : void 0), typeChecker);
954
+ }
955
+ default: {
956
+ if (typeof initializer === "undefined") return;
957
+ if (typeof initializer.parent === "undefined" || typeof typeChecker === "undefined") {
958
+ if (hasOwnProperty(initializer, "text")) return initializer.text;
959
+ return;
960
+ }
961
+ const symbol = typeChecker.getSymbolAtLocation(initializer);
962
+ return getInitializerValue(extractInitializer(symbol.valueDeclaration) || extractInitializer(extractImportSpecifier(symbol)), typeChecker);
963
+ }
964
+ }
965
+ }
966
+ const hasInitializer = (node) => Object.prototype.hasOwnProperty.call(node, "initializer");
967
+ const extractInitializer = (valueDeclaration) => valueDeclaration && hasInitializer(valueDeclaration) && valueDeclaration.initializer || void 0;
968
+ const extractImportSpecifier = (symbol) => symbol?.declarations && symbol.declarations.length > 0 && ts.isImportSpecifier(symbol.declarations[0]) && symbol.declarations[0] || void 0;
969
+ //#endregion
970
+ //#region src/adapters/decorator/typescript/utils.ts
971
+ /**
972
+ * Enumerate decorators on a TS node and classify their argument values without
973
+ * going through the registry. Used by read-side consumers (type resolver,
974
+ * extension extraction) that only need decorator names + argument values.
975
+ */
976
+ function readNodeDecorators(node, typeChecker) {
977
+ if (!ts.canHaveDecorators(node)) return [];
978
+ const decorators = ts.getDecorators(node);
979
+ if (!decorators || decorators.length === 0) return [];
980
+ const output = [];
981
+ for (const decorator of decorators) {
982
+ const { expression } = decorator;
983
+ let name;
984
+ let argumentExpressions = [];
985
+ if (ts.isCallExpression(expression)) {
986
+ argumentExpressions = expression.arguments;
987
+ name = readDecoratorName$1(expression.expression);
988
+ } else name = readDecoratorName$1(expression);
989
+ if (!name) continue;
990
+ output.push({
991
+ name,
992
+ arguments: argumentExpressions.map((a) => buildDecoratorArgument(a, typeChecker))
993
+ });
994
+ }
995
+ return output;
996
+ }
997
+ function findDecoratorByName(node, name, typeChecker) {
998
+ return readNodeDecorators(node, typeChecker).find((d) => d.name === name);
999
+ }
1000
+ function findDecoratorsByName(node, name, typeChecker) {
1001
+ return readNodeDecorators(node, typeChecker).filter((d) => d.name === name);
1002
+ }
1003
+ function hasDecoratorNamed(node, name, typeChecker) {
1004
+ return readNodeDecorators(node, typeChecker).some((d) => d.name === name);
1005
+ }
1006
+ function readDecoratorName$1(expression) {
1007
+ if (ts.isIdentifier(expression)) return expression.text;
1008
+ if (ts.isPropertyAccessExpression(expression)) return expression.name.text;
1009
+ }
1010
+ function buildDecoratorArgument(expr, typeChecker) {
1011
+ if (ts.isStringLiteral(expr) || ts.isNumericLiteral(expr) || ts.isNoSubstitutionTemplateLiteral(expr)) return {
1012
+ raw: getInitializerValue(expr, typeChecker),
1013
+ kind: "literal"
1014
+ };
1015
+ if (expr.kind === ts.SyntaxKind.TrueKeyword) return {
1016
+ raw: true,
1017
+ kind: "literal"
1018
+ };
1019
+ if (expr.kind === ts.SyntaxKind.FalseKeyword) return {
1020
+ raw: false,
1021
+ kind: "literal"
1022
+ };
1023
+ if (expr.kind === ts.SyntaxKind.NullKeyword) return {
1024
+ raw: null,
1025
+ kind: "literal"
1026
+ };
1027
+ if (ts.isPrefixUnaryExpression(expr) && (expr.operator === ts.SyntaxKind.PlusToken || expr.operator === ts.SyntaxKind.MinusToken) && ts.isNumericLiteral(expr.operand)) return {
1028
+ raw: getInitializerValue(expr, typeChecker),
1029
+ kind: "literal"
1030
+ };
1031
+ if (ts.isObjectLiteralExpression(expr)) return {
1032
+ raw: getInitializerValue(expr, typeChecker),
1033
+ kind: "object"
1034
+ };
1035
+ if (ts.isArrayLiteralExpression(expr)) return {
1036
+ raw: getInitializerValue(expr, typeChecker),
1037
+ kind: "array"
1038
+ };
1039
+ if (ts.isIdentifier(expr) || ts.isPropertyAccessExpression(expr)) {
1040
+ const value = getInitializerValue(expr, typeChecker);
1041
+ if (typeof value !== "undefined") return {
1042
+ raw: value,
1043
+ kind: "identifier"
1044
+ };
1045
+ return {
1046
+ raw: void 0,
1047
+ kind: "unresolvable"
1048
+ };
1049
+ }
1050
+ return {
1051
+ raw: void 0,
1052
+ kind: "unresolvable"
1053
+ };
1054
+ }
1055
+ //#endregion
1056
+ //#region src/adapters/decorator/typescript/module.ts
1057
+ function buildDecoratorSources(node, options) {
1058
+ if (!ts.canHaveDecorators(node)) return [];
1059
+ const decorators = ts.getDecorators(node);
1060
+ if (!decorators || decorators.length === 0) return [];
1061
+ const output = [];
1062
+ for (const decorator of decorators) {
1063
+ const source = buildDecoratorSource(decorator, options);
1064
+ if (source) output.push(source);
1065
+ }
1066
+ return output;
1067
+ }
1068
+ function buildDecoratorSource(decorator, options) {
1069
+ const { expression } = decorator;
1070
+ let name;
1071
+ let argumentExpressions = [];
1072
+ let typeArgumentNodes = [];
1073
+ if (ts.isCallExpression(expression)) {
1074
+ argumentExpressions = expression.arguments;
1075
+ typeArgumentNodes = expression.typeArguments ?? [];
1076
+ name = readDecoratorName(expression.expression);
1077
+ } else name = readDecoratorName(expression);
1078
+ if (!name) return;
1079
+ const decoratorArguments = argumentExpressions.map((arg) => buildDecoratorArgument(arg, options.typeChecker));
1080
+ const decoratorTypeArguments = typeArgumentNodes.map((typeNode) => ({ resolve: () => options.resolveTypeNode(typeNode) }));
1081
+ const sourceFile = decorator.getSourceFile();
1082
+ const location = sourceFile ? {
1083
+ file: sourceFile.fileName,
1084
+ line: sourceFile.getLineAndCharacterOfPosition(decorator.getStart()).line + 1
1085
+ } : void 0;
1086
+ return {
1087
+ name,
1088
+ arguments: decoratorArguments,
1089
+ typeArguments: decoratorTypeArguments,
1090
+ target: options.target,
1091
+ host: options.host,
1092
+ location
1093
+ };
1094
+ }
1095
+ function readDecoratorName(expression) {
1096
+ if (ts.isIdentifier(expression)) return expression.text;
1097
+ if (ts.isPropertyAccessExpression(expression)) return expression.name.text;
1098
+ }
1099
+ function buildJsDocSources(node, options) {
1100
+ const tags = getJSDocTags(node);
1101
+ if (tags.length === 0) return [];
1102
+ const output = [];
1103
+ for (const tag of tags) output.push(buildJsDocSource(tag, options));
1104
+ return output;
1105
+ }
1106
+ function buildJsDocSource(tag, options) {
1107
+ const tagName = tag.tagName.text;
1108
+ const text = transformJSDocComment(tag.comment);
1109
+ let parameterName;
1110
+ let typeNode;
1111
+ if (ts.isJSDocParameterTag(tag) || ts.isJSDocPropertyTag(tag)) {
1112
+ if (tag.name) parameterName = readEntityName(tag.name);
1113
+ typeNode = tag.typeExpression?.type;
1114
+ } else if (ts.isJSDocReturnTag(tag) || ts.isJSDocTypeTag(tag) || ts.isJSDocThisTag(tag)) typeNode = tag.typeExpression?.type;
1115
+ const source = {
1116
+ tag: tagName,
1117
+ target: options.target,
1118
+ host: options.host
1119
+ };
1120
+ if (typeof text !== "undefined") source.text = text;
1121
+ if (typeof parameterName !== "undefined") source.parameterName = parameterName;
1122
+ if (typeNode) {
1123
+ const capturedTypeNode = typeNode;
1124
+ source.typeExpression = { resolve: () => options.resolveTypeNode(capturedTypeNode) };
1125
+ }
1126
+ return source;
1127
+ }
1128
+ function readEntityName(name) {
1129
+ if (ts.isIdentifier(name)) return name.text;
1130
+ if (ts.isQualifiedName(name)) {
1131
+ const left = readEntityName(name.left);
1132
+ return left ? `${left}.${name.right.text}` : name.right.text;
1133
+ }
1134
+ }
1135
+ //#endregion
1136
+ //#region src/adapters/decorator/orchestrator/module.ts
1137
+ function buildHandlerContext(source, options) {
1138
+ return {
1139
+ host: source.host,
1140
+ argument: (i) => source.arguments[i],
1141
+ arguments: () => source.arguments,
1142
+ typeArgument: (i) => source.typeArguments[i],
1143
+ typeArguments: () => source.typeArguments,
1144
+ parameterType: options.parameterType ?? (() => void 0)
1145
+ };
1146
+ }
1147
+ function buildJsDocHandlerContext(source, options) {
1148
+ return {
1149
+ host: source.host,
1150
+ source,
1151
+ parameterType: options.parameterType ?? (() => void 0)
1152
+ };
1153
+ }
1154
+ function applyDecoratorHandlers(node, handlers, draft, options) {
1155
+ if (handlers.length === 0 && !options.onUnmatchedDecorator) return;
1156
+ const sources = buildDecoratorSources(node, options);
1157
+ if (sources.length === 0) return;
1158
+ for (const source of sources) {
1159
+ let matched = 0;
1160
+ for (const handler of handlers) if (matches(handler.match, source)) {
1161
+ handler.apply(buildHandlerContext(source, options), draft);
1162
+ matched += 1;
1163
+ }
1164
+ if (matched === 0 && options.onUnmatchedDecorator) {
1165
+ let file;
1166
+ let line;
1167
+ if (source.location) {
1168
+ file = source.location.file;
1169
+ line = source.location.line;
1170
+ } else {
1171
+ const sourceFile = node.getSourceFile();
1172
+ file = sourceFile.fileName;
1173
+ line = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
1174
+ }
1175
+ options.onUnmatchedDecorator({
1176
+ name: source.name,
1177
+ target: source.target,
1178
+ host: source.host,
1179
+ file,
1180
+ line
1181
+ }, source);
1182
+ }
1183
+ }
1184
+ }
1185
+ function applyJsDocHandlers(node, handlers, draft, options) {
1186
+ if (handlers.length === 0) return;
1187
+ const sources = buildJsDocSources(node, options);
1188
+ if (sources.length === 0) return;
1189
+ for (const source of sources) for (const handler of handlers) if (matchesJsDoc(handler.match, source)) handler.apply(buildJsDocHandlerContext(source, options), draft);
1190
+ }
1191
+ //#endregion
1192
+ //#region src/core/error/validator.ts
1193
+ var ValidatorError$1 = class extends MetadataError {};
1194
+ //#endregion
1195
+ //#region src/core/error/validator-codes.ts
1196
+ const ValidatorErrorCode$1 = {
1197
+ EXPECTED_NUMBER: "VALIDATOR_EXPECTED_NUMBER",
1198
+ EXPECTED_DATE: "VALIDATOR_EXPECTED_DATE",
1199
+ EXPECTED_STRING: "VALIDATOR_EXPECTED_STRING"
1200
+ };
1201
+ //#endregion
1202
+ //#region src/adapters/typescript/validator/module.ts
1203
+ function getDeclarationValidators(declaration, name) {
1204
+ if (!declaration.parent) return {};
1205
+ const getCommentValue = (comment) => comment && comment.split(" ")[0];
1206
+ const parameterTags = getSupportedParameterTags();
1207
+ const tags = getJSDocTags(declaration.parent, (tag) => {
1208
+ const { comment } = tag;
1209
+ const text = transformJSDocComment(comment);
1210
+ if (!comment) return false;
1211
+ const commentValue = getCommentValue(text);
1212
+ return parameterTags.some((value) => {
1213
+ if (value !== tag.tagName.text) return false;
1214
+ return !(name && name !== commentValue);
1215
+ });
1216
+ });
1217
+ function getErrorMsg(comment, isValue = true) {
1218
+ if (!comment) return;
1219
+ if (isValue) {
1220
+ const indexOf = comment.indexOf(" ");
1221
+ if (indexOf > 0) return comment.substring(indexOf + 1);
1222
+ return;
1223
+ }
1224
+ return comment;
1225
+ }
1226
+ const validators = {};
1227
+ for (const tag of tags) {
1228
+ if (!tag.comment) continue;
1229
+ const name = tag.tagName.text;
1230
+ let comment = transformJSDocComment(tag.comment);
1231
+ comment = comment.substring(comment.indexOf(" ") + 1).trim();
1232
+ const value = getCommentValue(comment);
1233
+ switch (name) {
1234
+ case "uniqueItems":
1235
+ validators[name] = {
1236
+ message: getErrorMsg(comment, false),
1237
+ value: void 0
1238
+ };
1239
+ break;
1240
+ case "minimum":
1241
+ case "maximum":
1242
+ case "minItems":
1243
+ case "maxItems":
1244
+ case "minLength":
1245
+ case "maxLength":
1246
+ {
1247
+ const parsed = Number(value);
1248
+ if (!Number.isFinite(parsed)) throw new ValidatorError$1({
1249
+ message: `@${name} validator expects a numeric value, got '${value}'.`,
1250
+ code: ValidatorErrorCode$1.EXPECTED_NUMBER
1251
+ });
1252
+ validators[name] = {
1253
+ message: getErrorMsg(comment),
1254
+ value: parsed
1255
+ };
1256
+ }
1257
+ break;
1258
+ case "minDate":
1259
+ case "maxDate":
1260
+ if (typeof value !== "string") throw new ValidatorError$1({
1261
+ message: `@${name} validator expects a date string, got '${typeof value}'.`,
1262
+ code: ValidatorErrorCode$1.EXPECTED_DATE
1263
+ });
1264
+ validators[name] = {
1265
+ message: getErrorMsg(comment),
1266
+ value
1267
+ };
1268
+ break;
1269
+ case "pattern":
1270
+ if (typeof value !== "string") throw new ValidatorError$1({
1271
+ message: `@${name} validator expects a string pattern, got '${value}'.`,
1272
+ code: ValidatorErrorCode$1.EXPECTED_STRING
1273
+ });
1274
+ validators[name] = {
1275
+ message: getErrorMsg(comment),
1276
+ value: removeSurroundingQuotes(value)
1277
+ };
1278
+ break;
1279
+ default:
1280
+ if (name.toLowerCase().startsWith("is")) {
1281
+ const errorMsg = getErrorMsg(comment, false);
1282
+ if (errorMsg) validators[name] = {
1283
+ message: errorMsg,
1284
+ value: void 0
1285
+ };
1286
+ }
1287
+ break;
1288
+ }
1289
+ }
1290
+ return validators;
1291
+ }
1292
+ function getSupportedParameterTags() {
1293
+ return [
1294
+ "isString",
1295
+ "isBoolean",
1296
+ "isInt",
1297
+ "isLong",
1298
+ "isFloat",
1299
+ "isDouble",
1300
+ "isDate",
1301
+ "isDateTime",
1302
+ "minItems",
1303
+ "maxItems",
1304
+ "uniqueItems",
1305
+ "minLength",
1306
+ "maxLength",
1307
+ "pattern",
1308
+ "minimum",
1309
+ "maximum",
1310
+ "minDate",
1311
+ "maxDate"
1312
+ ];
1313
+ }
1314
+ function removeSurroundingQuotes(str) {
1315
+ if (str.startsWith("`") && str.endsWith("`")) return str.substring(1, str.length - 1);
1316
+ if (str.startsWith("```") && str.endsWith("```")) return str.substring(3, str.length - 3);
1317
+ return str;
1318
+ }
1319
+ //#endregion
1320
+ //#region src/core/error/resolver.ts
1321
+ var ResolverError$1 = class extends MetadataError {
1322
+ file;
1323
+ line;
1324
+ constructor(message, node, options) {
1325
+ const opts = typeof options === "boolean" ? { onlyCurrent: options } : options;
1326
+ const onlyCurrent = opts?.onlyCurrent ?? false;
1327
+ const parts = [message];
1328
+ let file;
1329
+ let line;
1330
+ if (node) {
1331
+ const location = prettyLocationOfNode$1(node);
1332
+ if (location) {
1333
+ parts.push(location.text);
1334
+ file = location.file;
1335
+ line = location.line;
1336
+ }
1337
+ parts.push(prettyTroubleCause$1(node, onlyCurrent));
1338
+ }
1339
+ super({
1340
+ message: parts.join("\n"),
1341
+ cause: opts?.cause
1342
+ });
1343
+ this.file = file;
1344
+ this.line = line;
1345
+ }
1346
+ };
1347
+ function isResolverError$1(input) {
1348
+ if (!isBaseError(input)) return false;
1349
+ return "file" in input && "line" in input;
1350
+ }
1351
+ function prettyLocationOfNode$1(node) {
1352
+ try {
1353
+ const sourceFile = node.getSourceFile();
1354
+ if (!sourceFile) return void 0;
1355
+ const token = node.getFirstToken() || node.parent?.getFirstToken();
1356
+ const start = token ? sourceFile.getLineAndCharacterOfPosition(token.getStart()).line + 1 : void 0;
1357
+ const end = token ? sourceFile.getLineAndCharacterOfPosition(token.getEnd()).line + 1 : void 0;
1358
+ return {
1359
+ text: `At: ${normalize(sourceFile.fileName)}${start ? `:${start}` : ""}${end ? `:${end}` : ""}.`,
1360
+ file: sourceFile.fileName,
1361
+ line: start
1362
+ };
1363
+ } catch {
1364
+ return;
1365
+ }
1366
+ }
1367
+ function prettyTroubleCause$1(node, onlyCurrent = false) {
1368
+ try {
1369
+ let name;
1370
+ if (onlyCurrent || !node.parent) name = node.pos !== -1 ? node.getText() : node.name.text;
1371
+ else name = node.parent.pos !== -1 ? node.parent.getText() : node.parent.name.text;
1372
+ return `This was caused by '${name}'`;
1373
+ } catch {
1374
+ return "This was caused by an unknown node";
1375
+ }
1376
+ }
1377
+ //#endregion
1378
+ //#region src/adapters/typescript/resolver/extension/module.ts
1379
+ function getNodeExtensions(node, registry) {
1380
+ const names = namesForMarker(registry, isExtensionMarker);
1381
+ if (names.size === 0) return [];
1382
+ const output = [];
1383
+ for (const name of names) {
1384
+ const decorators = findDecoratorsByName(node, name);
1385
+ for (const decorator of decorators) {
1386
+ const keyArg = decorator.arguments[0];
1387
+ const valueArg = decorator.arguments[1];
1388
+ if (!keyArg || keyArg.kind !== "literal" || typeof keyArg.raw !== "string") continue;
1389
+ if (!valueArg || valueArg.kind === "unresolvable" || typeof valueArg.raw === "undefined") continue;
1390
+ output.push({
1391
+ key: keyArg.raw,
1392
+ value: valueArg.raw
1393
+ });
1394
+ }
1395
+ }
1396
+ return output;
1397
+ }
1398
+ //#endregion
1399
+ //#region src/adapters/typescript/resolver/sub/array.ts
1400
+ function resolveArrayType(typeNode, ctx) {
1401
+ if (!ts.isArrayTypeNode(typeNode)) return;
1402
+ return {
1403
+ typeName: "array",
1404
+ elementType: ctx.resolveType(typeNode.elementType, ctx.parentNode, ctx.context)
1405
+ };
1406
+ }
1407
+ //#endregion
1408
+ //#region src/adapters/typescript/resolver/sub/base.ts
1409
+ var ResolverBase = class {
1410
+ hasPublicModifier(node) {
1411
+ if (!canHaveModifiers(node)) return true;
1412
+ const modifiers = getModifiers(node);
1413
+ if (!modifiers) return true;
1414
+ return modifiers.every((modifier) => modifier.kind !== SyntaxKind.ProtectedKeyword && modifier.kind !== SyntaxKind.PrivateKeyword);
1415
+ }
1416
+ hasStaticModifier(node) {
1417
+ if (!canHaveModifiers(node)) return false;
1418
+ const modifiers = getModifiers(node);
1419
+ return modifiers && modifiers.some((modifier) => modifier.kind === SyntaxKind.StaticKeyword);
1420
+ }
1421
+ isAccessibleParameter(node) {
1422
+ if (!canHaveModifiers(node)) return false;
1423
+ const modifiers = getModifiers(node);
1424
+ if (!modifiers) return false;
1425
+ if (modifiers.some((modifier) => modifier.kind === SyntaxKind.PublicKeyword)) return true;
1426
+ const isReadonly = modifiers.some((modifier) => modifier.kind === SyntaxKind.ReadonlyKeyword);
1427
+ const isProtectedOrPrivate = modifiers.some((modifier) => modifier.kind === SyntaxKind.ProtectedKeyword || modifier.kind === SyntaxKind.PrivateKeyword);
1428
+ return isReadonly && !isProtectedOrPrivate;
1429
+ }
1430
+ };
1431
+ //#endregion
1432
+ //#region src/adapters/typescript/resolver/utils.ts
1433
+ function getNodeDescription(node, typeChecker) {
1434
+ if (!hasOwnProperty(node, "name")) return;
1435
+ const symbol = typeChecker.getSymbolAtLocation(node.name);
1436
+ if (!symbol) return;
1437
+ /**
1438
+ * TODO: Workaround for what seems like a bug in the compiler
1439
+ * Warrants more investigation and possibly a PR against typescript
1440
+ */
1441
+ if (node.kind === SyntaxKind.Parameter) symbol.flags = 0;
1442
+ const comments = symbol.getDocumentationComment(typeChecker);
1443
+ if (comments.length) return displayPartsToString(comments);
1444
+ }
1445
+ function toTypeNodeOrFail(typeChecker, ...args) {
1446
+ const output = typeChecker.typeToTypeNode(...args);
1447
+ if (typeof output === "undefined") throw new ResolverError$1("Type could not be transformed to TypeNode.");
1448
+ return output;
1449
+ }
1450
+ //#endregion
1451
+ //#region src/adapters/typescript/resolver/sub/indexed-access.ts
1452
+ function resolveIndexedAccessType(typeNode, ctx) {
1453
+ if (!ts.isIndexedAccessTypeNode(typeNode)) return;
1454
+ if (typeNode.indexType.kind === ts.SyntaxKind.NumberKeyword || typeNode.indexType.kind === ts.SyntaxKind.StringKeyword) {
1455
+ const numberIndexType = typeNode.indexType.kind === ts.SyntaxKind.NumberKeyword;
1456
+ const objectType = ctx.typeChecker.getTypeFromTypeNode(typeNode.objectType);
1457
+ const type = numberIndexType ? objectType.getNumberIndexType() : objectType.getStringIndexType();
1458
+ if (type === void 0) throw new ResolverError$1(`Could not determine ${numberIndexType ? "number" : "string"} index on ${ctx.typeChecker.typeToString(objectType)}`, typeNode);
1459
+ return ctx.resolveType(toTypeNodeOrFail(ctx.typeChecker, type, void 0, void 0), typeNode, ctx.context, ctx.referencer);
1460
+ }
1461
+ if (ts.isLiteralTypeNode(typeNode.indexType) && (ts.isStringLiteral(typeNode.indexType.literal) || ts.isNumericLiteral(typeNode.indexType.literal))) {
1462
+ const hasType = (node) => node !== void 0 && Object.prototype.hasOwnProperty.call(node, "type");
1463
+ const symbol = ctx.typeChecker.getPropertyOfType(ctx.typeChecker.getTypeFromTypeNode(typeNode.objectType), typeNode.indexType.literal.text);
1464
+ if (symbol === void 0) throw new ResolverError$1(`Could not determine the keys on ${ctx.typeChecker.typeToString(ctx.typeChecker.getTypeFromTypeNode(typeNode.objectType))}`, typeNode);
1465
+ if (hasType(symbol.valueDeclaration) && symbol.valueDeclaration.type) return ctx.resolveType(symbol.valueDeclaration.type, typeNode, ctx.context, ctx.referencer);
1466
+ const declaration = ctx.typeChecker.getTypeOfSymbolAtLocation(symbol, typeNode.objectType);
1467
+ try {
1468
+ return ctx.resolveType(toTypeNodeOrFail(ctx.typeChecker, declaration, void 0, void 0), typeNode, ctx.context, ctx.referencer);
1469
+ } catch (err) {
1470
+ throw new ResolverError$1(`Could not determine the keys on ${ctx.typeChecker.typeToString(declaration)}`, typeNode, { cause: err });
1471
+ }
1472
+ }
1473
+ }
1474
+ //#endregion
1475
+ //#region src/adapters/typescript/resolver/sub/intersection.ts
1476
+ function resolveIntersectionType(typeNode, ctx) {
1477
+ if (!ts.isIntersectionTypeNode(typeNode)) return;
1478
+ return {
1479
+ typeName: "intersection",
1480
+ members: typeNode.types.map((type) => ctx.resolveType(type, ctx.parentNode, ctx.context))
1481
+ };
1482
+ }
1483
+ //#endregion
1484
+ //#region src/adapters/typescript/resolver/sub/literal.ts
1485
+ function resolveLiteralType(typeNode, ctx) {
1486
+ if (typeNode.kind === ts.SyntaxKind.NullKeyword) return {
1487
+ typeName: "enum",
1488
+ members: [null]
1489
+ };
1490
+ if (typeNode.kind === ts.SyntaxKind.AnyKeyword || typeNode.kind === ts.SyntaxKind.UnknownKeyword) return { typeName: "any" };
1491
+ if (ts.isLiteralTypeNode(typeNode)) return {
1492
+ typeName: "enum",
1493
+ members: [getLiteralValue(typeNode)]
1494
+ };
1495
+ if (typeNode.kind === ts.SyntaxKind.TemplateLiteralType) {
1496
+ const type = ctx.typeChecker.getTypeFromTypeNode(ctx.referencer || typeNode);
1497
+ if (type.isUnion() && type.types.every((t) => t.isStringLiteral())) return {
1498
+ typeName: "enum",
1499
+ members: type.types.map((t) => t.value)
1500
+ };
1501
+ throw new ResolverError$1(`Could not resolve type: ${ctx.typeChecker.typeToString(ctx.typeChecker.getTypeFromTypeNode(typeNode), typeNode)}`, typeNode);
1502
+ }
1503
+ if (ts.isParenthesizedTypeNode(typeNode)) return ctx.resolveType(typeNode.type, typeNode, ctx.context, ctx.referencer);
1504
+ if (typeNode.kind === ts.SyntaxKind.ObjectKeyword || ts.isFunctionTypeNode(typeNode)) return { typeName: "object" };
1505
+ }
1506
+ function getLiteralValue(typeNode) {
1507
+ let value;
1508
+ switch (typeNode.literal.kind) {
1509
+ case ts.SyntaxKind.TrueKeyword:
1510
+ value = true;
1511
+ break;
1512
+ case ts.SyntaxKind.FalseKeyword:
1513
+ value = false;
1514
+ break;
1515
+ case ts.SyntaxKind.StringLiteral:
1516
+ value = typeNode.literal.text;
1517
+ break;
1518
+ case ts.SyntaxKind.NumericLiteral:
1519
+ value = Number.parseFloat(typeNode.literal.text);
1520
+ break;
1521
+ case ts.SyntaxKind.NullKeyword:
1522
+ value = null;
1523
+ break;
1524
+ default: if (Object.prototype.hasOwnProperty.call(typeNode.literal, "text")) value = typeNode.literal.text;
1525
+ else throw new ResolverError$1(`Couldn't resolve literal node: ${typeNode.literal.getText()}`, typeNode.literal);
1526
+ }
1527
+ return value;
1528
+ }
1529
+ //#endregion
1530
+ //#region src/adapters/typescript/resolver/sub/mapped.ts
1531
+ function resolveMappedType(typeNode, ctx) {
1532
+ if (!ts.isMappedTypeNode(typeNode) || !ctx.referencer) return;
1533
+ const type = ctx.typeChecker.getTypeFromTypeNode(ctx.referencer);
1534
+ const mappedTypeNode = typeNode;
1535
+ const { typeChecker } = ctx;
1536
+ const getDeclaration = (prop) => prop.declarations && prop.declarations[0];
1537
+ const isIgnored = (prop) => {
1538
+ const declaration = getDeclaration(prop);
1539
+ if (prop.getJsDocTags().findIndex((tag) => tag.name === "ignore") >= 0) return true;
1540
+ return !!declaration && !ts.isPropertyDeclaration(declaration) && !ts.isPropertySignature(declaration) && !ts.isParameter(declaration);
1541
+ };
1542
+ return {
1543
+ typeName: "nestedObjectLiteral",
1544
+ properties: type.getProperties().filter((property) => !isIgnored(property)).map((property) => {
1545
+ const declaration = getDeclaration(property);
1546
+ const overrideToken = mappedTypeNode.questionToken?.kind === ts.SyntaxKind.PlusToken ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : mappedTypeNode.questionToken;
1547
+ if (declaration && ts.isPropertySignature(declaration)) return {
1548
+ ...ctx.propertyFromSignature(declaration, overrideToken),
1549
+ name: property.getName()
1550
+ };
1551
+ if (declaration && (ts.isPropertyDeclaration(declaration) || ts.isParameter(declaration))) return {
1552
+ ...ctx.propertyFromDeclaration(declaration, overrideToken),
1553
+ name: property.getName()
1554
+ };
1555
+ let required = (property.flags & ts.SymbolFlags.Optional) === 0;
1556
+ const typeNode2 = toTypeNodeOrFail(typeChecker, typeChecker.getTypeOfSymbolAtLocation(property, typeNode), void 0, ts.NodeBuilderFlags.NoTruncation);
1557
+ if (mappedTypeNode.questionToken && mappedTypeNode.questionToken.kind === ts.SyntaxKind.MinusToken) required = true;
1558
+ else if (mappedTypeNode.questionToken && (mappedTypeNode.questionToken.kind === ts.SyntaxKind.QuestionToken || mappedTypeNode.questionToken.kind === ts.SyntaxKind.PlusToken)) required = false;
1559
+ return {
1560
+ name: property.getName(),
1561
+ required,
1562
+ deprecated: false,
1563
+ type: ctx.resolveType(typeNode2, typeNode, ctx.context, ctx.referencer),
1564
+ validators: {}
1565
+ };
1566
+ })
1567
+ };
1568
+ }
1569
+ //#endregion
1570
+ //#region src/adapters/typescript/resolver/sub/object-literal.ts
1571
+ function resolveObjectLiteralType(typeNode, ctx) {
1572
+ if (!ts.isTypeLiteralNode(typeNode)) return;
1573
+ const properties = typeNode.members.filter((member) => ts.isPropertySignature(member)).reduce((res, propertySignature) => {
1574
+ if (!propertySignature.type) throw new ResolverError$1("No valid type found for property declaration.", propertySignature);
1575
+ const type = ctx.resolveType(propertySignature.type, propertySignature, ctx.context);
1576
+ return [{
1577
+ deprecated: hasJSDocTag(propertySignature, "deprecated"),
1578
+ example: ctx.getNodeExample(propertySignature),
1579
+ extensions: ctx.getNodeExtensions(propertySignature),
1580
+ default: getJSDocTagComment(propertySignature, "default"),
1581
+ description: ctx.getNodeDescription(propertySignature),
1582
+ format: getNodeFormat(propertySignature),
1583
+ name: getPropertyName(propertySignature),
1584
+ required: !propertySignature.questionToken,
1585
+ type,
1586
+ validators: getDeclarationValidators(propertySignature) || {}
1587
+ }, ...res];
1588
+ }, []);
1589
+ const indexMember = typeNode.members.find((member) => ts.isIndexSignatureDeclaration(member));
1590
+ let additionalType;
1591
+ if (indexMember) {
1592
+ const indexSignatureDeclaration = indexMember;
1593
+ if (!isStringType(ctx.resolveType(indexSignatureDeclaration.parameters[0].type, ctx.parentNode, ctx.context))) throw new ResolverError$1("Only string indexes are supported.", typeNode);
1594
+ additionalType = ctx.resolveType(indexSignatureDeclaration.type, ctx.parentNode, ctx.context);
1595
+ }
1596
+ return {
1597
+ additionalProperties: indexMember && additionalType,
1598
+ typeName: "nestedObjectLiteral",
1599
+ properties
1600
+ };
1601
+ }
1602
+ function getNodeFormat(node) {
1603
+ return getJSDocTagComment(node, "format");
1604
+ }
1605
+ function getPropertyName(node) {
1606
+ if (ts.isIdentifier(node.name)) return node.name.text;
1607
+ if (ts.isStringLiteral(node.name) || ts.isNumericLiteral(node.name)) return node.name.text;
1608
+ return node.name.getText();
1609
+ }
1610
+ //#endregion
1611
+ //#region src/adapters/typescript/resolver/sub/primitive.ts
1612
+ const NUMERIC_KIND_TO_TYPE_NAME = {
1613
+ [NumericKind.Int]: "integer",
1614
+ [NumericKind.Long]: "long",
1615
+ [NumericKind.Float]: "float",
1616
+ [NumericKind.Double]: "double"
1617
+ };
1618
+ var PrimitiveResolver = class {
1619
+ registry;
1620
+ constructor(registry) {
1621
+ this.registry = registry;
1622
+ }
1623
+ resolve(node, parentNode) {
1624
+ const resolved = this.resolveSyntaxKind(node.kind);
1625
+ if (resolved) {
1626
+ if (resolved === "string") return { typeName: "string" };
1627
+ if (resolved === "void") return { typeName: "void" };
1628
+ if (resolved === "boolean") return { typeName: "boolean" };
1629
+ if (resolved === "undefined") return { typeName: "undefined" };
1630
+ if (resolved === "null") return;
1631
+ if (resolved === "never") return { typeName: "never" };
1632
+ if (resolved === "bigint") return { typeName: "bigint" };
1633
+ if (resolved === "number") {
1634
+ if (!parentNode) return { typeName: "double" };
1635
+ const presentJsDocTags = new Set(getJSDocTagNames(parentNode).map((tag) => tag.toLowerCase()));
1636
+ for (const kind of [
1637
+ NumericKind.Int,
1638
+ NumericKind.Long,
1639
+ NumericKind.Float,
1640
+ NumericKind.Double
1641
+ ]) {
1642
+ const matchKind = (m) => numericMarkerKind(m) === kind;
1643
+ const decoratorNames = namesForMarker(this.registry, matchKind);
1644
+ for (const name of decoratorNames) if (hasDecoratorNamed(parentNode, name)) return { typeName: NUMERIC_KIND_TO_TYPE_NAME[kind] };
1645
+ const jsDocTags = tagsForMarker(this.registry, matchKind);
1646
+ for (const tag of jsDocTags) if (presentJsDocTags.has(tag.toLowerCase())) return { typeName: NUMERIC_KIND_TO_TYPE_NAME[kind] };
1647
+ }
1648
+ return { typeName: "double" };
1649
+ }
1650
+ }
1651
+ }
1652
+ resolveSyntaxKind(syntaxKind) {
1653
+ switch (syntaxKind) {
1654
+ case SyntaxKind.StringKeyword: return "string";
1655
+ case SyntaxKind.BooleanKeyword: return "boolean";
1656
+ case SyntaxKind.VoidKeyword: return "void";
1657
+ case SyntaxKind.UndefinedKeyword: return "undefined";
1658
+ case SyntaxKind.NullKeyword: return "null";
1659
+ case SyntaxKind.NumberKeyword: return "number";
1660
+ case SyntaxKind.BigIntKeyword: return "bigint";
1661
+ case SyntaxKind.NeverKeyword: return "never";
1662
+ default: return;
1663
+ }
1664
+ }
1665
+ };
1666
+ //#endregion
1667
+ //#region src/adapters/typescript/resolver/sub/reference.ts
1668
+ var ReferenceResolver = class extends ResolverBase {
1669
+ typeChecker;
1670
+ constructor(typeChecker) {
1671
+ super();
1672
+ this.typeChecker = typeChecker;
1673
+ }
1674
+ merge(referenceTypes) {
1675
+ if (referenceTypes.length === 1) return referenceTypes[0];
1676
+ if (referenceTypes.every((refType) => refType.refName === "refEnum")) return this.mergeManyRefEnums(referenceTypes);
1677
+ if (referenceTypes.every((refType) => refType.refName === "refObject")) return this.mergeManyRefObjects(referenceTypes);
1678
+ throw new ResolverError$1(`These resolved type merge rules are not defined: ${JSON.stringify(referenceTypes)}`);
1679
+ }
1680
+ mergeManyRefEnums(many) {
1681
+ let merged = this.mergeRefEnums(many[0], many[1]);
1682
+ for (let i = 2; i < many.length; ++i) merged = this.mergeRefEnums(merged, many[i]);
1683
+ return merged;
1684
+ }
1685
+ mergeRefEnums(first, second) {
1686
+ let description;
1687
+ if (first.description || second.description) if (!first.description) description = second.description;
1688
+ else if (!second.description) description = first.description;
1689
+ else description = `${first.description}\n${second.description}`;
1690
+ return {
1691
+ typeName: "refEnum",
1692
+ example: first.example || second.example,
1693
+ description,
1694
+ members: [...first.members || [], ...second.members || []],
1695
+ memberNames: [...first.memberNames || [], ...second.memberNames || []],
1696
+ refName: first.refName,
1697
+ deprecated: first.deprecated || second.deprecated
1698
+ };
1699
+ }
1700
+ mergeManyRefObjects(many) {
1701
+ let merged = this.mergeRefObject(many[0], many[1]);
1702
+ for (let i = 2; i < many.length; ++i) merged = this.mergeRefObject(merged, many[i]);
1703
+ return merged;
1704
+ }
1705
+ mergeRefObject(first, second) {
1706
+ let description;
1707
+ if (first.description || second.description) if (!first.description) description = second.description;
1708
+ else if (!second.description) description = first.description;
1709
+ else description = `${first.description}\n${second.description}`;
1710
+ const properties = [...first.properties, ...second.properties.filter((prop) => first.properties.every((firstProp) => firstProp.name !== prop.name))];
1711
+ let additionalProperties;
1712
+ if (first.additionalProperties || second.additionalProperties) if (!first.additionalProperties) additionalProperties = second.additionalProperties;
1713
+ else if (!second.additionalProperties) additionalProperties = first.additionalProperties;
1714
+ else additionalProperties = {
1715
+ typeName: "union",
1716
+ members: [first.additionalProperties, second.additionalProperties]
1717
+ };
1718
+ return {
1719
+ typeName: "refObject",
1720
+ description,
1721
+ properties,
1722
+ additionalProperties,
1723
+ refName: first.refName,
1724
+ deprecated: first.deprecated || second.deprecated,
1725
+ example: first.example || second.example
1726
+ };
1727
+ }
1728
+ transformEnum(declaration, enumName) {
1729
+ const isNotUndefined = (item) => item !== void 0;
1730
+ const enums = declaration.members.map(this.typeChecker.getConstantValue.bind(this.typeChecker)).filter(isNotUndefined);
1731
+ const enumNames = declaration.members.map((e) => e.name.getText()).filter(isNotUndefined);
1732
+ return {
1733
+ typeName: "refEnum",
1734
+ description: getNodeDescription(declaration, this.typeChecker),
1735
+ members: enums,
1736
+ memberNames: enumNames,
1737
+ refName: enumName,
1738
+ deprecated: hasJSDocTag(declaration, "deprecated")
1739
+ };
1740
+ }
1741
+ transformEnumMember(declaration, enumName) {
1742
+ return {
1743
+ typeName: "refEnum",
1744
+ refName: enumName,
1745
+ members: [this.typeChecker.getConstantValue(declaration)],
1746
+ memberNames: [declaration.name.getText()],
1747
+ deprecated: hasJSDocTag(declaration, "deprecated")
1748
+ };
1749
+ }
1750
+ };
1751
+ //#endregion
1752
+ //#region src/adapters/typescript/resolver/sub/tuple.ts
1753
+ function resolveTupleType(typeNode, ctx) {
1754
+ if (!ts.isTupleTypeNode(typeNode)) return;
1755
+ return {
1756
+ typeName: "tuple",
1757
+ elements: typeNode.elements.map((element) => {
1758
+ const isNamed = ts.isNamedTupleMember(element);
1759
+ const actualType = isNamed ? element.type : element;
1760
+ return {
1761
+ type: ctx.resolveType(actualType, ctx.parentNode, ctx.context),
1762
+ ...isNamed && { name: element.name.text }
1763
+ };
1764
+ })
1765
+ };
1766
+ }
1767
+ //#endregion
1768
+ //#region src/adapters/typescript/resolver/sub/type-operator.ts
1769
+ function resolveTypeOperatorType(typeNode, ctx) {
1770
+ if (!ts.isTypeOperatorNode(typeNode)) return;
1771
+ if (typeNode.operator === ts.SyntaxKind.KeyOfKeyword) {
1772
+ const type = ctx.typeChecker.getTypeFromTypeNode(typeNode);
1773
+ try {
1774
+ return ctx.resolveType(toTypeNodeOrFail(ctx.typeChecker, type, void 0, ts.NodeBuilderFlags.NoTruncation), typeNode, ctx.context, ctx.referencer);
1775
+ } catch (err) {
1776
+ throw new ResolverError$1(`Could not determine the keys on ${ctx.typeChecker.typeToString(ctx.typeChecker.getTypeFromTypeNode(typeNode.type))}`, typeNode, { cause: err });
1777
+ }
1778
+ }
1779
+ if (typeNode.operator === ts.SyntaxKind.ReadonlyKeyword) return ctx.resolveType(typeNode.type, typeNode, ctx.context, ctx.referencer);
1780
+ }
1781
+ //#endregion
1782
+ //#region src/adapters/typescript/resolver/sub/union.ts
1783
+ function resolveUnionType(typeNode, ctx) {
1784
+ if (!ts.isUnionTypeNode(typeNode)) return;
1785
+ return {
1786
+ typeName: "union",
1787
+ members: typeNode.types.map((type) => ctx.resolveType(type, ctx.parentNode, ctx.context))
1788
+ };
1789
+ }
1790
+ //#endregion
1791
+ //#region src/adapters/typescript/resolver/module.ts
1792
+ var TypeNodeResolver = class TypeNodeResolver extends ResolverBase {
1793
+ static MAX_DEPTH = 50;
1794
+ typeNode;
1795
+ current;
1796
+ parentNode;
1797
+ context;
1798
+ referencer;
1799
+ depth;
1800
+ primitiveResolver;
1801
+ referenceResolver;
1802
+ constructor(typeNode, current, parentNode, context, referencer, depth) {
1803
+ super();
1804
+ this.typeNode = typeNode;
1805
+ this.current = current;
1806
+ this.parentNode = parentNode;
1807
+ this.context = context || {};
1808
+ this.referencer = referencer;
1809
+ this.depth = depth ?? 0;
1810
+ this.primitiveResolver = new PrimitiveResolver(current.registry);
1811
+ this.referenceResolver = new ReferenceResolver(current.typeChecker);
1812
+ }
1813
+ /**
1814
+ * @deprecated Use resolverCache.clear() on the context instead.
1815
+ * Kept for backward compatibility — no-ops since cache is now instance-scoped.
1816
+ */
1817
+ static clearCache() {}
1818
+ resolve() {
1819
+ if (this.depth > TypeNodeResolver.MAX_DEPTH) throw new ResolverError$1(`Type resolution exceeded maximum depth of ${TypeNodeResolver.MAX_DEPTH}. This usually indicates deeply nested or circular generics.`, this.typeNode);
1820
+ const ctx = this.createSubResolverContext();
1821
+ const result = this.primitiveResolver.resolve(this.typeNode, this.parentNode) ?? resolveLiteralType(this.typeNode, ctx) ?? resolveArrayType(this.typeNode, ctx) ?? resolveUnionType(this.typeNode, ctx) ?? resolveIntersectionType(this.typeNode, ctx) ?? resolveObjectLiteralType(this.typeNode, ctx) ?? resolveTupleType(this.typeNode, ctx) ?? resolveMappedType(this.typeNode, ctx) ?? this.resolveConditionalType() ?? resolveTypeOperatorType(this.typeNode, ctx) ?? resolveIndexedAccessType(this.typeNode, ctx) ?? this.resolveTypeReference();
1822
+ if (!result) this.throwUnknownType();
1823
+ return result;
1824
+ }
1825
+ createSubResolverContext() {
1826
+ return {
1827
+ typeChecker: this.current.typeChecker,
1828
+ current: this.current,
1829
+ parentNode: this.parentNode,
1830
+ context: this.context,
1831
+ referencer: this.referencer,
1832
+ resolveType: (typeNode, parentNode, context, referencer) => this.resolveNestedType(typeNode, parentNode, context, referencer),
1833
+ propertyFromSignature: (sig, overrideToken) => this.propertyFromSignature(sig, overrideToken),
1834
+ propertyFromDeclaration: (decl, overrideToken) => this.propertyFromDeclaration(decl, overrideToken),
1835
+ getNodeDescription: (node) => this.getNodeDescription(node),
1836
+ getNodeExample: (node) => this.getNodeExample(node),
1837
+ getNodeExtensions: (node) => this.getNodeExtensions(node)
1838
+ };
1839
+ }
1840
+ resolveNestedType(typeNode, parentNode, context, referencer) {
1841
+ return new TypeNodeResolver(typeNode, this.current, parentNode, context, referencer, this.depth + 1).resolve();
1842
+ }
1843
+ throwUnknownType() {
1844
+ throw new ResolverError$1(`Unknown type: ${ts.SyntaxKind[this.typeNode.kind]}`, this.typeNode);
1845
+ }
1846
+ resolveConditionalType() {
1847
+ if (!ts.isConditionalTypeNode(this.typeNode)) return;
1848
+ if (Object.keys(this.context).length > 0 && this.referencer) return this.resolveTypeViaChecker(this.referencer);
1849
+ return this.resolveTypeViaChecker(this.typeNode);
1850
+ }
1851
+ resolveTypeReference() {
1852
+ if (this.typeNode.kind !== ts.SyntaxKind.TypeReference) return;
1853
+ const typeReference = this.typeNode;
1854
+ if (typeReference.typeName.kind === ts.SyntaxKind.Identifier) {
1855
+ if (typeReference.typeName.text === "Record" && typeReference.typeArguments) return {
1856
+ additionalProperties: this.resolveNestedType(typeReference.typeArguments[1], this.parentNode, this.context),
1857
+ typeName: "nestedObjectLiteral",
1858
+ properties: []
1859
+ };
1860
+ const specialReference = TypeNodeResolver.resolveSpecialReference(typeReference.typeName);
1861
+ if (typeof specialReference !== "undefined") return specialReference;
1862
+ if (typeReference.typeName.text === "Date") return this.getDateType(this.parentNode);
1863
+ if (typeReference.typeName.text === "Buffer" || typeReference.typeName.text === "Readable") return { typeName: "buffer" };
1864
+ if (typeReference.typeName.text === "Array" && typeReference.typeArguments && typeReference.typeArguments.length >= 1) return {
1865
+ typeName: "array",
1866
+ elementType: this.resolveNestedType(typeReference.typeArguments[0], this.parentNode, this.context)
1867
+ };
1868
+ if (typeReference.typeName.text === "Promise" && typeReference.typeArguments && typeReference.typeArguments.length === 1) return this.resolveNestedType(typeReference.typeArguments[0], this.parentNode, this.context);
1869
+ if (typeReference.typeName.text === "String") return { typeName: "string" };
1870
+ if (this.context[typeReference.typeName.text]) return this.resolveNestedType(this.context[typeReference.typeName.text], this.parentNode, this.context);
1871
+ if (TypeNodeResolver.isCheckerResolvableUtilityType(typeReference.typeName.text)) return this.resolveUtilityTypeViaChecker(typeReference);
1872
+ }
1873
+ try {
1874
+ const referenceType = this.getReferenceType(typeReference);
1875
+ this.current.addReferenceType(referenceType);
1876
+ return referenceType;
1877
+ } catch (err) {
1878
+ try {
1879
+ return this.resolveTypeViaChecker(typeReference);
1880
+ } catch {
1881
+ throw err;
1882
+ }
1883
+ }
1884
+ }
1885
+ static CHECKER_RESOLVABLE_UTILITY_TYPES = new Set([
1886
+ "NonNullable",
1887
+ "Omit",
1888
+ "Partial",
1889
+ "Readonly",
1890
+ "Required",
1891
+ "Pick",
1892
+ "Extract",
1893
+ "Exclude",
1894
+ "ReturnType",
1895
+ "Parameters",
1896
+ "Awaited",
1897
+ "InstanceType",
1898
+ "ConstructorParameters"
1899
+ ]);
1900
+ static isCheckerResolvableUtilityType(name) {
1901
+ return TypeNodeResolver.CHECKER_RESOLVABLE_UTILITY_TYPES.has(name);
1902
+ }
1903
+ resolveUtilityTypeViaChecker(typeReference) {
1904
+ if (this.hasUnboundContextArgs(typeReference) && this.referencer) return this.resolveTypeViaChecker(this.referencer);
1905
+ return this.resolveTypeViaChecker(typeReference);
1906
+ }
1907
+ /**
1908
+ * Shared checker delegation: resolves a type node by letting the TS
1909
+ * type checker evaluate it, converting back to a TypeNode, and
1910
+ * recursively resolving the result.
1911
+ */
1912
+ resolveTypeViaChecker(typeNode) {
1913
+ const type = this.current.typeChecker.getTypeFromTypeNode(typeNode);
1914
+ const resolvedTypeNode = this.current.typeChecker.typeToTypeNode(type, void 0, ts.NodeBuilderFlags.NoTruncation | ts.NodeBuilderFlags.InTypeAlias);
1915
+ if (!resolvedTypeNode) return {
1916
+ typeName: "tuple",
1917
+ elements: []
1918
+ };
1919
+ return this.resolveNestedType(resolvedTypeNode, this.parentNode, this.context);
1920
+ }
1921
+ /**
1922
+ * Check if a type reference has type arguments that reference unbound
1923
+ * type parameters from this.context (e.g. `Awaited<T>` where T is a
1924
+ * generic parameter mapped in context).
1925
+ */
1926
+ hasUnboundContextArgs(typeReference) {
1927
+ if (!typeReference.typeArguments || Object.keys(this.context).length === 0) return false;
1928
+ return typeReference.typeArguments.some((arg) => ts.isTypeReferenceNode(arg) && ts.isIdentifier(arg.typeName) && arg.typeName.text in this.context);
1929
+ }
1930
+ static resolveSpecialReference(node) {
1931
+ switch (node.text) {
1932
+ case "Buffer":
1933
+ case "DownloadBinaryData":
1934
+ case "DownloadResource": return { typeName: "buffer" };
1935
+ default: return;
1936
+ }
1937
+ }
1938
+ getDateType(parentNode) {
1939
+ if (!parentNode) return { typeName: "datetime" };
1940
+ const tags = getJSDocTagNames(parentNode).filter((name) => ["isDate", "isDateTime"].includes(name));
1941
+ if (tags.length === 0) return { typeName: "datetime" };
1942
+ switch (tags[0]) {
1943
+ case "isDate": return { typeName: "date" };
1944
+ default: return { typeName: "datetime" };
1945
+ }
1946
+ }
1947
+ static getDesignatedModels(nodes, _typeName) {
1948
+ return nodes;
1949
+ }
1950
+ getEnumerateType(typeName) {
1951
+ const enumName = typeName.text;
1952
+ let enumNodes = this.current.nodes.filter((node) => node.kind === ts.SyntaxKind.EnumDeclaration && node.name.text === enumName);
1953
+ if (!enumNodes.length) return;
1954
+ enumNodes = TypeNodeResolver.getDesignatedModels(enumNodes, enumName);
1955
+ if (enumNodes.length > 1) throw new ResolverError$1(`Multiple matching enum found for enum ${enumName}; please make enum names unique.`);
1956
+ const enumDeclaration = enumNodes[0];
1957
+ const isNotUndefined = (item) => item !== void 0;
1958
+ const enums = enumDeclaration.members.map(this.current.typeChecker.getConstantValue.bind(this.current.typeChecker)).filter(isNotUndefined);
1959
+ const enumNames = enumDeclaration.members.map((e) => e.name.getText()).filter(isNotUndefined);
1960
+ return {
1961
+ typeName: "refEnum",
1962
+ description: this.getNodeDescription(enumDeclaration),
1963
+ members: enums,
1964
+ memberNames: enumNames,
1965
+ refName: enumName,
1966
+ deprecated: hasJSDocTag(enumDeclaration, "deprecated")
1967
+ };
1968
+ }
1969
+ getReferenceType(node) {
1970
+ let type;
1971
+ if (ts.isTypeReferenceNode(node)) type = node.typeName;
1972
+ else if (ts.isExpressionWithTypeArguments(node)) type = node.expression;
1973
+ else throw new ResolverError$1("Can't resolve reference type.");
1974
+ let resolvableName = node.pos !== -1 ? node.getText() : type.text;
1975
+ if (node.pos === -1 && "typeArguments" in node && Array.isArray(node.typeArguments)) {
1976
+ const argumentsString = node.typeArguments.map((arg) => {
1977
+ if (ts.isLiteralTypeNode(arg)) return `'${String(getLiteralValue(arg))}'`;
1978
+ const resolvedType = this.primitiveResolver.resolveSyntaxKind(arg.kind);
1979
+ if (typeof resolvedType === "undefined") return "any";
1980
+ return resolvedType;
1981
+ });
1982
+ resolvableName += `<${argumentsString.join(", ")}>`;
1983
+ }
1984
+ const name = this.contextualizedName(resolvableName);
1985
+ this.typeArgumentsToContext(node, type, this.context);
1986
+ try {
1987
+ const existingType = this.current.resolverCache.getCachedType(name);
1988
+ if (existingType) return existingType;
1989
+ if (this.current.resolverCache.isInProgress(name)) return this.createCircularDependencyResolver(name);
1990
+ this.current.resolverCache.markInProgress(name);
1991
+ try {
1992
+ const refName = TypeNodeResolver.getRefTypeName(name);
1993
+ const declarations = this.getModelTypeDeclarations(type);
1994
+ const referenceTypes = [];
1995
+ for (const declaration of declarations) if (ts.isTypeAliasDeclaration(declaration)) referenceTypes.push(this.getTypeAliasReference(declaration, name, node));
1996
+ else if (isEnumDeclaration(declaration)) referenceTypes.push(this.referenceResolver.transformEnum(declaration, refName));
1997
+ else if (isEnumMember(declaration)) referenceTypes.push(this.referenceResolver.transformEnumMember(declaration, refName));
1998
+ else referenceTypes.push(this.getModelReference(declaration, name));
1999
+ const referenceType = this.referenceResolver.merge(referenceTypes);
2000
+ this.current.resolverCache.setCachedType(name, referenceType);
2001
+ return referenceType;
2002
+ } finally {
2003
+ this.current.resolverCache.clearInProgress(name);
2004
+ }
2005
+ } catch (err) {
2006
+ throw new ResolverError$1(`There was a problem resolving type of '${name}'.`, node, { cause: err });
2007
+ }
2008
+ }
2009
+ getTypeAliasReference(declaration, name, referencer) {
2010
+ const refName = TypeNodeResolver.getRefTypeName(name);
2011
+ if (declaration.type.kind === ts.SyntaxKind.TypeReference) {
2012
+ const innerRef = declaration.type;
2013
+ const innerName = ts.isIdentifier(innerRef.typeName) ? innerRef.typeName.text : void 0;
2014
+ if (!(innerName === "Record" || innerName !== void 0 && TypeNodeResolver.isCheckerResolvableUtilityType(innerName))) {
2015
+ const referenceType = this.getReferenceType(innerRef);
2016
+ if (referenceType.refName === refName) return referenceType;
2017
+ }
2018
+ }
2019
+ const type = this.resolveNestedType(declaration.type, declaration, this.context, this.referencer || referencer);
2020
+ const example = this.getNodeExample(declaration);
2021
+ return {
2022
+ typeName: "refAlias",
2023
+ default: getJSDocTagComment(declaration, "default"),
2024
+ description: this.getNodeDescription(declaration),
2025
+ refName,
2026
+ format: TypeNodeResolver.getNodeFormat(declaration),
2027
+ type,
2028
+ validators: getDeclarationValidators(declaration) || {},
2029
+ deprecated: hasJSDocTag(declaration, "deprecated"),
2030
+ ...example && { example }
2031
+ };
2032
+ }
2033
+ getModelReference(modelType, name) {
2034
+ const example = this.getNodeExample(modelType);
2035
+ const description = this.getNodeDescription(modelType);
2036
+ const deprecatedDecoratorNames = namesForMarker(this.current.registry, isDeprecatedMarker);
2037
+ const deprecated = [...tagsForMarker(this.current.registry, isDeprecatedMarker)].some((tag) => hasJSDocTag(modelType, tag)) || [...deprecatedDecoratorNames].some((name) => hasDecoratorNamed(modelType, name));
2038
+ if (!modelType.name) throw new ResolverError$1("Can't get Symbol from anonymous class", modelType);
2039
+ const type = this.current.typeChecker.getTypeAtLocation(modelType.name);
2040
+ const toJSON = this.current.typeChecker.getPropertyOfType(type, "toJSON");
2041
+ if (toJSON && toJSON.valueDeclaration && (ts.isMethodDeclaration(toJSON.valueDeclaration) || ts.isMethodSignature(toJSON.valueDeclaration))) {
2042
+ let nodeType = toJSON.valueDeclaration.type;
2043
+ if (!nodeType) {
2044
+ const signature = this.current.typeChecker.getSignatureFromDeclaration(toJSON.valueDeclaration);
2045
+ if (signature) {
2046
+ const implicitType = this.current.typeChecker.getReturnTypeOfSignature(signature);
2047
+ nodeType = this.current.typeChecker.typeToTypeNode(implicitType, void 0, ts.NodeBuilderFlags.NoTruncation);
2048
+ } else throw new ResolverError$1("Can't get signature from toJson value declaration", modelType);
2049
+ }
2050
+ return {
2051
+ refName: `${TypeNodeResolver.getRefTypeName(name)}Alias`,
2052
+ typeName: "refAlias",
2053
+ description,
2054
+ type: this.resolveNestedType(nodeType),
2055
+ deprecated,
2056
+ validators: {},
2057
+ ...example && { example }
2058
+ };
2059
+ }
2060
+ const properties = this.getModelProperties(modelType);
2061
+ const referenceType = {
2062
+ additionalProperties: this.getModelAdditionalProperties(modelType),
2063
+ typeName: "refObject",
2064
+ description,
2065
+ properties: this.getModelInheritedProperties(modelType) || [],
2066
+ refName: TypeNodeResolver.getRefTypeName(name),
2067
+ deprecated,
2068
+ ...example && { example }
2069
+ };
2070
+ referenceType.properties = referenceType.properties.concat(properties);
2071
+ return referenceType;
2072
+ }
2073
+ static getRefTypeName(name) {
2074
+ const sanitized = name.replace(/[<>]/g, "_").replace(/[{}]/g, "_").replace(/\s+/g, "").replace(/,/g, ".").replace(/'([^']*)'/g, "$1").replace(/"([^"]*)"/g, "$1").replace(/&/g, "-and-").replace(/\|/g, "-or-").replace(/\[\]/g, "-array").replace(/([a-z]+):([a-z]+)/gi, "$1-$2").replace(/;/g, "--").replace(/([a-z]+)\[([a-z]+)]/gi, "$1-at-$2").replace(/_/g, "");
2075
+ return encodeURIComponent(sanitized);
2076
+ }
2077
+ contextualizedName(name) {
2078
+ return Object.entries(this.context).reduce((acc, [key, entry]) => acc.replace(new RegExp(`<\\s*([^>]*\\s)*\\s*(${key})(\\s[^>]*)*\\s*>`, "g"), `<$1${entry.getText()}$3>`).replace(new RegExp(`<\\s*([^,]*\\s)*\\s*(${key})(\\s[^,]*)*\\s*,`, "g"), `<$1${entry.getText()}$3,`).replace(new RegExp(`,\\s*([^>]*\\s)*\\s*(${key})(\\s[^>]*)*\\s*>`, "g"), `,$1${entry.getText()}$3>`).replace(new RegExp(`<\\s*([^<]*\\s)*\\s*(${key})(\\s[^<]*)*\\s*<`, "g"), `<$1${entry.getText()}$3<`), name);
2079
+ }
2080
+ handleCachingAndCircularReferences(name, declarationResolver) {
2081
+ try {
2082
+ const existingType = this.current.resolverCache.getCachedType(name);
2083
+ if (existingType) return existingType;
2084
+ if (this.current.resolverCache.isInProgress(name)) return this.createCircularDependencyResolver(name);
2085
+ this.current.resolverCache.markInProgress(name);
2086
+ try {
2087
+ const reference = declarationResolver();
2088
+ this.current.resolverCache.setCachedType(name, reference);
2089
+ this.current.addReferenceType(reference);
2090
+ return reference;
2091
+ } finally {
2092
+ this.current.resolverCache.clearInProgress(name);
2093
+ }
2094
+ } catch (err) {
2095
+ throw new ResolverError$1(`There was a problem resolving type of '${name}'.`, this.typeNode, { cause: err });
2096
+ }
2097
+ }
2098
+ createCircularDependencyResolver(refName) {
2099
+ const referenceType = {
2100
+ deprecated: false,
2101
+ properties: [],
2102
+ typeName: "refObject",
2103
+ refName
2104
+ };
2105
+ this.current.registerDependencyResolver((referenceTypes) => {
2106
+ const realReferenceType = referenceTypes[refName];
2107
+ if (!realReferenceType) return;
2108
+ referenceType.description = realReferenceType.description;
2109
+ if (realReferenceType.typeName === "refObject" && referenceType.typeName === "refObject") referenceType.properties = realReferenceType.properties;
2110
+ referenceType.typeName = realReferenceType.typeName;
2111
+ referenceType.refName = realReferenceType.refName;
2112
+ });
2113
+ return referenceType;
2114
+ }
2115
+ static nodeIsUsable(node) {
2116
+ switch (node.kind) {
2117
+ case ts.SyntaxKind.InterfaceDeclaration:
2118
+ case ts.SyntaxKind.ClassDeclaration:
2119
+ case ts.SyntaxKind.TypeAliasDeclaration:
2120
+ case ts.SyntaxKind.EnumDeclaration:
2121
+ case ts.SyntaxKind.EnumMember: return true;
2122
+ default: return false;
2123
+ }
2124
+ }
2125
+ getModelTypeDeclarations(type) {
2126
+ let typeName = type.kind === ts.SyntaxKind.Identifier ? type.text : type.right.text;
2127
+ let symbol = this.getSymbolAtLocation(type);
2128
+ if (!symbol && type.kind === ts.SyntaxKind.QualifiedName) symbol = this.getSymbolAtLocation(type.left).exports?.get(typeName);
2129
+ if (!symbol) throw new ResolverError$1(`No symbol found for referenced type ${typeName}.`);
2130
+ const declarations = symbol.getDeclarations();
2131
+ if (!declarations || declarations.length === 0) throw new ResolverError$1(`No declarations found for referenced type ${typeName}.`);
2132
+ if (symbol.escapedName !== typeName && symbol.escapedName !== "default") typeName = symbol.escapedName;
2133
+ let modelTypes = declarations.filter((node) => {
2134
+ if (!TypeNodeResolver.nodeIsUsable(node) || !this.current.isExportedNode(node)) return false;
2135
+ return node.name?.text === typeName;
2136
+ });
2137
+ if (!modelTypes.length) throw new ResolverError$1(`No matching model found for referenced type ${typeName}. If ${typeName} comes from a dependency, please create an interface in your own code that has the same structure. The compiler can not utilize interfaces from external dependencies.`);
2138
+ if (modelTypes.length > 1) {
2139
+ modelTypes = modelTypes.filter((modelType) => modelType.getSourceFile().fileName.replace(/\\/g, "/").toLowerCase().indexOf("node_modules/typescript") <= -1);
2140
+ modelTypes = TypeNodeResolver.getDesignatedModels(modelTypes, typeName);
2141
+ }
2142
+ return modelTypes;
2143
+ }
2144
+ getModelTypeDeclaration(type) {
2145
+ let typeName = type.kind === ts.SyntaxKind.Identifier ? type.text : type.right.text;
2146
+ const symbol = this.getSymbolAtLocation(type);
2147
+ const declarations = symbol.getDeclarations();
2148
+ if (!declarations || declarations.length === 0) throw new ResolverError$1(`No models found for referenced type ${typeName}.`);
2149
+ if (symbol.escapedName !== typeName && symbol.escapedName !== "default") typeName = symbol.escapedName;
2150
+ let modelTypes = declarations.filter((node) => {
2151
+ if (!TypeNodeResolver.nodeIsUsable(node) || !this.current.isExportedNode(node)) return false;
2152
+ return node.name?.text === typeName;
2153
+ });
2154
+ if (!modelTypes.length) throw new ResolverError$1(`No matching model found for referenced type ${typeName}. If ${typeName} comes from a dependency, please create an interface in your own code that has the same structure. The compiler can not utilize interfaces from external dependencies.`);
2155
+ if (modelTypes.length > 1) {
2156
+ modelTypes = modelTypes.filter((modelType) => modelType.getSourceFile().fileName.replace(/\\/g, "/").toLowerCase().indexOf("node_modules/typescript") <= -1);
2157
+ modelTypes = TypeNodeResolver.getDesignatedModels(modelTypes, typeName);
2158
+ }
2159
+ if (modelTypes.length > 1) {
2160
+ const conflicts = modelTypes.map((modelType) => modelType.getSourceFile().fileName).join("\"; \"");
2161
+ throw new ResolverError$1(`Multiple matching models found for referenced type ${typeName}; please make model names unique. Conflicts found: "${conflicts}".`);
2162
+ }
2163
+ return modelTypes[0];
2164
+ }
2165
+ hasFlag(type, flag) {
2166
+ return (type.flags & flag) === flag;
2167
+ }
2168
+ getSymbolAtLocation(type) {
2169
+ const symbol = this.current.typeChecker.getSymbolAtLocation(type) || type.symbol;
2170
+ return symbol && this.hasFlag(symbol, ts.SymbolFlags.Alias) && this.current.typeChecker.getAliasedSymbol(symbol) || symbol;
2171
+ }
2172
+ getModelProperties(node, overrideToken) {
2173
+ const isIgnored = (e) => hasJSDocTag(e, "ignore");
2174
+ if (ts.isInterfaceDeclaration(node)) return node.members.filter((member) => !isIgnored(member) && ts.isPropertySignature(member)).map((member) => this.propertyFromSignature(member, overrideToken));
2175
+ const properties = node.members.filter((member) => !isIgnored(member) && member.kind === ts.SyntaxKind.PropertyDeclaration && !this.hasStaticModifier(member) && this.hasPublicModifier(member));
2176
+ const classConstructor = node.members.find((member) => ts.isConstructorDeclaration(member));
2177
+ if (classConstructor && classConstructor.parameters) {
2178
+ const constructorProperties = classConstructor.parameters.filter((parameter) => this.isAccessibleParameter(parameter));
2179
+ properties.push(...constructorProperties);
2180
+ }
2181
+ return properties.map((property) => this.propertyFromDeclaration(property, overrideToken));
2182
+ }
2183
+ propertyFromSignature(propertySignature, overrideToken) {
2184
+ const identifier = propertySignature.name;
2185
+ if (!propertySignature.type) throw new ResolverError$1("No valid type found for property declaration.");
2186
+ let required = !propertySignature.questionToken;
2187
+ if (overrideToken && overrideToken.kind === ts.SyntaxKind.MinusToken) required = true;
2188
+ else if (overrideToken && overrideToken.kind === ts.SyntaxKind.QuestionToken) required = false;
2189
+ return {
2190
+ deprecated: hasJSDocTag(propertySignature, "deprecated"),
2191
+ default: getJSDocTagComment(propertySignature, "default"),
2192
+ description: this.getNodeDescription(propertySignature),
2193
+ example: this.getNodeExample(propertySignature),
2194
+ extensions: this.getNodeExtensions(propertySignature),
2195
+ format: TypeNodeResolver.getNodeFormat(propertySignature),
2196
+ name: identifier.text,
2197
+ required,
2198
+ type: this.resolveNestedType(propertySignature.type, propertySignature.type.parent, this.context, propertySignature.type),
2199
+ validators: getDeclarationValidators(propertySignature) || {}
2200
+ };
2201
+ }
2202
+ propertyFromDeclaration(propertyDeclaration, overrideToken) {
2203
+ const identifier = propertyDeclaration.name;
2204
+ let typeNode = propertyDeclaration.type;
2205
+ if (!typeNode) {
2206
+ const tsType = this.current.typeChecker.getTypeAtLocation(propertyDeclaration);
2207
+ typeNode = this.current.typeChecker.typeToTypeNode(tsType, void 0, ts.NodeBuilderFlags.NoTruncation);
2208
+ }
2209
+ if (!typeNode) throw new ResolverError$1("No valid type found for property declaration.");
2210
+ const type = this.resolveNestedType(typeNode, propertyDeclaration, this.context, typeNode);
2211
+ let required = !propertyDeclaration.questionToken && !propertyDeclaration.initializer;
2212
+ if (overrideToken && overrideToken.kind === ts.SyntaxKind.MinusToken) required = true;
2213
+ else if (overrideToken && overrideToken.kind === ts.SyntaxKind.QuestionToken) required = false;
2214
+ return {
2215
+ deprecated: hasJSDocTag(propertyDeclaration, "deprecated"),
2216
+ default: getInitializerValue(propertyDeclaration.initializer, this.current.typeChecker),
2217
+ description: this.getNodeDescription(propertyDeclaration),
2218
+ example: this.getNodeExample(propertyDeclaration),
2219
+ extensions: this.getNodeExtensions(propertyDeclaration),
2220
+ format: TypeNodeResolver.getNodeFormat(propertyDeclaration),
2221
+ name: identifier.text,
2222
+ required,
2223
+ type,
2224
+ validators: getDeclarationValidators(propertyDeclaration) || {}
2225
+ };
2226
+ }
2227
+ getModelAdditionalProperties(node) {
2228
+ if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
2229
+ const indexMember = node.members.find((member) => member.kind === ts.SyntaxKind.IndexSignature);
2230
+ if (!indexMember) return;
2231
+ const indexSignatureDeclaration = indexMember;
2232
+ if (this.resolveNestedType(indexSignatureDeclaration.parameters[0].type, this.parentNode, this.context).typeName !== "string") throw new ResolverError$1("Only string indexers are supported.", this.typeNode);
2233
+ return this.resolveNestedType(indexSignatureDeclaration.type, this.parentNode, this.context);
2234
+ }
2235
+ }
2236
+ typeArgumentsToContext(type, targetEntity, context) {
2237
+ const declaration = this.getModelTypeDeclaration(targetEntity);
2238
+ if (typeof declaration === "undefined" || !("typeParameters" in declaration)) return context;
2239
+ const { typeParameters } = declaration;
2240
+ if (typeParameters) for (const [index, typeParameter] of typeParameters.entries()) {
2241
+ const typeArg = type.typeArguments && type.typeArguments[index];
2242
+ let resolvedType;
2243
+ if (typeArg && ts.isTypeReferenceNode(typeArg) && ts.isIdentifier(typeArg.typeName) && context[typeArg.typeName.text]) resolvedType = context[typeArg.typeName.text];
2244
+ else if (typeArg) resolvedType = typeArg;
2245
+ else if (typeParameter.default) resolvedType = typeParameter.default;
2246
+ else throw new ResolverError$1(`Could not find a value for type parameter ${typeParameter.name.text}`, type);
2247
+ this.context = {
2248
+ ...this.context,
2249
+ [typeParameter.name.text]: resolvedType
2250
+ };
2251
+ }
2252
+ return context;
2253
+ }
2254
+ getModelInheritedProperties(modelTypeDeclaration) {
2255
+ let properties = [];
2256
+ const { heritageClauses } = modelTypeDeclaration;
2257
+ if (!heritageClauses) return properties;
2258
+ heritageClauses.forEach((clause) => {
2259
+ if (!clause.types) return;
2260
+ clause.types.forEach((t) => {
2261
+ const baseEntityName = t.expression;
2262
+ const resetCtx = this.typeArgumentsToContext(t, baseEntityName, this.context);
2263
+ const referenceType = this.getReferenceType(t);
2264
+ if (referenceType) {
2265
+ if (isRefAliasType(referenceType)) {
2266
+ let type = referenceType;
2267
+ while (isRefAliasType(type)) type = type.type;
2268
+ if (type.typeName === "refObject") properties = [...properties, ...type.properties];
2269
+ else if (type.typeName === "nestedObjectLiteral") properties = [...properties, ...type.properties];
2270
+ }
2271
+ if (isRefObjectType(referenceType)) referenceType.properties.forEach((property) => properties.push(property));
2272
+ }
2273
+ this.context = resetCtx;
2274
+ });
2275
+ });
2276
+ return properties;
2277
+ }
2278
+ getNodeDescription(node) {
2279
+ return getNodeDescription(node, this.current.typeChecker);
2280
+ }
2281
+ static getNodeFormat(node) {
2282
+ return getJSDocTagComment(node, "format");
2283
+ }
2284
+ getNodeExample(node) {
2285
+ const example = getJSDocTagComment(node, "example");
2286
+ if (example) try {
2287
+ return JSON.parse(example);
2288
+ } catch {
2289
+ return example;
2290
+ }
2291
+ }
2292
+ getNodeExtensions(node) {
2293
+ return getNodeExtensions(node, this.current.registry);
2294
+ }
2295
+ };
2296
+ //#endregion
2297
+ //#region src/adapters/typescript/resolver/cache.ts
2298
+ var ResolverCache = class {
2299
+ referenceTypes = /* @__PURE__ */ new Map();
2300
+ inProgressTypes = /* @__PURE__ */ new Set();
2301
+ getCachedType(name) {
2302
+ return this.referenceTypes.get(name);
2303
+ }
2304
+ setCachedType(name, type) {
2305
+ this.referenceTypes.set(name, type);
2306
+ }
2307
+ isInProgress(name) {
2308
+ return this.inProgressTypes.has(name);
2309
+ }
2310
+ markInProgress(name) {
2311
+ this.inProgressTypes.add(name);
2312
+ }
2313
+ clearInProgress(name) {
2314
+ this.inProgressTypes.delete(name);
2315
+ }
2316
+ clear() {
2317
+ this.referenceTypes.clear();
2318
+ this.inProgressTypes.clear();
2319
+ }
2320
+ };
2321
+ //#endregion
2322
+ //#region src/adapters/typescript/node-utils/module.ts
2323
+ /**
2324
+ * Get Decorators for a specific node.
2325
+ *
2326
+ * @param node
2327
+ * @param isMatching
2328
+ */
2329
+ function getNodeDecorators(node, isMatching) {
2330
+ if (!canHaveDecorators(node)) return [];
2331
+ const decorators = getDecorators(node);
2332
+ if (typeof decorators === "undefined") return [];
2333
+ const items = decorators.map((d) => {
2334
+ const result = {
2335
+ arguments: [],
2336
+ typeArguments: []
2337
+ };
2338
+ let x = d.expression;
2339
+ if (isCallExpression(x)) {
2340
+ if (x.arguments) result.arguments = x.arguments.map((argument) => {
2341
+ if (isStringLiteral(argument) || isNumericLiteral(argument)) return argument.text;
2342
+ return argument;
2343
+ });
2344
+ if (x.typeArguments) result.typeArguments = x.typeArguments;
2345
+ x = x.expression;
2346
+ }
2347
+ result.text = x.text || x.name.text;
2348
+ return result;
2349
+ });
2350
+ return typeof isMatching === "undefined" ? items : items.filter(isMatching);
2351
+ }
2352
+ //#endregion
2353
+ //#region src/adapters/filesystem/source-files.ts
2354
+ async function scanSourceFiles(input) {
2355
+ const sources = Array.isArray(input) ? input : [input];
2356
+ const result = /* @__PURE__ */ new Set();
2357
+ const promises = [];
2358
+ for (const source of sources) if (typeof source === "string") promises.push(locateMany(source));
2359
+ else promises.push(locateMany(source.pattern, { path: source.cwd }));
2360
+ const matches = (await Promise.all(promises)).flat();
2361
+ for (const match of matches) result.add(buildFilePath(match));
2362
+ return Array.from(result);
2363
+ }
2364
+ //#endregion
2365
+ //#region src/adapters/filesystem/tsconfig/module.ts
2366
+ async function loadTSConfig(context = {}) {
2367
+ let fileName;
2368
+ let filePath;
2369
+ const cwd = context.cwd || process.cwd();
2370
+ if (typeof context.name === "string") {
2371
+ if (path.isAbsolute(context.name)) filePath = context.name;
2372
+ else filePath = path.resolve(cwd, context.name);
2373
+ fileName = path.basename(filePath);
2374
+ } else {
2375
+ fileName = "tsconfig.json";
2376
+ filePath = path.join(cwd, fileName);
2377
+ }
2378
+ const content = await load(filePath);
2379
+ if (!isObject(content)) throw new ConfigError({
2380
+ message: `The tsconfig file '${filePath}' is malformed.`,
2381
+ code: ConfigErrorCode.TSCONFIG_MALFORMED
2382
+ });
2383
+ if (typeof content.compilerOptions !== "undefined") {
2384
+ const { options: compilerOptions } = convertCompilerOptionsFromJson(content.compilerOptions, cwd, fileName);
2385
+ content.compilerOptions = compilerOptions;
2386
+ }
2387
+ return content;
2388
+ }
2389
+ async function softLoadTsconfig(context = {}) {
2390
+ try {
2391
+ return await loadTSConfig(context);
2392
+ } catch {
2393
+ return {};
2394
+ }
2395
+ }
2396
+ //#endregion
2397
+ //#region src/adapters/cache/constants.ts
2398
+ /**
2399
+ * Bump whenever the on-disk cache shape changes incompatibly
2400
+ * (Metadata, Controller, Method, Parameter, resolver type nodes,
2401
+ * or the cache wrapper itself). Old cache files with a different
2402
+ * version are rejected on read.
2403
+ */
2404
+ const CACHE_SCHEMA_VERSION = "3";
2405
+ const CACHE_FILE_PREFIX = ".trapi-metadata-";
2406
+ const CACHE_FILE_SUFFIX = ".json";
2407
+ /** 7 days. */
2408
+ const CACHE_DEFAULT_MAX_AGE_MS = 10080 * 60 * 1e3;
2409
+ //#endregion
2410
+ //#region src/adapters/cache/utils.ts
2411
+ function buildCacheOptions(input) {
2412
+ if (typeof input === "string") input = {
2413
+ enabled: true,
2414
+ directoryPath: input
2415
+ };
2416
+ if (typeof input === "boolean") input = { enabled: input };
2417
+ input = input || {};
2418
+ let directoryPath = tmpdir();
2419
+ if (typeof input.directoryPath === "string") directoryPath = path.isAbsolute(input.directoryPath) ? input.directoryPath : path.join(process.cwd(), input.directoryPath);
2420
+ return {
2421
+ fileName: input.fileName,
2422
+ directoryPath,
2423
+ enabled: input.enabled ?? true,
2424
+ maxAgeMs: normalizeMaxAgeMs(input.maxAgeMs)
2425
+ };
2426
+ }
2427
+ function normalizeMaxAgeMs(input) {
2428
+ if (typeof input !== "number" || !Number.isFinite(input) || input < 0) return CACHE_DEFAULT_MAX_AGE_MS;
2429
+ return input;
2430
+ }
2431
+ /**
2432
+ * Combines all key contributors into a single sha256 hex string. The order is
2433
+ * stable; each part is null-separated to avoid concatenation ambiguity.
2434
+ */
2435
+ function composeCacheKey(parts) {
2436
+ const hash = crypto.createHash("sha256");
2437
+ hash.update(parts.schemaVersion);
2438
+ hash.update("\0");
2439
+ hash.update(parts.sourceFilesHash);
2440
+ hash.update("\0");
2441
+ hash.update(parts.compilerOptionsHash);
2442
+ hash.update("\0");
2443
+ hash.update(parts.registryHash);
2444
+ hash.update("\0");
2445
+ hash.update(parts.presetName ?? "");
2446
+ return hash.digest("hex");
2447
+ }
2448
+ /**
2449
+ * Hash a stable JSON projection of `compilerOptions`. Sorting keys keeps the
2450
+ * output deterministic regardless of declaration order in tsconfig.json.
2451
+ */
2452
+ function hashCompilerOptions(options) {
2453
+ const hash = crypto.createHash("sha256");
2454
+ hash.update(stableStringify(options ?? {}));
2455
+ return hash.digest("hex");
2456
+ }
2457
+ /**
2458
+ * Hash the resolved registry's structural shape. Catches structural changes
2459
+ * (handler added/removed/renamed, marker changed, replaces policy changed)
2460
+ * AND most logic changes via `apply.toString()`. Misses changes that are
2461
+ * purely captured-variable shifts in factory-built handlers — acceptable
2462
+ * trade-off for catching local preset edits.
2463
+ */
2464
+ function hashRegistry(registry) {
2465
+ const hash = crypto.createHash("sha256");
2466
+ for (const kind of [
2467
+ "controllers",
2468
+ "methods",
2469
+ "parameters",
2470
+ "controllerJsDoc",
2471
+ "methodJsDoc",
2472
+ "parameterJsDoc"
2473
+ ]) {
2474
+ hash.update(kind);
2475
+ hash.update("\0");
2476
+ const handlers = registry[kind] ?? [];
2477
+ for (const handler of handlers) {
2478
+ hash.update(stableStringify(handler.match));
2479
+ hash.update("\0");
2480
+ hash.update(stableStringify(handler.marker ?? null));
2481
+ hash.update("\0");
2482
+ hash.update(String(handler.replaces ?? ""));
2483
+ hash.update("\0");
2484
+ hash.update(handler.apply.toString());
2485
+ hash.update("\0");
2486
+ }
2487
+ hash.update("");
2488
+ }
2489
+ return hash.digest("hex");
2490
+ }
2491
+ /**
2492
+ * JSON.stringify with sorted object keys at every level. Functions and
2493
+ * undefined are omitted as usual; that's fine for the inputs we hash here.
2494
+ */
2495
+ function stableStringify(value) {
2496
+ return JSON.stringify(value, (_key, val) => {
2497
+ if (val && typeof val === "object" && !Array.isArray(val)) {
2498
+ const sorted = {};
2499
+ for (const k of Object.keys(val).sort()) sorted[k] = val[k];
2500
+ return sorted;
2501
+ }
2502
+ return val;
2503
+ });
2504
+ }
2505
+ //#endregion
2506
+ //#region src/adapters/cache/client.ts
2507
+ var CacheClient = class {
2508
+ options;
2509
+ constructor(input) {
2510
+ this.options = buildCacheOptions(input);
2511
+ }
2512
+ async save(data) {
2513
+ if (!this.options.enabled) return;
2514
+ await this.ensureDirectory();
2515
+ const filePath = this.resolveFilePath(data.cacheKey);
2516
+ const payload = stringify(data);
2517
+ const tmpPath = `${filePath}.${process.pid}.${crypto.randomBytes(6).toString("hex")}.tmp`;
2518
+ try {
2519
+ await fs.promises.writeFile(tmpPath, payload);
2520
+ await fs.promises.rename(tmpPath, filePath);
2521
+ } catch (err) {
2522
+ try {
2523
+ await fs.promises.unlink(tmpPath);
2524
+ } catch {}
2525
+ throw err;
2526
+ }
2527
+ this.evict().catch(() => void 0);
2528
+ return filePath;
2529
+ }
2530
+ async get(cacheKey) {
2531
+ if (!this.options.enabled) return;
2532
+ const filePath = this.resolveFilePath(cacheKey);
2533
+ let content;
2534
+ try {
2535
+ content = await fs.promises.readFile(filePath, { encoding: "utf-8" });
2536
+ } catch {
2537
+ return;
2538
+ }
2539
+ let cache;
2540
+ try {
2541
+ cache = parse(content);
2542
+ } catch {
2543
+ await fs.promises.unlink(filePath).catch(() => void 0);
2544
+ return;
2545
+ }
2546
+ if (!cache || cache.cacheKey !== cacheKey || cache.schemaVersion !== "3") return;
2547
+ return cache;
2548
+ }
2549
+ /**
2550
+ * Prune cache files older than `maxAgeMs`. No-op when disabled or when
2551
+ * `maxAgeMs <= 0`. Each unlink is best-effort — a concurrent generator
2552
+ * may have already removed the file.
2553
+ */
2554
+ async evict() {
2555
+ if (!this.options.enabled || this.options.maxAgeMs <= 0) return;
2556
+ const pattern = this.options.fileName ?? `.trapi-metadata-*.json`;
2557
+ let entries;
2558
+ try {
2559
+ entries = await locateMany(pattern, { path: this.options.directoryPath });
2560
+ } catch {
2561
+ return;
2562
+ }
2563
+ const cutoff = Date.now() - this.options.maxAgeMs;
2564
+ await Promise.all(entries.map(async (entry) => {
2565
+ const filePath = buildFilePath(entry);
2566
+ try {
2567
+ if ((await fs.promises.stat(filePath)).mtimeMs < cutoff) await fs.promises.unlink(filePath);
2568
+ } catch {}
2569
+ }));
2570
+ }
2571
+ resolveFilePath(cacheKey) {
2572
+ if (!CACHE_KEY_PATTERN.test(cacheKey)) throw new Error(`Invalid cacheKey: must match ${CACHE_KEY_PATTERN}`);
2573
+ const fileName = this.options.fileName ?? `.trapi-metadata-${cacheKey}.json`;
2574
+ return path.join(this.options.directoryPath, fileName);
2575
+ }
2576
+ async ensureDirectory() {
2577
+ await fs.promises.mkdir(this.options.directoryPath, { recursive: true });
2578
+ }
2579
+ };
2580
+ const CACHE_KEY_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
2581
+ //#endregion
2582
+ //#region src/core/error/generator.ts
2583
+ var GeneratorError$1 = class extends MetadataError {};
2584
+ function isGeneratorError$1(input) {
2585
+ if (!isBaseError(input)) return false;
2586
+ return typeof input.code === "string";
2587
+ }
2588
+ //#endregion
2589
+ //#region src/core/error/generator-codes.ts
2590
+ const GeneratorErrorCode$1 = {
2591
+ CONTROLLER_NO_SOURCE_FILE: "GENERATOR_CONTROLLER_NO_SOURCE_FILE",
2592
+ CONTROLLER_NO_NAME: "GENERATOR_CONTROLLER_NO_NAME",
2593
+ PARAMETER_GENERATION_FAILED: "GENERATOR_PARAMETER_GENERATION_FAILED",
2594
+ BODY_PARAMETER_DUPLICATE: "GENERATOR_BODY_PARAMETER_DUPLICATE",
2595
+ BODY_FORM_CONFLICT: "GENERATOR_BODY_FORM_CONFLICT",
2596
+ STRICT_UNMATCHED_DECORATORS: "GENERATOR_STRICT_UNMATCHED_DECORATORS"
2597
+ };
2598
+ //#endregion
2599
+ //#region src/core/error/parameter.ts
2600
+ var ParameterError$1 = class ParameterError$1 extends MetadataError {
2601
+ static typeUnsupported(context) {
2602
+ const location = context.node ? ParameterError$1.getCurrentLocation(context.node) : void 0;
2603
+ return new ParameterError$1({
2604
+ message: `@${context.decoratorName}('${context.propertyName}') does not support '${context.type.typeName}' type${location ? ` at ${location}` : ""}.`,
2605
+ code: ParameterErrorCode.TYPE_UNSUPPORTED
2606
+ });
2607
+ }
2608
+ static methodUnsupported(context) {
2609
+ const location = context.node ? ParameterError$1.getCurrentLocation(context.node) : void 0;
2610
+ return new ParameterError$1({
2611
+ message: `@${context.decoratorName}('${context.propertyName}') does not support method '${context.method}'${location ? ` at ${location}` : ""}.`,
2612
+ code: ParameterErrorCode.METHOD_UNSUPPORTED
2613
+ });
2614
+ }
2615
+ static invalidPathMatch(context) {
2616
+ const location = context.node ? ParameterError$1.getCurrentLocation(context.node) : void 0;
2617
+ return new ParameterError$1({
2618
+ message: `@${context.decoratorName}('${context.propertyName}') does not exist in path '${context.path}'${location ? ` at ${location}` : ""}.`,
2619
+ code: ParameterErrorCode.PATH_MISMATCH
2620
+ });
2621
+ }
2622
+ static scopeRequired(context) {
2623
+ const location = context.node ? ParameterError$1.getCurrentLocation(context.node) : void 0;
2624
+ return new ParameterError$1({
2625
+ message: `@${context.decoratorName}() requires a scope argument${location ? ` at ${location}` : ""}.`,
2626
+ code: ParameterErrorCode.SCOPE_REQUIRED
2627
+ });
2628
+ }
2629
+ static invalidExampleSchema() {
2630
+ return new ParameterError$1({
2631
+ message: "The @example JSDoc tag contains invalid JSON.",
2632
+ code: ParameterErrorCode.INVALID_EXAMPLE
2633
+ });
2634
+ }
2635
+ static getCurrentLocation(node) {
2636
+ const parts = [];
2637
+ if (isMethodDeclaration(node.parent)) {
2638
+ parts.push(node.parent.name.getText());
2639
+ if (isClassDeclaration(node.parent.parent)) parts.unshift(node.parent.parent.name.text);
2640
+ }
2641
+ return parts.join(".");
2642
+ }
2643
+ };
2644
+ //#endregion
2645
+ //#region src/app/generator/parameter/module.ts
2646
+ const BODY_SUPPORTED_METHODS = new Set([
2647
+ "delete",
2648
+ "post",
2649
+ "put",
2650
+ "patch",
2651
+ "get"
2652
+ ]);
2653
+ const SUPPORTED_LEAF_TYPES = new Set([
2654
+ "string",
2655
+ "integer",
2656
+ "long",
2657
+ "float",
2658
+ "double",
2659
+ "date",
2660
+ "datetime",
2661
+ "buffer",
2662
+ "boolean",
2663
+ "enum"
2664
+ ]);
2665
+ var ParameterGenerator = class {
2666
+ parameter;
2667
+ method;
2668
+ paths;
2669
+ current;
2670
+ constructor(parameter, method, paths, current) {
2671
+ this.parameter = parameter;
2672
+ this.method = method;
2673
+ this.paths = paths.length === 0 ? [""] : paths;
2674
+ this.current = current;
2675
+ }
2676
+ generate() {
2677
+ const parameterName = this.getParameterName();
2678
+ const draft = newParameterDraft({ parameterName });
2679
+ const options = this.applyOptions(parameterName);
2680
+ applyDecoratorHandlers(this.parameter, this.current.registry.parameters, draft, options);
2681
+ applyJsDocHandlers(this.parameter, this.current.registry.parameterJsDoc, draft, options);
2682
+ const type = this.resolveType();
2683
+ draft.type = type;
2684
+ const description = this.getDescription();
2685
+ if (description) draft.description = description;
2686
+ if (draft.deprecated === void 0 && hasJSDocTag(this.parameter, "deprecated")) draft.deprecated = true;
2687
+ const defaultValue = getInitializerValue(this.parameter.initializer, this.current.typeChecker, type);
2688
+ if (defaultValue !== void 0) draft.default = defaultValue;
2689
+ draft.required = !this.parameter.questionToken && !this.parameter.initializer;
2690
+ const { examples, exampleLabels } = this.getJsDocExamples(parameterName);
2691
+ if (examples) {
2692
+ draft.examples = examples.map((value) => ({ value }));
2693
+ draft.exampleLabels = (exampleLabels ?? []).filter((l) => l !== void 0);
2694
+ }
2695
+ Object.assign(draft.validators, getDeclarationValidators(this.parameter, parameterName));
2696
+ if (!draft.in) {
2697
+ if (!BODY_SUPPORTED_METHODS.has(this.method)) throw ParameterError$1.methodUnsupported({
2698
+ decoratorName: "Body",
2699
+ propertyName: parameterName,
2700
+ method: this.method,
2701
+ node: this.parameter
2702
+ });
2703
+ draft.in = ParamKind.Body;
2704
+ }
2705
+ if ((draft.in === ParamKind.Body || draft.in === ParamKind.BodyProp) && !BODY_SUPPORTED_METHODS.has(this.method)) throw ParameterError$1.methodUnsupported({
2706
+ decoratorName: "Body",
2707
+ propertyName: draft.name,
2708
+ method: this.method,
2709
+ node: this.parameter
2710
+ });
2711
+ return this.finalize(draft, type, parameterName, examples, exampleLabels);
2712
+ }
2713
+ finalize(draft, type, parameterName, examples, exampleLabels) {
2714
+ const kind = draft.in;
2715
+ const wrappedExamples = examples ? examples.map((value) => ({ value })) : void 0;
2716
+ const filteredLabels = exampleLabels?.filter((l) => l !== void 0);
2717
+ if ((kind === ParameterSource.QUERY || kind === ParameterSource.PATH) && (isNestedObjectLiteralType(type) || isRefObjectType(type))) {
2718
+ const decomposed = this.decomposeObject(type, {
2719
+ in: kind === ParameterSource.QUERY ? ParameterSource.QUERY_PROP : ParameterSource.PATH,
2720
+ examples: wrappedExamples,
2721
+ exampleLabels: filteredLabels,
2722
+ extensions: draft.extensions
2723
+ });
2724
+ if (kind === ParameterSource.PATH) this.validatePathDecomposition(decomposed);
2725
+ return decomposed;
2726
+ }
2727
+ if ((kind === ParameterSource.QUERY || kind === ParameterSource.QUERY_PROP) && isArrayType(type)) {
2728
+ if (!this.isLeafTypeSupported(type.elementType)) throw ParameterError$1.typeUnsupported({
2729
+ decoratorName: kind === ParameterSource.QUERY ? "Query" : "QueryProp",
2730
+ propertyName: draft.name,
2731
+ type: type.elementType,
2732
+ node: this.parameter
2733
+ });
2734
+ return [{
2735
+ ...this.draftToParameter(draft),
2736
+ collectionFormat: draft.collectionFormat ?? CollectionFormat.MULTI,
2737
+ type
2738
+ }];
2739
+ }
2740
+ if ((kind === ParameterSource.QUERY || kind === ParameterSource.QUERY_PROP) && !this.isLeafOrEnumOrUnion(type)) throw ParameterError$1.typeUnsupported({
2741
+ decoratorName: kind === ParameterSource.QUERY ? "Query" : "QueryProp",
2742
+ propertyName: draft.name,
2743
+ type,
2744
+ node: this.parameter
2745
+ });
2746
+ if (kind === ParameterSource.PATH) this.validatePathName(draft.name, parameterName);
2747
+ return [this.draftToParameter(draft)];
2748
+ }
2749
+ draftToParameter(draft) {
2750
+ return {
2751
+ allowEmptyValue: draft.allowEmptyValue,
2752
+ collectionFormat: draft.collectionFormat,
2753
+ default: draft.default,
2754
+ description: draft.description,
2755
+ examples: draft.examples.length > 0 ? draft.examples : void 0,
2756
+ exampleLabels: draft.exampleLabels.length > 0 ? draft.exampleLabels : void 0,
2757
+ extensions: draft.extensions,
2758
+ in: draft.in,
2759
+ maxItems: draft.maxItems,
2760
+ minItems: draft.minItems,
2761
+ name: draft.name,
2762
+ parameterName: draft.parameterName,
2763
+ required: draft.required,
2764
+ type: draft.type,
2765
+ deprecated: draft.deprecated,
2766
+ validators: draft.validators
2767
+ };
2768
+ }
2769
+ decomposeObject(type, details) {
2770
+ if (type.properties.length === 0) return [];
2771
+ const parameterName = this.getParameterName();
2772
+ const initializerValue = getInitializerValue(this.parameter.initializer, this.current.typeChecker, type);
2773
+ const description = this.getDescription();
2774
+ const isParamOptional = !!this.parameter.questionToken;
2775
+ const isParamDeprecated = hasJSDocTag(this.parameter, "deprecated");
2776
+ const output = [];
2777
+ for (const property of type.properties) {
2778
+ let propertyDefaultValue = property.default;
2779
+ if (typeof propertyDefaultValue === "undefined" && isObject(initializerValue)) propertyDefaultValue = initializerValue[property.name];
2780
+ const required = isParamOptional ? false : property.required;
2781
+ output.push({
2782
+ extensions: [...details.extensions],
2783
+ in: details.in,
2784
+ examples: details.examples,
2785
+ exampleLabels: details.exampleLabels,
2786
+ default: propertyDefaultValue,
2787
+ description: property.description || description,
2788
+ name: property.name,
2789
+ parameterName,
2790
+ required,
2791
+ type: property.type,
2792
+ deprecated: property.deprecated || isParamDeprecated,
2793
+ validators: {}
2794
+ });
2795
+ }
2796
+ return output;
2797
+ }
2798
+ pathContainsParam(name) {
2799
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2800
+ const colonPattern = new RegExp(`:${escaped}\\b`);
2801
+ const bracePattern = `{${name}}`;
2802
+ for (const p of this.paths) if (p.includes(bracePattern) || colonPattern.test(p)) return true;
2803
+ return false;
2804
+ }
2805
+ validatePathDecomposition(decomposed) {
2806
+ for (const element of decomposed) if (!this.pathContainsParam(element.name)) throw ParameterError$1.invalidPathMatch({
2807
+ decoratorName: "Path",
2808
+ propertyName: element.name,
2809
+ path: this.paths.join(" | "),
2810
+ node: this.parameter
2811
+ });
2812
+ }
2813
+ validatePathName(name, parameterName) {
2814
+ const candidate = name || parameterName;
2815
+ if (!this.pathContainsParam(candidate)) throw ParameterError$1.invalidPathMatch({
2816
+ decoratorName: "Path",
2817
+ propertyName: candidate,
2818
+ path: this.paths.join(" | "),
2819
+ node: this.parameter
2820
+ });
2821
+ }
2822
+ isLeafTypeSupported(type) {
2823
+ return SUPPORTED_LEAF_TYPES.has(type.typeName);
2824
+ }
2825
+ isLeafOrEnumOrUnion(type) {
2826
+ return SUPPORTED_LEAF_TYPES.has(type.typeName) || isRefEnumType(type) || isUnionType(type);
2827
+ }
2828
+ resolveType() {
2829
+ let typeNode = this.parameter.type;
2830
+ if (!typeNode) {
2831
+ const t = this.current.typeChecker.getTypeAtLocation(this.parameter);
2832
+ typeNode = this.current.typeChecker.typeToTypeNode(t, void 0, ts.NodeBuilderFlags.NoTruncation);
2833
+ }
2834
+ if (!typeNode) throw new ParameterError$1({ message: `Could not resolve type for parameter '${this.getParameterName()}'.` });
2835
+ return new TypeNodeResolver(typeNode, this.current, this.parameter).resolve();
2836
+ }
2837
+ getParameterName() {
2838
+ if (!ts.isIdentifier(this.parameter.name)) throw new ParameterError$1({ message: "Destructured parameters are not supported. Use a simple identifier name." });
2839
+ return this.parameter.name.text;
2840
+ }
2841
+ getDescription() {
2842
+ const symbol = this.current.typeChecker.getSymbolAtLocation(this.parameter.name);
2843
+ if (symbol) {
2844
+ const comments = symbol.getDocumentationComment(this.current.typeChecker);
2845
+ if (comments.length > 0) return ts.displayPartsToString(comments);
2846
+ }
2847
+ return "";
2848
+ }
2849
+ getJsDocExamples(parameterName) {
2850
+ const exampleLabels = [];
2851
+ const examples = getJSDocTags(this.parameter.parent, (tag) => {
2852
+ const comment = transformJSDocComment(tag.comment);
2853
+ const isExample = (tag.tagName.text === "example" || tag.tagName.escapedText === "example") && !!comment && comment.startsWith(parameterName);
2854
+ if (isExample && comment) {
2855
+ const hasExampleLabel = (comment.split(" ")[0].indexOf(".") || -1) > 0;
2856
+ exampleLabels.push(hasExampleLabel ? comment.split(" ")[0].split(".").slice(1).join(".") : void 0);
2857
+ }
2858
+ return isExample ?? false;
2859
+ }).map((tag) => (transformJSDocComment(tag.comment) || "").replace(`${transformJSDocComment(tag.comment)?.split(" ")[0] || ""}`, "").replace(/\r/g, ""));
2860
+ if (examples.length === 0) return {
2861
+ examples: void 0,
2862
+ exampleLabels: void 0
2863
+ };
2864
+ try {
2865
+ return {
2866
+ examples: examples.map((example) => JSON.parse(example)),
2867
+ exampleLabels
2868
+ };
2869
+ } catch {
2870
+ throw ParameterError$1.invalidExampleSchema();
2871
+ }
2872
+ }
2873
+ applyOptions(parameterName) {
2874
+ return {
2875
+ target: "parameter",
2876
+ host: {
2877
+ name: parameterName,
2878
+ parentName: this.method
2879
+ },
2880
+ resolveTypeNode: (n) => new TypeNodeResolver(n, this.current).resolve(),
2881
+ typeChecker: this.current.typeChecker,
2882
+ parameterType: () => this.parameter.type ? new TypeNodeResolver(this.parameter.type, this.current).resolve() : void 0,
2883
+ onUnmatchedDecorator: this.current.config.strict || this.current.config.onUnmatchedDecorator ? (report) => this.current.reportUnmatchedDecorator?.(report) : void 0
2884
+ };
2885
+ }
2886
+ };
2887
+ //#endregion
2888
+ //#region src/app/generator/method/module.ts
2889
+ var MethodGenerator = class {
2890
+ node;
2891
+ current;
2892
+ constructor(node, current) {
2893
+ this.node = node;
2894
+ this.current = current;
2895
+ }
2896
+ getMethodName() {
2897
+ return this.node.name.text;
2898
+ }
2899
+ generate(controllerPaths) {
2900
+ const name = this.getMethodName();
2901
+ const draft = newMethodDraft({ name });
2902
+ const options = this.applyOptions();
2903
+ applyDecoratorHandlers(this.node, this.current.registry.methods, draft, options);
2904
+ applyJsDocHandlers(this.node, this.current.registry.methodJsDoc, draft, options);
2905
+ if (!draft.verb) return null;
2906
+ if (draft.hidden) return null;
2907
+ const returnType = this.resolveReturnType();
2908
+ const defaultResponse = buildDefaultResponse(returnType, draft.defaultResponseExamples);
2909
+ const responses = mergeDefaultResponse(draft.responses, defaultResponse);
2910
+ const parameters = this.buildParameters(controllerPaths, draft.path, draft.verb);
2911
+ const description = getJSDocDescription(this.node) ?? draft.description;
2912
+ const summary = draft.summary ?? getJSDocTagComment(this.node, "summary");
2913
+ return {
2914
+ consumes: draft.consumes,
2915
+ deprecated: draft.deprecated ?? false,
2916
+ description: description ?? "",
2917
+ extensions: draft.extensions,
2918
+ hidden: draft.hidden,
2919
+ method: draft.verb,
2920
+ name,
2921
+ path: normalizePath(draft.path),
2922
+ produces: draft.produces,
2923
+ responses,
2924
+ security: draft.security,
2925
+ summary,
2926
+ tags: draft.tags,
2927
+ type: returnType,
2928
+ parameters
2929
+ };
2930
+ }
2931
+ applyOptions() {
2932
+ const parentName = this.node.parent.name?.text;
2933
+ return {
2934
+ target: "method",
2935
+ host: {
2936
+ name: this.getMethodName(),
2937
+ parentName
2938
+ },
2939
+ resolveTypeNode: (n) => new TypeNodeResolver(n, this.current).resolve(),
2940
+ typeChecker: this.current.typeChecker,
2941
+ onUnmatchedDecorator: this.current.config.strict || this.current.config.onUnmatchedDecorator ? (report) => this.current.reportUnmatchedDecorator?.(report) : void 0
2942
+ };
2943
+ }
2944
+ resolveReturnType() {
2945
+ let nodeType = this.node.type;
2946
+ if (!nodeType) {
2947
+ const { typeChecker } = this.current;
2948
+ const signature = typeChecker.getSignatureFromDeclaration(this.node);
2949
+ const implicitType = typeChecker.getReturnTypeOfSignature(signature);
2950
+ nodeType = typeChecker.typeToTypeNode(implicitType, void 0, NodeBuilderFlags.NoTruncation);
2951
+ }
2952
+ return new TypeNodeResolver(nodeType, this.current).resolve();
2953
+ }
2954
+ buildParameters(controllerPaths, methodPath, verb) {
2955
+ const controllerId = this.node.parent.name;
2956
+ const methodId = this.node.name;
2957
+ const fullPaths = (controllerPaths.length === 0 ? [""] : controllerPaths).map((cp) => path.posix.join("/", cp, methodPath));
2958
+ const output = [];
2959
+ let bodyParameterCount = 0;
2960
+ let formParameterCount = 0;
2961
+ for (let i = 0; i < this.node.parameters.length; i++) try {
2962
+ const parameters = new ParameterGenerator(this.node.parameters[i], verb, fullPaths, this.current).generate();
2963
+ for (const parameter of parameters) {
2964
+ if (parameter.in === ParameterSource.BODY) bodyParameterCount += 1;
2965
+ if (parameter.in === ParameterSource.FORM_DATA) formParameterCount += 1;
2966
+ if (parameter.in !== ParameterSource.CONTEXT) output.push(parameter);
2967
+ }
2968
+ } catch (e) {
2969
+ const causeMsg = e instanceof Error ? `: ${e.message}` : "";
2970
+ throw new GeneratorError$1({
2971
+ message: `Parameter generation failed for '${controllerId.text}.${methodId.text}' argument index ${i}${causeMsg}`,
2972
+ code: GeneratorErrorCode$1.PARAMETER_GENERATION_FAILED,
2973
+ cause: e
2974
+ });
2975
+ }
2976
+ if (bodyParameterCount > 1) throw new GeneratorError$1({
2977
+ message: `Only one body parameter allowed in '${controllerId.text}.${methodId.text}' method.`,
2978
+ code: GeneratorErrorCode$1.BODY_PARAMETER_DUPLICATE
2979
+ });
2980
+ if (bodyParameterCount > 0 && formParameterCount > 0) throw new GeneratorError$1({
2981
+ message: `Cannot mix body and form parameters in '${controllerId.text}.${methodId.text}' method.`,
2982
+ code: GeneratorErrorCode$1.BODY_FORM_CONFLICT
2983
+ });
2984
+ return output;
2985
+ }
2986
+ };
2987
+ function buildDefaultResponse(returnType, examples) {
2988
+ const isVoid = isVoidType(returnType);
2989
+ return {
2990
+ description: isVoid ? "No content" : "Ok",
2991
+ examples,
2992
+ schema: returnType,
2993
+ status: isVoid ? "204" : "200",
2994
+ name: isVoid ? "204" : "200"
2995
+ };
2996
+ }
2997
+ function mergeDefaultResponse(handlerResponses, defaultResponse) {
2998
+ if (handlerResponses.length === 0) return [defaultResponse];
2999
+ const existing = handlerResponses.findIndex((r) => r.status === defaultResponse.status);
3000
+ if (existing >= 0) {
3001
+ const target = handlerResponses[existing];
3002
+ if (defaultResponse.examples && defaultResponse.examples.length > 0 && (!target.examples || target.examples.length === 0)) target.examples = defaultResponse.examples;
3003
+ return handlerResponses;
3004
+ }
3005
+ return [...handlerResponses, defaultResponse];
3006
+ }
3007
+ //#endregion
3008
+ //#region src/app/generator/controller/module.ts
3009
+ var ControllerGenerator = class {
3010
+ node;
3011
+ current;
3012
+ constructor(node, current) {
3013
+ this.node = node;
3014
+ this.current = current;
3015
+ }
3016
+ isValid() {
3017
+ return !!this.node.name;
3018
+ }
3019
+ generate() {
3020
+ if (!this.node.parent) throw new GeneratorError$1({
3021
+ message: "Controller node doesn't have a valid parent source file.",
3022
+ code: GeneratorErrorCode$1.CONTROLLER_NO_SOURCE_FILE
3023
+ });
3024
+ if (!this.node.name) throw new GeneratorError$1({
3025
+ message: "Controller node doesn't have a valid name.",
3026
+ code: GeneratorErrorCode$1.CONTROLLER_NO_NAME
3027
+ });
3028
+ const sourceFile = this.node.parent.getSourceFile();
3029
+ const draft = newControllerDraft({
3030
+ name: this.node.name.text,
3031
+ location: sourceFile.fileName
3032
+ });
3033
+ const options = this.applyOptions();
3034
+ applyDecoratorHandlers(this.node, this.current.registry.controllers, draft, options);
3035
+ applyJsDocHandlers(this.node, this.current.registry.controllerJsDoc, draft, options);
3036
+ if (draft.paths === void 0) return null;
3037
+ const normalized = (draft.paths.length === 0 ? [""] : draft.paths).map(normalizePath);
3038
+ const paths = [...new Set(normalized)];
3039
+ const methods = this.buildMethods(paths);
3040
+ return {
3041
+ consumes: draft.consumes,
3042
+ extensions: draft.extensions,
3043
+ hidden: draft.hidden,
3044
+ location: draft.location,
3045
+ name: draft.name,
3046
+ paths,
3047
+ produces: draft.produces,
3048
+ responses: draft.responses,
3049
+ security: draft.security,
3050
+ tags: draft.tags,
3051
+ methods
3052
+ };
3053
+ }
3054
+ applyOptions() {
3055
+ return {
3056
+ target: "class",
3057
+ host: { name: this.node.name.text },
3058
+ resolveTypeNode: (n) => new TypeNodeResolver(n, this.current).resolve(),
3059
+ typeChecker: this.current.typeChecker,
3060
+ onUnmatchedDecorator: this.current.config.strict || this.current.config.onUnmatchedDecorator ? (report) => this.current.reportUnmatchedDecorator?.(report) : void 0
3061
+ };
3062
+ }
3063
+ buildMethods(controllerPaths) {
3064
+ const set = /* @__PURE__ */ new Set();
3065
+ const output = [];
3066
+ for (const member of this.node.members) {
3067
+ if (!isMethodDeclaration(member)) continue;
3068
+ const generator = new MethodGenerator(member, this.current);
3069
+ const methodName = generator.getMethodName();
3070
+ if (set.has(methodName)) continue;
3071
+ const method = generator.generate(controllerPaths);
3072
+ if (!method) continue;
3073
+ set.add(methodName);
3074
+ output.push(method);
3075
+ }
3076
+ const inheritedMethods = this.collectInheritedMethodDeclarations(this.node);
3077
+ for (const node of inheritedMethods) {
3078
+ const generator = new MethodGenerator(node, this.current);
3079
+ const methodName = generator.getMethodName();
3080
+ if (set.has(methodName)) continue;
3081
+ try {
3082
+ const method = generator.generate(controllerPaths);
3083
+ if (!method) continue;
3084
+ set.add(methodName);
3085
+ output.push(method);
3086
+ } catch (error) {
3087
+ if (isResolverError$1(error) || isGeneratorError$1(error) && error.code === GeneratorErrorCode$1.PARAMETER_GENERATION_FAILED) continue;
3088
+ throw error;
3089
+ }
3090
+ }
3091
+ return output;
3092
+ }
3093
+ collectInheritedMethodDeclarations(node) {
3094
+ const methods = [];
3095
+ if (!node.heritageClauses) return methods;
3096
+ for (const clause of node.heritageClauses) {
3097
+ if (clause.token !== SyntaxKind.ExtendsKeyword) continue;
3098
+ for (const type of clause.types) {
3099
+ const baseDeclaration = this.resolveBaseClassDeclaration(type.expression);
3100
+ if (!baseDeclaration) continue;
3101
+ for (const member of baseDeclaration.members) if (isMethodDeclaration(member)) methods.push(member);
3102
+ methods.push(...this.collectInheritedMethodDeclarations(baseDeclaration));
3103
+ }
3104
+ }
3105
+ return methods;
3106
+ }
3107
+ resolveBaseClassDeclaration(expression) {
3108
+ let symbol = this.current.typeChecker.getSymbolAtLocation(expression);
3109
+ if (!symbol) return;
3110
+ if (symbol.flags & SymbolFlags.Alias) symbol = this.current.typeChecker.getAliasedSymbol(symbol);
3111
+ const declarations = symbol.getDeclarations();
3112
+ if (!declarations || declarations.length === 0) return;
3113
+ const declaration = declarations[0];
3114
+ if (isClassDeclaration(declaration)) return declaration;
3115
+ }
3116
+ };
3117
+ //#endregion
3118
+ //#region src/app/generator/metadata/module.ts
3119
+ var MetadataGenerator = class {
3120
+ nodes;
3121
+ typeChecker;
3122
+ registry;
3123
+ resolverCache;
3124
+ config;
3125
+ program;
3126
+ cache;
3127
+ controllers;
3128
+ referenceTypes = {};
3129
+ circularDependencyResolvers = new Array();
3130
+ unmatchedDecorators = /* @__PURE__ */ new Map();
3131
+ constructor(context) {
3132
+ this.nodes = [];
3133
+ this.config = context.options;
3134
+ this.cache = new CacheClient(context.options.cache);
3135
+ this.registry = createRegistry();
3136
+ this.resolverCache = new ResolverCache();
3137
+ this.program = createProgram(context.sourceFiles, context.compilerOptions || {});
3138
+ this.typeChecker = this.program.getTypeChecker();
3139
+ }
3140
+ async generate() {
3141
+ const sourceFilesHash = this.buildNodesFromSourceFiles();
3142
+ if (this.config.preset) this.registry = await loadRegistryByName(this.config.preset);
3143
+ const cacheKey = composeCacheKey({
3144
+ schemaVersion: "3",
3145
+ sourceFilesHash,
3146
+ compilerOptionsHash: hashCompilerOptions(this.program.getCompilerOptions()),
3147
+ registryHash: hashRegistry(this.registry),
3148
+ presetName: this.config.preset
3149
+ });
3150
+ const bypassCache = !!(this.config.strict || this.config.onUnmatchedDecorator);
3151
+ let cache = bypassCache ? void 0 : await this.cache.get(cacheKey);
3152
+ if (!cache) {
3153
+ this.buildControllers();
3154
+ this.assertPresetProducedControllers();
3155
+ this.circularDependencyResolvers.forEach((resolve) => resolve(this.referenceTypes));
3156
+ cache = {
3157
+ controllers: this.controllers,
3158
+ referenceTypes: this.referenceTypes,
3159
+ cacheKey,
3160
+ schemaVersion: "3"
3161
+ };
3162
+ if (!bypassCache) await this.cache.save(cache);
3163
+ }
3164
+ if (this.config.strict || this.config.onUnmatchedDecorator) this.dispatchUnmatchedDecoratorReports();
3165
+ return {
3166
+ controllers: cache.controllers,
3167
+ referenceTypes: cache.referenceTypes
3168
+ };
3169
+ }
3170
+ assertPresetProducedControllers() {
3171
+ if (this.config.preset || this.controllers.length > 0) return;
3172
+ if (this.nodes.length === 0) return;
3173
+ throw new ConfigError({
3174
+ message: "No preset configured and no controllers detected. Provide `preset: '@trapi/preset-decorators-express'` (or another preset) so handlers can match your decorators.",
3175
+ code: ConfigErrorCode.PRESET_MISSING
3176
+ });
3177
+ }
3178
+ reportUnmatchedDecorator(report) {
3179
+ const key = `${report.target}:${report.name}`;
3180
+ const existing = this.unmatchedDecorators.get(key);
3181
+ if (existing) {
3182
+ existing.push(report);
3183
+ return;
3184
+ }
3185
+ this.unmatchedDecorators.set(key, [report]);
3186
+ }
3187
+ dispatchUnmatchedDecoratorReports() {
3188
+ if (this.unmatchedDecorators.size === 0) return;
3189
+ const flat = [];
3190
+ for (const reports of this.unmatchedDecorators.values()) flat.push(...reports);
3191
+ if (this.config.onUnmatchedDecorator) {
3192
+ this.config.onUnmatchedDecorator(flat);
3193
+ return;
3194
+ }
3195
+ const summary = this.formatUnmatchedSummary();
3196
+ if (this.config.strict === "throw") throw new GeneratorError$1({
3197
+ message: summary,
3198
+ code: GeneratorErrorCode$1.STRICT_UNMATCHED_DECORATORS
3199
+ });
3200
+ console.warn(summary);
3201
+ }
3202
+ formatUnmatchedSummary() {
3203
+ const lines = ["[trapi] strict mode: decorators with no matching handler:"];
3204
+ for (const reports of this.unmatchedDecorators.values()) {
3205
+ const first = reports[0];
3206
+ const occurrences = reports.length;
3207
+ const location = `${first.file}:${first.line}`;
3208
+ const suffix = occurrences > 1 ? ` (${occurrences} occurrences; first at ${location})` : ` (${location})`;
3209
+ lines.push(` - @${first.name} on ${first.target} '${first.host.name}'${suffix}`);
3210
+ }
3211
+ return lines.join("\n");
3212
+ }
3213
+ buildNodesFromSourceFiles() {
3214
+ const hash = crypto.createHash("sha256");
3215
+ this.program.getSourceFiles().forEach((sf) => {
3216
+ if (this.isIgnoredPath(sf.fileName) && !this.isAllowedPath(sf.fileName)) return;
3217
+ hash.update(sf.fileName);
3218
+ hash.update("\0");
3219
+ hash.update(sf.text);
3220
+ hash.update("\0");
3221
+ forEachChild(sf, (node) => {
3222
+ if (isModuleDeclaration(node)) {
3223
+ /**
3224
+ * For some reason unknown to me, TS resolves both `declare module` and `namespace` to
3225
+ * the same kind (`ModuleDeclaration`). In order to figure out whether it's one or the other,
3226
+ * we check the node flags. They tell us whether it is a namespace or not.
3227
+ */
3228
+ if ((node.flags & NodeFlags.Namespace) === 0 && node.body && isModuleBlock(node.body)) {
3229
+ node.body.statements.forEach((statement) => {
3230
+ this.nodes.push(statement);
3231
+ });
3232
+ return;
3233
+ }
3234
+ }
3235
+ this.nodes.push(node);
3236
+ });
3237
+ });
3238
+ return hash.digest("hex");
3239
+ }
3240
+ /**
3241
+ * Check if the source file path is in the ignored path list.
3242
+ *
3243
+ * @param filePath
3244
+ * @protected
3245
+ */
3246
+ isIgnoredPath(filePath) {
3247
+ if (typeof this.config.ignore === "undefined") return false;
3248
+ return this.config.ignore.some((item) => minimatch(filePath, item));
3249
+ }
3250
+ /**
3251
+ * Check if the source file path is in the ignored path list.
3252
+ *
3253
+ * @param filePath
3254
+ * @protected
3255
+ */
3256
+ isAllowedPath(filePath) {
3257
+ if (typeof this.config.allow === "undefined") return false;
3258
+ return this.config.allow.some((item) => minimatch(filePath, item));
3259
+ }
3260
+ isExportedNode(_node) {
3261
+ return true;
3262
+ }
3263
+ addReferenceType(referenceType) {
3264
+ if (!referenceType.refName) return;
3265
+ this.referenceTypes[referenceType.refName] = referenceType;
3266
+ }
3267
+ getReferenceType(refName) {
3268
+ return this.referenceTypes[refName];
3269
+ }
3270
+ registerDependencyResolver(callback) {
3271
+ this.circularDependencyResolvers.push(callback);
3272
+ }
3273
+ buildControllers() {
3274
+ this.controllers = [];
3275
+ for (let i = 0; i < this.nodes.length; i++) {
3276
+ const node = this.nodes[i];
3277
+ if (!isClassDeclaration(node)) continue;
3278
+ const generator = new ControllerGenerator(node, this);
3279
+ if (!generator.isValid()) continue;
3280
+ const controller = generator.generate();
3281
+ if (controller) this.controllers.push(controller);
3282
+ }
3283
+ }
3284
+ };
3285
+ //#endregion
3286
+ //#region src/app/generator/metadata/utils.ts
3287
+ function isMetadata(input) {
3288
+ return isObject(input) && hasOwnProperty$1(input, "controllers") && Array.isArray(input.controllers) && hasOwnProperty$1(input, "referenceTypes") && isObject(input.referenceTypes);
3289
+ }
3290
+ //#endregion
3291
+ //#region src/app/generate.ts
3292
+ async function generateMetadata(options) {
3293
+ let compilerOptions;
3294
+ if (options.tsconfig) {
3295
+ let { tsconfig } = options;
3296
+ if (typeof tsconfig === "string") {
3297
+ tsconfig = await softLoadTsconfig({ name: tsconfig });
3298
+ compilerOptions = tsconfig.compilerOptions;
3299
+ } else compilerOptions = tsconfig.compilerOptions || {};
3300
+ }
3301
+ return new MetadataGenerator({
3302
+ sourceFiles: await scanSourceFiles(options.entryPoint),
3303
+ compilerOptions,
3304
+ options
3305
+ }).generate();
3306
+ }
3307
+ //#endregion
3308
+ export { CACHE_DEFAULT_MAX_AGE_MS, CACHE_FILE_PREFIX, CACHE_FILE_SUFFIX, CACHE_SCHEMA_VERSION, CacheClient, CollectionFormat, CollectionKind, ConfigError, ConfigErrorCode, ControllerGenerator, DecoratorArgumentKindName, DecoratorTargetKind, GeneratorError, GeneratorErrorCode, JSDocTagName, MarkerName, MetadataError, MetadataGenerator, MethodGenerator, MethodName, NumericKind, ParamKind, ParameterError, ParameterErrorCode, ParameterGenerator, ParameterSource, PrimitiveResolver, ReferenceResolver, ResolverBase, ResolverCache, ResolverError, TypeName, TypeNodeResolver, UtilityTypeName, ValidatorError, ValidatorErrorCode, ValidatorName, append, applyDecoratorHandlers, applyJsDocHandlers, buildCacheOptions, buildDecoratorArgument, buildDecoratorSources, buildHandlerContext, buildJsDocHandlerContext, buildJsDocSources, composeCacheKey, controller, controllerHandlerSchema, controllerJsDoc, controllerJsDocHandlerSchema, createPresetContainer, createRegistry, findDecoratorByName, findDecoratorsByName, flag, generateMetadata, generatePresetLookupPaths, getDeclarationValidators, getInitializerValue, getJSDoc, getJSDocDescription, getJSDocTagComment, getJSDocTagNames, getJSDocTags, getLiteralValue, getNodeDecorators, getNodeDescription, getNodeExtensions, hasDecoratorNamed, hasInitializer, hasJSDocTag, hasOwnProperty, hashCompilerOptions, hashRegistry, into, isAnyType, isArrayType, isBigintType, isBinaryType, isBooleanType, isBufferType, isByteType, isDateTimeType, isDateType, isDeprecatedMarker, isDoubleType, isEnumType, isExtensionMarker, isFileType, isFloatType, isGeneratorError, isHiddenMarker, isIntegerType, isIntersectionType, isLongType, isMetadata, isNestedObjectLiteralType, isNeverType, isObjectType, isPrimitiveType, isRefAliasType, isRefEnumType, isRefObjectType, isReferenceType, isResolverError, isStringArray, isStringType, isTupleType, isUndefinedType, isUnionType, isVoidType, jsDocMatchSchema, loadRegistry, loadRegistryByName, loadTSConfig, matchSchema, matches, matchesJsDoc, method, methodHandlerSchema, methodJsDoc, methodJsDocHandlerSchema, namesForMarker, newControllerDraft, newMethodDraft, newParameterDraft, normalizePath, numericMarkerKind, parameter, parameterHandlerSchema, parameterJsDoc, parameterJsDocHandlerSchema, presetSchema, prettyLocationOfNode, prettyTroubleCause, readNodeDecorators, resolveArrayType, resolveIndexedAccessType, resolveIntersectionType, resolveLiteralType, resolveMappedType, resolveObjectLiteralType, resolvePresetByName, resolveTupleType, resolveTypeOperatorType, resolveUnionType, scanSourceFiles, softLoadTsconfig, tagsForMarker, toTypeNodeOrFail, transformJSDocComment, validatePreset };
3309
+
3310
+ //# sourceMappingURL=index.mjs.map