@trapi/metadata 1.3.0 → 2.0.0-beta.1

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