@jesscss/core 2.0.0-alpha.5 → 2.0.0-alpha.6

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 (637) hide show
  1. package/lib/index.cjs +20159 -0
  2. package/lib/index.d.cts +5993 -0
  3. package/lib/index.d.cts.map +1 -0
  4. package/lib/index.d.ts +5992 -21
  5. package/lib/index.d.ts.map +1 -1
  6. package/lib/index.js +19926 -22
  7. package/lib/index.js.map +1 -1
  8. package/package.json +15 -14
  9. package/src/__tests__/define-function-record.test.ts +58 -0
  10. package/src/__tests__/define-function-simple.test.ts +55 -0
  11. package/src/__tests__/define-function-split-sequence.test.ts +547 -0
  12. package/src/__tests__/define-function-type-parity.test.ts +9 -0
  13. package/src/__tests__/define-function.test.ts +763 -0
  14. package/src/__tests__/num-operations.test.ts +91 -0
  15. package/src/__tests__/safe-parse.test.ts +374 -0
  16. package/src/context.ts +896 -0
  17. package/src/conversions.ts +282 -0
  18. package/src/debug-log.ts +29 -0
  19. package/src/define-function.ts +1006 -0
  20. package/src/deprecation.ts +67 -0
  21. package/src/globals.d.ts +26 -0
  22. package/src/index.ts +31 -0
  23. package/src/jess-error.ts +773 -0
  24. package/src/logger/deprecation-processing.ts +109 -0
  25. package/src/logger.ts +31 -0
  26. package/src/plugin.ts +292 -0
  27. package/src/tree/LOOKUP_CHAINS.md +35 -0
  28. package/src/tree/README.md +18 -0
  29. package/src/tree/__tests__/__snapshots__/extend-eval-integration.test.ts.snap +1455 -0
  30. package/src/tree/__tests__/ampersand.test.ts +382 -0
  31. package/src/tree/__tests__/at-rule.test.ts +2047 -0
  32. package/src/tree/__tests__/basic-render.test.ts +212 -0
  33. package/src/tree/__tests__/block.test.ts +40 -0
  34. package/src/tree/__tests__/call.test.ts +346 -0
  35. package/src/tree/__tests__/color.test.ts +537 -0
  36. package/src/tree/__tests__/condition.test.ts +186 -0
  37. package/src/tree/__tests__/control.test.ts +564 -0
  38. package/src/tree/__tests__/declaration.test.ts +253 -0
  39. package/src/tree/__tests__/dependency-graph.test.ts +177 -0
  40. package/src/tree/__tests__/detached-rulesets.test.ts +213 -0
  41. package/src/tree/__tests__/dimension.test.ts +236 -0
  42. package/src/tree/__tests__/expression.test.ts +73 -0
  43. package/src/tree/__tests__/ext-node.test.ts +31 -0
  44. package/src/tree/__tests__/extend-eval-integration.test.ts +1033 -0
  45. package/src/tree/__tests__/extend-import-style.test.ts +929 -0
  46. package/src/tree/__tests__/extend-less-fixtures.test.ts +851 -0
  47. package/src/tree/__tests__/extend-list.test.ts +31 -0
  48. package/src/tree/__tests__/extend-roots.test.ts +1045 -0
  49. package/src/tree/__tests__/extend-rules.test.ts +740 -0
  50. package/src/tree/__tests__/func.test.ts +171 -0
  51. package/src/tree/__tests__/import-js.test.ts +33 -0
  52. package/src/tree/__tests__/import-style-test-helpers.ts +56 -0
  53. package/src/tree/__tests__/import-style.test.ts +1967 -0
  54. package/src/tree/__tests__/interpolated-reference.test.ts +44 -0
  55. package/src/tree/__tests__/interpolated.test.ts +41 -0
  56. package/src/tree/__tests__/list.test.ts +177 -0
  57. package/src/tree/__tests__/log.test.ts +83 -0
  58. package/src/tree/__tests__/mixin-recursion.test.ts +639 -0
  59. package/src/tree/__tests__/mixin.test.ts +2171 -0
  60. package/src/tree/__tests__/negative.test.ts +45 -0
  61. package/src/tree/__tests__/nesting-collapse.test.ts +519 -0
  62. package/src/tree/__tests__/node-flags-perf.test.ts +195 -0
  63. package/src/tree/__tests__/node-flags.test.ts +410 -0
  64. package/src/tree/__tests__/node-graph.test.ts +598 -0
  65. package/src/tree/__tests__/node-mutation.test.ts +182 -0
  66. package/src/tree/__tests__/operation.test.ts +18 -0
  67. package/src/tree/__tests__/paren.test.ts +90 -0
  68. package/src/tree/__tests__/preserve-mode-output.test.ts +50 -0
  69. package/src/tree/__tests__/quoted.test.ts +72 -0
  70. package/src/tree/__tests__/range.test.ts +59 -0
  71. package/src/tree/__tests__/reference.test.ts +743 -0
  72. package/src/tree/__tests__/rest.test.ts +29 -0
  73. package/src/tree/__tests__/rules-raw.test.ts +14 -0
  74. package/src/tree/__tests__/rules.test.ts +1271 -0
  75. package/src/tree/__tests__/ruleset.test.ts +597 -0
  76. package/src/tree/__tests__/selector-attr.test.ts +50 -0
  77. package/src/tree/__tests__/selector-basic.test.ts +44 -0
  78. package/src/tree/__tests__/selector-capture.test.ts +22 -0
  79. package/src/tree/__tests__/selector-complex.test.ts +120 -0
  80. package/src/tree/__tests__/selector-compound.test.ts +74 -0
  81. package/src/tree/__tests__/selector-interpolated.test.ts +50 -0
  82. package/src/tree/__tests__/selector-list.test.ts +59 -0
  83. package/src/tree/__tests__/selector-pseudo.test.ts +23 -0
  84. package/src/tree/__tests__/selector.test.ts +182 -0
  85. package/src/tree/__tests__/sequence.test.ts +226 -0
  86. package/src/tree/__tests__/serialize-types.test.ts +529 -0
  87. package/src/tree/__tests__/spaced.test.ts +8 -0
  88. package/src/tree/__tests__/url.test.ts +72 -0
  89. package/src/tree/__tests__/var-declaration.test.ts +90 -0
  90. package/src/tree/ampersand.ts +538 -0
  91. package/src/tree/any.ts +169 -0
  92. package/src/tree/at-rule.ts +760 -0
  93. package/src/tree/block.ts +72 -0
  94. package/src/tree/bool.ts +46 -0
  95. package/src/tree/call.ts +593 -0
  96. package/src/tree/collection.ts +52 -0
  97. package/src/tree/color.ts +629 -0
  98. package/src/tree/combinator.ts +30 -0
  99. package/src/tree/comment.ts +36 -0
  100. package/src/tree/condition.ts +194 -0
  101. package/src/tree/control.ts +452 -0
  102. package/src/tree/declaration-custom.ts +56 -0
  103. package/src/tree/declaration-var.ts +87 -0
  104. package/src/tree/declaration.ts +742 -0
  105. package/src/tree/default-guard.ts +35 -0
  106. package/src/tree/dimension.ts +392 -0
  107. package/src/tree/expression.ts +97 -0
  108. package/src/tree/extend-list.ts +51 -0
  109. package/src/tree/extend.ts +391 -0
  110. package/src/tree/function.ts +254 -0
  111. package/src/tree/import-js.ts +130 -0
  112. package/src/tree/import-style.ts +875 -0
  113. package/{lib/tree/index.js → src/tree/index.ts} +49 -22
  114. package/src/tree/interpolated.ts +346 -0
  115. package/src/tree/js-array.ts +21 -0
  116. package/src/tree/js-expr.ts +50 -0
  117. package/src/tree/js-function.ts +31 -0
  118. package/src/tree/js-object.ts +22 -0
  119. package/src/tree/list.ts +415 -0
  120. package/src/tree/log.ts +89 -0
  121. package/src/tree/mixin.ts +331 -0
  122. package/src/tree/negative.ts +58 -0
  123. package/src/tree/nil.ts +57 -0
  124. package/src/tree/node-base.ts +1716 -0
  125. package/src/tree/node-type.ts +122 -0
  126. package/src/tree/node.ts +118 -0
  127. package/src/tree/number.ts +54 -0
  128. package/src/tree/operation.ts +187 -0
  129. package/src/tree/paren.ts +132 -0
  130. package/src/tree/query-condition.ts +47 -0
  131. package/src/tree/quoted.ts +119 -0
  132. package/src/tree/range.ts +101 -0
  133. package/src/tree/reference.ts +1099 -0
  134. package/src/tree/rest.ts +55 -0
  135. package/src/tree/rules-raw.ts +52 -0
  136. package/src/tree/rules.ts +2896 -0
  137. package/src/tree/ruleset.ts +1217 -0
  138. package/src/tree/selector-attr.ts +172 -0
  139. package/src/tree/selector-basic.ts +75 -0
  140. package/src/tree/selector-capture.ts +85 -0
  141. package/src/tree/selector-complex.ts +189 -0
  142. package/src/tree/selector-compound.ts +205 -0
  143. package/src/tree/selector-interpolated.ts +95 -0
  144. package/src/tree/selector-list.ts +245 -0
  145. package/src/tree/selector-pseudo.ts +173 -0
  146. package/src/tree/selector-simple.ts +10 -0
  147. package/src/tree/selector.ts +152 -0
  148. package/src/tree/sequence.ts +463 -0
  149. package/src/tree/tree.ts +130 -0
  150. package/src/tree/url.ts +95 -0
  151. package/src/tree/util/EXTEND_ARCHITECTURE_ANALYSIS.md +215 -0
  152. package/src/tree/util/EXTEND_AUDIT.md +233 -0
  153. package/src/tree/util/EXTEND_BASELINE.md +64 -0
  154. package/src/tree/util/EXTEND_CALL_GRAPH_ANALYSIS.md +244 -0
  155. package/src/tree/util/EXTEND_DOCS.md +24 -0
  156. package/src/tree/util/EXTEND_FINAL_SUMMARY.md +95 -0
  157. package/src/tree/util/EXTEND_FUNCTION_AUDIT.md +1433 -0
  158. package/src/tree/util/EXTEND_OPTIMIZATION_PLAN.md +114 -0
  159. package/src/tree/util/EXTEND_REFACTORING_SUMMARY.md +152 -0
  160. package/src/tree/util/EXTEND_RULES.md +74 -0
  161. package/src/tree/util/EXTEND_UNUSED_FUNCTIONS.md +127 -0
  162. package/src/tree/util/EXTEND_UNUSED_FUNCTIONS_ANALYSIS.md +227 -0
  163. package/src/tree/util/NODE_COPY_REDUCTION_PLAN.md +12 -0
  164. package/src/tree/util/__tests__/EXTEND_TEST_INDEX.md +59 -0
  165. package/src/tree/util/__tests__/OPTIMIZATION-ANALYSIS.md +130 -0
  166. package/src/tree/util/__tests__/WALK_AND_CONSUME_DESIGN.md +138 -0
  167. package/src/tree/util/__tests__/_archive/2026-02-09__OPTIMIZATION-ANALYSIS.md +9 -0
  168. package/src/tree/util/__tests__/_archive/README.md +4 -0
  169. package/src/tree/util/__tests__/bitset.test.ts +142 -0
  170. package/src/tree/util/__tests__/debug-log.ts +50 -0
  171. package/src/tree/util/__tests__/extend-comment-handling.test.ts +187 -0
  172. package/src/tree/util/__tests__/extend-core-unit.test.ts +941 -0
  173. package/src/tree/util/__tests__/extend-pipeline-bench.test.ts +154 -0
  174. package/src/tree/util/__tests__/extend-pipeline-bench.ts +190 -0
  175. package/src/tree/util/__tests__/fast-reject.test.ts +377 -0
  176. package/src/tree/util/__tests__/is-node.test.ts +63 -0
  177. package/src/tree/util/__tests__/list-like.test.ts +63 -0
  178. package/src/tree/util/__tests__/outputwriter.test.ts +523 -0
  179. package/src/tree/util/__tests__/print.test.ts +183 -0
  180. package/src/tree/util/__tests__/process-extends.test.ts +226 -0
  181. package/src/tree/util/__tests__/process-leading-is.test.ts +205 -0
  182. package/src/tree/util/__tests__/recursion-helper.test.ts +184 -0
  183. package/src/tree/util/__tests__/selector-match-unit.test.ts +1427 -0
  184. package/src/tree/util/__tests__/sourcemap.test.ts +117 -0
  185. package/src/tree/util/ampersand-template.ts +9 -0
  186. package/src/tree/util/bitset.ts +194 -0
  187. package/src/tree/util/calculate.ts +11 -0
  188. package/src/tree/util/cast.ts +89 -0
  189. package/src/tree/util/cloning.ts +8 -0
  190. package/src/tree/util/collections.ts +299 -0
  191. package/src/tree/util/compare.ts +90 -0
  192. package/src/tree/util/cursor.ts +171 -0
  193. package/src/tree/util/extend-core.ts +2139 -0
  194. package/src/tree/util/extend-roots.ts +1108 -0
  195. package/src/tree/util/field-helpers.ts +354 -0
  196. package/src/tree/util/is-node.ts +43 -0
  197. package/src/tree/util/list-like.ts +93 -0
  198. package/src/tree/util/mixin-instance-primitives.ts +2020 -0
  199. package/src/tree/util/print.ts +303 -0
  200. package/src/tree/util/process-leading-is.ts +421 -0
  201. package/src/tree/util/recursion-helper.ts +54 -0
  202. package/src/tree/util/regex.ts +2 -0
  203. package/src/tree/util/registry-utils.ts +1953 -0
  204. package/src/tree/util/ruleset-trace.ts +17 -0
  205. package/src/tree/util/scoped-body-eval.ts +320 -0
  206. package/src/tree/util/selector-match-core.ts +2005 -0
  207. package/src/tree/util/selector-utils.ts +757 -0
  208. package/src/tree/util/serialize-helper.ts +535 -0
  209. package/src/tree/util/serialize-types.ts +318 -0
  210. package/src/tree/util/should-operate.ts +78 -0
  211. package/src/tree/util/sourcemap.ts +37 -0
  212. package/src/types/config.ts +247 -0
  213. package/src/types/index.ts +12 -0
  214. package/{lib/types/modes.d.ts → src/types/modes.ts} +2 -1
  215. package/src/types.d.ts +9 -0
  216. package/src/types.ts +68 -0
  217. package/src/use-webpack-resolver.ts +56 -0
  218. package/src/visitor/__tests__/visitor.test.ts +136 -0
  219. package/src/visitor/index.ts +263 -0
  220. package/{lib/visitor/less-visitor.js → src/visitor/less-visitor.ts} +3 -2
  221. package/lib/context.d.ts +0 -352
  222. package/lib/context.d.ts.map +0 -1
  223. package/lib/context.js +0 -636
  224. package/lib/context.js.map +0 -1
  225. package/lib/conversions.d.ts +0 -73
  226. package/lib/conversions.d.ts.map +0 -1
  227. package/lib/conversions.js +0 -253
  228. package/lib/conversions.js.map +0 -1
  229. package/lib/debug-log.d.ts +0 -2
  230. package/lib/debug-log.d.ts.map +0 -1
  231. package/lib/debug-log.js +0 -27
  232. package/lib/debug-log.js.map +0 -1
  233. package/lib/define-function.d.ts +0 -587
  234. package/lib/define-function.d.ts.map +0 -1
  235. package/lib/define-function.js +0 -726
  236. package/lib/define-function.js.map +0 -1
  237. package/lib/deprecation.d.ts +0 -34
  238. package/lib/deprecation.d.ts.map +0 -1
  239. package/lib/deprecation.js +0 -57
  240. package/lib/deprecation.js.map +0 -1
  241. package/lib/jess-error.d.ts +0 -343
  242. package/lib/jess-error.d.ts.map +0 -1
  243. package/lib/jess-error.js +0 -508
  244. package/lib/jess-error.js.map +0 -1
  245. package/lib/logger/deprecation-processing.d.ts +0 -41
  246. package/lib/logger/deprecation-processing.d.ts.map +0 -1
  247. package/lib/logger/deprecation-processing.js +0 -81
  248. package/lib/logger/deprecation-processing.js.map +0 -1
  249. package/lib/logger.d.ts +0 -10
  250. package/lib/logger.d.ts.map +0 -1
  251. package/lib/logger.js +0 -20
  252. package/lib/logger.js.map +0 -1
  253. package/lib/plugin.d.ts +0 -94
  254. package/lib/plugin.d.ts.map +0 -1
  255. package/lib/plugin.js +0 -174
  256. package/lib/plugin.js.map +0 -1
  257. package/lib/tree/ampersand.d.ts +0 -98
  258. package/lib/tree/ampersand.d.ts.map +0 -1
  259. package/lib/tree/ampersand.js +0 -319
  260. package/lib/tree/ampersand.js.map +0 -1
  261. package/lib/tree/any.d.ts +0 -58
  262. package/lib/tree/any.d.ts.map +0 -1
  263. package/lib/tree/any.js +0 -104
  264. package/lib/tree/any.js.map +0 -1
  265. package/lib/tree/at-rule.d.ts +0 -53
  266. package/lib/tree/at-rule.d.ts.map +0 -1
  267. package/lib/tree/at-rule.js +0 -503
  268. package/lib/tree/at-rule.js.map +0 -1
  269. package/lib/tree/block.d.ts +0 -22
  270. package/lib/tree/block.d.ts.map +0 -1
  271. package/lib/tree/block.js +0 -24
  272. package/lib/tree/block.js.map +0 -1
  273. package/lib/tree/bool.d.ts +0 -18
  274. package/lib/tree/bool.d.ts.map +0 -1
  275. package/lib/tree/bool.js +0 -28
  276. package/lib/tree/bool.js.map +0 -1
  277. package/lib/tree/call.d.ts +0 -66
  278. package/lib/tree/call.d.ts.map +0 -1
  279. package/lib/tree/call.js +0 -306
  280. package/lib/tree/call.js.map +0 -1
  281. package/lib/tree/collection.d.ts +0 -30
  282. package/lib/tree/collection.d.ts.map +0 -1
  283. package/lib/tree/collection.js +0 -37
  284. package/lib/tree/collection.js.map +0 -1
  285. package/lib/tree/color.d.ts +0 -101
  286. package/lib/tree/color.d.ts.map +0 -1
  287. package/lib/tree/color.js +0 -513
  288. package/lib/tree/color.js.map +0 -1
  289. package/lib/tree/combinator.d.ts +0 -13
  290. package/lib/tree/combinator.d.ts.map +0 -1
  291. package/lib/tree/combinator.js +0 -12
  292. package/lib/tree/combinator.js.map +0 -1
  293. package/lib/tree/comment.d.ts +0 -20
  294. package/lib/tree/comment.d.ts.map +0 -1
  295. package/lib/tree/comment.js +0 -19
  296. package/lib/tree/comment.js.map +0 -1
  297. package/lib/tree/condition.d.ts +0 -31
  298. package/lib/tree/condition.d.ts.map +0 -1
  299. package/lib/tree/condition.js +0 -103
  300. package/lib/tree/condition.js.map +0 -1
  301. package/lib/tree/control.d.ts +0 -104
  302. package/lib/tree/control.d.ts.map +0 -1
  303. package/lib/tree/control.js +0 -430
  304. package/lib/tree/control.js.map +0 -1
  305. package/lib/tree/declaration-custom.d.ts +0 -18
  306. package/lib/tree/declaration-custom.d.ts.map +0 -1
  307. package/lib/tree/declaration-custom.js +0 -24
  308. package/lib/tree/declaration-custom.js.map +0 -1
  309. package/lib/tree/declaration-var.d.ts +0 -35
  310. package/lib/tree/declaration-var.d.ts.map +0 -1
  311. package/lib/tree/declaration-var.js +0 -63
  312. package/lib/tree/declaration-var.js.map +0 -1
  313. package/lib/tree/declaration.d.ts +0 -78
  314. package/lib/tree/declaration.d.ts.map +0 -1
  315. package/lib/tree/declaration.js +0 -286
  316. package/lib/tree/declaration.js.map +0 -1
  317. package/lib/tree/default-guard.d.ts +0 -15
  318. package/lib/tree/default-guard.d.ts.map +0 -1
  319. package/lib/tree/default-guard.js +0 -19
  320. package/lib/tree/default-guard.js.map +0 -1
  321. package/lib/tree/dimension.d.ts +0 -34
  322. package/lib/tree/dimension.d.ts.map +0 -1
  323. package/lib/tree/dimension.js +0 -294
  324. package/lib/tree/dimension.js.map +0 -1
  325. package/lib/tree/expression.d.ts +0 -25
  326. package/lib/tree/expression.d.ts.map +0 -1
  327. package/lib/tree/expression.js +0 -32
  328. package/lib/tree/expression.js.map +0 -1
  329. package/lib/tree/extend-list.d.ts +0 -23
  330. package/lib/tree/extend-list.d.ts.map +0 -1
  331. package/lib/tree/extend-list.js +0 -23
  332. package/lib/tree/extend-list.js.map +0 -1
  333. package/lib/tree/extend.d.ts +0 -47
  334. package/lib/tree/extend.d.ts.map +0 -1
  335. package/lib/tree/extend.js +0 -296
  336. package/lib/tree/extend.js.map +0 -1
  337. package/lib/tree/function.d.ts +0 -48
  338. package/lib/tree/function.d.ts.map +0 -1
  339. package/lib/tree/function.js +0 -74
  340. package/lib/tree/function.js.map +0 -1
  341. package/lib/tree/import-js.d.ts +0 -35
  342. package/lib/tree/import-js.d.ts.map +0 -1
  343. package/lib/tree/import-js.js +0 -45
  344. package/lib/tree/import-js.js.map +0 -1
  345. package/lib/tree/import-style.d.ts +0 -156
  346. package/lib/tree/import-style.d.ts.map +0 -1
  347. package/lib/tree/import-style.js +0 -566
  348. package/lib/tree/import-style.js.map +0 -1
  349. package/lib/tree/index.d.ts +0 -71
  350. package/lib/tree/index.d.ts.map +0 -1
  351. package/lib/tree/index.js.map +0 -1
  352. package/lib/tree/interpolated-reference.d.ts +0 -24
  353. package/lib/tree/interpolated-reference.d.ts.map +0 -1
  354. package/lib/tree/interpolated-reference.js +0 -37
  355. package/lib/tree/interpolated-reference.js.map +0 -1
  356. package/lib/tree/interpolated.d.ts +0 -62
  357. package/lib/tree/interpolated.d.ts.map +0 -1
  358. package/lib/tree/interpolated.js +0 -204
  359. package/lib/tree/interpolated.js.map +0 -1
  360. package/lib/tree/js-array.d.ts +0 -10
  361. package/lib/tree/js-array.d.ts.map +0 -1
  362. package/lib/tree/js-array.js +0 -10
  363. package/lib/tree/js-array.js.map +0 -1
  364. package/lib/tree/js-expr.d.ts +0 -23
  365. package/lib/tree/js-expr.d.ts.map +0 -1
  366. package/lib/tree/js-expr.js +0 -28
  367. package/lib/tree/js-expr.js.map +0 -1
  368. package/lib/tree/js-function.d.ts +0 -20
  369. package/lib/tree/js-function.d.ts.map +0 -1
  370. package/lib/tree/js-function.js +0 -16
  371. package/lib/tree/js-function.js.map +0 -1
  372. package/lib/tree/js-object.d.ts +0 -10
  373. package/lib/tree/js-object.d.ts.map +0 -1
  374. package/lib/tree/js-object.js +0 -10
  375. package/lib/tree/js-object.js.map +0 -1
  376. package/lib/tree/list.d.ts +0 -38
  377. package/lib/tree/list.d.ts.map +0 -1
  378. package/lib/tree/list.js +0 -83
  379. package/lib/tree/list.js.map +0 -1
  380. package/lib/tree/log.d.ts +0 -29
  381. package/lib/tree/log.d.ts.map +0 -1
  382. package/lib/tree/log.js +0 -56
  383. package/lib/tree/log.js.map +0 -1
  384. package/lib/tree/mixin.d.ts +0 -87
  385. package/lib/tree/mixin.d.ts.map +0 -1
  386. package/lib/tree/mixin.js +0 -112
  387. package/lib/tree/mixin.js.map +0 -1
  388. package/lib/tree/negative.d.ts +0 -17
  389. package/lib/tree/negative.d.ts.map +0 -1
  390. package/lib/tree/negative.js +0 -22
  391. package/lib/tree/negative.js.map +0 -1
  392. package/lib/tree/nil.d.ts +0 -30
  393. package/lib/tree/nil.d.ts.map +0 -1
  394. package/lib/tree/nil.js +0 -35
  395. package/lib/tree/nil.js.map +0 -1
  396. package/lib/tree/node-base.d.ts +0 -361
  397. package/lib/tree/node-base.d.ts.map +0 -1
  398. package/lib/tree/node-base.js +0 -930
  399. package/lib/tree/node-base.js.map +0 -1
  400. package/lib/tree/node.d.ts +0 -10
  401. package/lib/tree/node.d.ts.map +0 -1
  402. package/lib/tree/node.js +0 -45
  403. package/lib/tree/node.js.map +0 -1
  404. package/lib/tree/number.d.ts +0 -21
  405. package/lib/tree/number.d.ts.map +0 -1
  406. package/lib/tree/number.js +0 -27
  407. package/lib/tree/number.js.map +0 -1
  408. package/lib/tree/operation.d.ts +0 -26
  409. package/lib/tree/operation.d.ts.map +0 -1
  410. package/lib/tree/operation.js +0 -103
  411. package/lib/tree/operation.js.map +0 -1
  412. package/lib/tree/paren.d.ts +0 -19
  413. package/lib/tree/paren.d.ts.map +0 -1
  414. package/lib/tree/paren.js +0 -92
  415. package/lib/tree/paren.js.map +0 -1
  416. package/lib/tree/query-condition.d.ts +0 -17
  417. package/lib/tree/query-condition.d.ts.map +0 -1
  418. package/lib/tree/query-condition.js +0 -39
  419. package/lib/tree/query-condition.js.map +0 -1
  420. package/lib/tree/quoted.d.ts +0 -28
  421. package/lib/tree/quoted.d.ts.map +0 -1
  422. package/lib/tree/quoted.js +0 -75
  423. package/lib/tree/quoted.js.map +0 -1
  424. package/lib/tree/range.d.ts +0 -33
  425. package/lib/tree/range.d.ts.map +0 -1
  426. package/lib/tree/range.js +0 -47
  427. package/lib/tree/range.js.map +0 -1
  428. package/lib/tree/reference.d.ts +0 -76
  429. package/lib/tree/reference.d.ts.map +0 -1
  430. package/lib/tree/reference.js +0 -521
  431. package/lib/tree/reference.js.map +0 -1
  432. package/lib/tree/rest.d.ts +0 -15
  433. package/lib/tree/rest.d.ts.map +0 -1
  434. package/lib/tree/rest.js +0 -32
  435. package/lib/tree/rest.js.map +0 -1
  436. package/lib/tree/rules-raw.d.ts +0 -17
  437. package/lib/tree/rules-raw.d.ts.map +0 -1
  438. package/lib/tree/rules-raw.js +0 -37
  439. package/lib/tree/rules-raw.js.map +0 -1
  440. package/lib/tree/rules.d.ts +0 -262
  441. package/lib/tree/rules.d.ts.map +0 -1
  442. package/lib/tree/rules.js +0 -2359
  443. package/lib/tree/rules.js.map +0 -1
  444. package/lib/tree/ruleset.d.ts +0 -92
  445. package/lib/tree/ruleset.d.ts.map +0 -1
  446. package/lib/tree/ruleset.js +0 -528
  447. package/lib/tree/ruleset.js.map +0 -1
  448. package/lib/tree/selector-attr.d.ts +0 -31
  449. package/lib/tree/selector-attr.d.ts.map +0 -1
  450. package/lib/tree/selector-attr.js +0 -99
  451. package/lib/tree/selector-attr.js.map +0 -1
  452. package/lib/tree/selector-basic.d.ts +0 -24
  453. package/lib/tree/selector-basic.d.ts.map +0 -1
  454. package/lib/tree/selector-basic.js +0 -38
  455. package/lib/tree/selector-basic.js.map +0 -1
  456. package/lib/tree/selector-capture.d.ts +0 -23
  457. package/lib/tree/selector-capture.d.ts.map +0 -1
  458. package/lib/tree/selector-capture.js +0 -34
  459. package/lib/tree/selector-capture.js.map +0 -1
  460. package/lib/tree/selector-complex.d.ts +0 -40
  461. package/lib/tree/selector-complex.d.ts.map +0 -1
  462. package/lib/tree/selector-complex.js +0 -143
  463. package/lib/tree/selector-complex.js.map +0 -1
  464. package/lib/tree/selector-compound.d.ts +0 -16
  465. package/lib/tree/selector-compound.d.ts.map +0 -1
  466. package/lib/tree/selector-compound.js +0 -114
  467. package/lib/tree/selector-compound.js.map +0 -1
  468. package/lib/tree/selector-interpolated.d.ts +0 -23
  469. package/lib/tree/selector-interpolated.d.ts.map +0 -1
  470. package/lib/tree/selector-interpolated.js +0 -27
  471. package/lib/tree/selector-interpolated.js.map +0 -1
  472. package/lib/tree/selector-list.d.ts +0 -17
  473. package/lib/tree/selector-list.d.ts.map +0 -1
  474. package/lib/tree/selector-list.js +0 -174
  475. package/lib/tree/selector-list.js.map +0 -1
  476. package/lib/tree/selector-pseudo.d.ts +0 -42
  477. package/lib/tree/selector-pseudo.d.ts.map +0 -1
  478. package/lib/tree/selector-pseudo.js +0 -204
  479. package/lib/tree/selector-pseudo.js.map +0 -1
  480. package/lib/tree/selector-simple.d.ts +0 -5
  481. package/lib/tree/selector-simple.d.ts.map +0 -1
  482. package/lib/tree/selector-simple.js +0 -6
  483. package/lib/tree/selector-simple.js.map +0 -1
  484. package/lib/tree/selector.d.ts +0 -43
  485. package/lib/tree/selector.d.ts.map +0 -1
  486. package/lib/tree/selector.js +0 -56
  487. package/lib/tree/selector.js.map +0 -1
  488. package/lib/tree/sequence.d.ts +0 -43
  489. package/lib/tree/sequence.d.ts.map +0 -1
  490. package/lib/tree/sequence.js +0 -151
  491. package/lib/tree/sequence.js.map +0 -1
  492. package/lib/tree/tree.d.ts +0 -87
  493. package/lib/tree/tree.d.ts.map +0 -1
  494. package/lib/tree/tree.js +0 -2
  495. package/lib/tree/tree.js.map +0 -1
  496. package/lib/tree/url.d.ts +0 -18
  497. package/lib/tree/url.d.ts.map +0 -1
  498. package/lib/tree/url.js +0 -35
  499. package/lib/tree/url.js.map +0 -1
  500. package/lib/tree/util/__tests__/debug-log.d.ts +0 -1
  501. package/lib/tree/util/__tests__/debug-log.d.ts.map +0 -1
  502. package/lib/tree/util/__tests__/debug-log.js +0 -36
  503. package/lib/tree/util/__tests__/debug-log.js.map +0 -1
  504. package/lib/tree/util/calculate.d.ts +0 -3
  505. package/lib/tree/util/calculate.d.ts.map +0 -1
  506. package/lib/tree/util/calculate.js +0 -10
  507. package/lib/tree/util/calculate.js.map +0 -1
  508. package/lib/tree/util/cast.d.ts +0 -10
  509. package/lib/tree/util/cast.d.ts.map +0 -1
  510. package/lib/tree/util/cast.js +0 -87
  511. package/lib/tree/util/cast.js.map +0 -1
  512. package/lib/tree/util/cloning.d.ts +0 -4
  513. package/lib/tree/util/cloning.d.ts.map +0 -1
  514. package/lib/tree/util/cloning.js +0 -8
  515. package/lib/tree/util/cloning.js.map +0 -1
  516. package/lib/tree/util/collections.d.ts +0 -57
  517. package/lib/tree/util/collections.d.ts.map +0 -1
  518. package/lib/tree/util/collections.js +0 -136
  519. package/lib/tree/util/collections.js.map +0 -1
  520. package/lib/tree/util/compare.d.ts +0 -11
  521. package/lib/tree/util/compare.d.ts.map +0 -1
  522. package/lib/tree/util/compare.js +0 -89
  523. package/lib/tree/util/compare.js.map +0 -1
  524. package/lib/tree/util/extend-helpers.d.ts +0 -2
  525. package/lib/tree/util/extend-helpers.d.ts.map +0 -1
  526. package/lib/tree/util/extend-helpers.js +0 -2
  527. package/lib/tree/util/extend-helpers.js.map +0 -1
  528. package/lib/tree/util/extend-roots.d.ts +0 -37
  529. package/lib/tree/util/extend-roots.d.ts.map +0 -1
  530. package/lib/tree/util/extend-roots.js +0 -700
  531. package/lib/tree/util/extend-roots.js.map +0 -1
  532. package/lib/tree/util/extend-roots.old.d.ts +0 -132
  533. package/lib/tree/util/extend-roots.old.d.ts.map +0 -1
  534. package/lib/tree/util/extend-roots.old.js +0 -2272
  535. package/lib/tree/util/extend-roots.old.js.map +0 -1
  536. package/lib/tree/util/extend-trace-debug.d.ts +0 -13
  537. package/lib/tree/util/extend-trace-debug.d.ts.map +0 -1
  538. package/lib/tree/util/extend-trace-debug.js +0 -34
  539. package/lib/tree/util/extend-trace-debug.js.map +0 -1
  540. package/lib/tree/util/extend-walk.d.ts +0 -53
  541. package/lib/tree/util/extend-walk.d.ts.map +0 -1
  542. package/lib/tree/util/extend-walk.js +0 -881
  543. package/lib/tree/util/extend-walk.js.map +0 -1
  544. package/lib/tree/util/extend.d.ts +0 -218
  545. package/lib/tree/util/extend.d.ts.map +0 -1
  546. package/lib/tree/util/extend.js +0 -3182
  547. package/lib/tree/util/extend.js.map +0 -1
  548. package/lib/tree/util/find-extendable-locations.d.ts +0 -2
  549. package/lib/tree/util/find-extendable-locations.d.ts.map +0 -1
  550. package/lib/tree/util/find-extendable-locations.js +0 -2
  551. package/lib/tree/util/find-extendable-locations.js.map +0 -1
  552. package/lib/tree/util/format.d.ts +0 -20
  553. package/lib/tree/util/format.d.ts.map +0 -1
  554. package/lib/tree/util/format.js +0 -67
  555. package/lib/tree/util/format.js.map +0 -1
  556. package/lib/tree/util/is-node.d.ts +0 -13
  557. package/lib/tree/util/is-node.d.ts.map +0 -1
  558. package/lib/tree/util/is-node.js +0 -43
  559. package/lib/tree/util/is-node.js.map +0 -1
  560. package/lib/tree/util/print.d.ts +0 -80
  561. package/lib/tree/util/print.d.ts.map +0 -1
  562. package/lib/tree/util/print.js +0 -205
  563. package/lib/tree/util/print.js.map +0 -1
  564. package/lib/tree/util/process-leading-is.d.ts +0 -25
  565. package/lib/tree/util/process-leading-is.d.ts.map +0 -1
  566. package/lib/tree/util/process-leading-is.js +0 -364
  567. package/lib/tree/util/process-leading-is.js.map +0 -1
  568. package/lib/tree/util/recursion-helper.d.ts +0 -15
  569. package/lib/tree/util/recursion-helper.d.ts.map +0 -1
  570. package/lib/tree/util/recursion-helper.js +0 -43
  571. package/lib/tree/util/recursion-helper.js.map +0 -1
  572. package/lib/tree/util/regex.d.ts +0 -4
  573. package/lib/tree/util/regex.d.ts.map +0 -1
  574. package/lib/tree/util/regex.js +0 -4
  575. package/lib/tree/util/regex.js.map +0 -1
  576. package/lib/tree/util/registry-utils.d.ts +0 -192
  577. package/lib/tree/util/registry-utils.d.ts.map +0 -1
  578. package/lib/tree/util/registry-utils.js +0 -1214
  579. package/lib/tree/util/registry-utils.js.map +0 -1
  580. package/lib/tree/util/ruleset-trace.d.ts +0 -4
  581. package/lib/tree/util/ruleset-trace.d.ts.map +0 -1
  582. package/lib/tree/util/ruleset-trace.js +0 -14
  583. package/lib/tree/util/ruleset-trace.js.map +0 -1
  584. package/lib/tree/util/selector-compare.d.ts +0 -2
  585. package/lib/tree/util/selector-compare.d.ts.map +0 -1
  586. package/lib/tree/util/selector-compare.js +0 -2
  587. package/lib/tree/util/selector-compare.js.map +0 -1
  588. package/lib/tree/util/selector-match-core.d.ts +0 -184
  589. package/lib/tree/util/selector-match-core.d.ts.map +0 -1
  590. package/lib/tree/util/selector-match-core.js +0 -1603
  591. package/lib/tree/util/selector-match-core.js.map +0 -1
  592. package/lib/tree/util/selector-utils.d.ts +0 -30
  593. package/lib/tree/util/selector-utils.d.ts.map +0 -1
  594. package/lib/tree/util/selector-utils.js +0 -100
  595. package/lib/tree/util/selector-utils.js.map +0 -1
  596. package/lib/tree/util/serialize-helper.d.ts +0 -13
  597. package/lib/tree/util/serialize-helper.d.ts.map +0 -1
  598. package/lib/tree/util/serialize-helper.js +0 -387
  599. package/lib/tree/util/serialize-helper.js.map +0 -1
  600. package/lib/tree/util/serialize-types.d.ts +0 -9
  601. package/lib/tree/util/serialize-types.d.ts.map +0 -1
  602. package/lib/tree/util/serialize-types.js +0 -216
  603. package/lib/tree/util/serialize-types.js.map +0 -1
  604. package/lib/tree/util/should-operate.d.ts +0 -23
  605. package/lib/tree/util/should-operate.d.ts.map +0 -1
  606. package/lib/tree/util/should-operate.js +0 -46
  607. package/lib/tree/util/should-operate.js.map +0 -1
  608. package/lib/tree/util/sourcemap.d.ts +0 -7
  609. package/lib/tree/util/sourcemap.d.ts.map +0 -1
  610. package/lib/tree/util/sourcemap.js +0 -25
  611. package/lib/tree/util/sourcemap.js.map +0 -1
  612. package/lib/types/config.d.ts +0 -205
  613. package/lib/types/config.d.ts.map +0 -1
  614. package/lib/types/config.js +0 -2
  615. package/lib/types/config.js.map +0 -1
  616. package/lib/types/index.d.ts +0 -15
  617. package/lib/types/index.d.ts.map +0 -1
  618. package/lib/types/index.js +0 -3
  619. package/lib/types/index.js.map +0 -1
  620. package/lib/types/modes.d.ts.map +0 -1
  621. package/lib/types/modes.js +0 -2
  622. package/lib/types/modes.js.map +0 -1
  623. package/lib/types.d.ts +0 -61
  624. package/lib/types.d.ts.map +0 -1
  625. package/lib/types.js +0 -2
  626. package/lib/types.js.map +0 -1
  627. package/lib/use-webpack-resolver.d.ts +0 -9
  628. package/lib/use-webpack-resolver.d.ts.map +0 -1
  629. package/lib/use-webpack-resolver.js +0 -41
  630. package/lib/use-webpack-resolver.js.map +0 -1
  631. package/lib/visitor/index.d.ts +0 -136
  632. package/lib/visitor/index.d.ts.map +0 -1
  633. package/lib/visitor/index.js +0 -135
  634. package/lib/visitor/index.js.map +0 -1
  635. package/lib/visitor/less-visitor.d.ts +0 -7
  636. package/lib/visitor/less-visitor.d.ts.map +0 -1
  637. package/lib/visitor/less-visitor.js.map +0 -1
@@ -0,0 +1,1006 @@
1
+ import { isPlainObject } from './tree/util/collections.js';
2
+ import { AbstractClass, Class, OmitIndexSignature } from 'type-fest';
3
+ import { isNode } from './tree/util/is-node.js';
4
+ import { N } from './tree/node-type.js';
5
+ import type { Context } from './context.js';
6
+ import { isThenable } from '@jesscss/awaitable-pipe';
7
+ import type { MaybePromise } from '@jesscss/awaitable-pipe';
8
+ import { List, Sequence, Operation, Num, Dimension } from './tree/index.js';
9
+ import type { ConversionPlugin, PreprocessParams } from './conversions.js';
10
+ import { isEvaluated } from './tree/util/field-helpers.js';
11
+ import { F_STATIC } from './tree/node.js';
12
+ export type PrimitiveType = 'string' | 'number' | 'boolean' | 'null' | 'undefined';
13
+ export type ArgType = PrimitiveType | Class<any> | AbstractClass<any>;
14
+ export type Lazy<T> = () => MaybePromise<T>;
15
+
16
+ /**
17
+ * FunctionThis provides a proxy-based interface for function execution context.
18
+ *
19
+ * The `args` property is always a function that returns a `MaybePromise<List>`,
20
+ * providing a consistent API regardless of lazy parameter configuration.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const func = defineFunction('test', async function(this: FunctionThis) {
25
+ * // this.args is always a function that returns the arguments
26
+ * const evaluatedArgs = await this.args();
27
+ * return evaluatedArgs;
28
+ * }, {
29
+ * params: [
30
+ * { name: 'value', type: 'string', lazy: true }
31
+ * ]
32
+ * });
33
+ * ```
34
+ */
35
+ export type FunctionThis = {
36
+ /** The evaluation context */
37
+ context: Context;
38
+ /** The current call node that invoked this function, when available. */
39
+ caller?: Context['caller'];
40
+ /**
41
+ * The function arguments. Always returns a function that evaluates to MaybePromise<List>.
42
+ * This provides a consistent API regardless of lazy parameter configuration.
43
+ */
44
+ args: () => MaybePromise<List>;
45
+ /** The original arguments, not evaluated */
46
+ rawArgs: List;
47
+ };
48
+
49
+ export type ParamDefinition = {
50
+ name: string;
51
+ type: ArgType | readonly ArgType[];
52
+ optional?: boolean;
53
+ default?: any;
54
+ /** Marks this parameter as a variadic rest parameter. Must be the last param. */
55
+ rest?: boolean;
56
+ /** If true, provide a thunk (() => Promise<T>) to the internal positional function */
57
+ lazy?: boolean;
58
+ /** Conversion plugins to apply to the argument before passing to the function */
59
+ convert?: ConversionPlugin[];
60
+ };
61
+
62
+ export type DefineFunctionOptions = {
63
+ /**
64
+ * Parameter definitions. Can be a single array for one signature,
65
+ * or an array of arrays for function overloading (multiple signatures).
66
+ * The system will try each signature until one matches.
67
+ */
68
+ params: readonly ParamDefinition[] | readonly ParamDefinition[][];
69
+ /**
70
+ * Preprocesses the raw arguments array before parsing into a record.
71
+ * This allows transformations like splitting sequences, normalizing arguments, etc.
72
+ * Applied in order, with each preprocessor receiving the output of the previous one.
73
+ *
74
+ * @param args - The raw arguments array
75
+ * @param context - The evaluation context
76
+ * @returns The processed arguments array (can be async)
77
+ */
78
+ preprocessParams?: PreprocessParams[];
79
+ // Future options can be added here
80
+ // example?: boolean;
81
+ // validate?: boolean;
82
+ };
83
+
84
+ // Helper type to get the inferred type from ArgType
85
+ type GetArgType<T extends ArgType> =
86
+ T extends 'string'
87
+ ? string
88
+ : T extends 'number'
89
+ ? number
90
+ : T extends 'boolean'
91
+ ? boolean
92
+ : T extends 'null'
93
+ ? null
94
+ : T extends 'undefined'
95
+ ? undefined
96
+ : T extends Class<any> | AbstractClass<any>
97
+ ? InstanceType<T>
98
+ : never;
99
+
100
+ // Helper type to get the inferred type from a parameter definition, accounting for lazy
101
+ type GetParamType<T extends DefineFunctionOptions['params'][number]> =
102
+ T extends { lazy: true; type: infer A extends ArgType }
103
+ ? Lazy<GetArgType<A>>
104
+ : T extends { lazy: true; type: readonly ArgType[] }
105
+ ? Lazy<GetArgType<T['type'][number]>>
106
+ : T extends { type: infer A extends ArgType }
107
+ ? GetArgType<A>
108
+ : T extends { type: readonly ArgType[] }
109
+ ? GetArgType<T['type'][number]>
110
+ : never;
111
+
112
+ /** This should be getting only required types but it doesn't? */
113
+ type GetBaseRecordType<T extends DefineFunctionOptions['params']> = (
114
+ OmitIndexSignature<{
115
+ [K in keyof T as T[K] extends { optional: true } | { default: any }
116
+ ? never
117
+ : T[K] extends { name: infer N extends string }
118
+ ? N
119
+ : never]:
120
+ T[K] extends DefineFunctionOptions['params'][number]
121
+ ? GetParamType<T[K]>
122
+ : never;
123
+ }>
124
+ );
125
+
126
+ type GetOptionalRecordType<T extends DefineFunctionOptions['params']> = {
127
+ [K in keyof T as T[K] extends { optional: true } | { default: any }
128
+ ? T[K] extends { name: infer N extends string }
129
+ ? N
130
+ : never
131
+ : never]?:
132
+ T[K] extends { rest: true }
133
+ ? (
134
+ T[K] extends DefineFunctionOptions['params'][number]
135
+ ? GetParamType<T[K]>[]
136
+ : never
137
+ )
138
+ : (
139
+ T[K] extends DefineFunctionOptions['params'][number]
140
+ ? GetParamType<T[K]>
141
+ : never
142
+ );
143
+ };
144
+
145
+ // Get record types for named parameters
146
+ type GetRecordType<T extends DefineFunctionOptions['params']> = (
147
+ GetOptionalRecordType<T> & Omit<GetBaseRecordType<T>, keyof GetOptionalRecordType<T>>
148
+ );
149
+
150
+ type GetPositionalTypes<
151
+ T extends DefineFunctionOptions['params'],
152
+ P extends Partial<GetRecordType<DefineFunctionOptions['params']>> = Partial<GetRecordType<T>>
153
+ > = T extends readonly [infer First, ...infer Rest]
154
+ ? Rest extends DefineFunctionOptions['params']
155
+ ? First extends { optional: true } | { default: any }
156
+ ? First extends DefineFunctionOptions['params'][number]
157
+ ? [(GetParamType<First> | (P & GetRecordType<T>))?, ...GetPositionalTypes<Rest, P>]
158
+ : never
159
+ : First extends DefineFunctionOptions['params'][number]
160
+ ? [GetParamType<First> | (P & GetRecordType<T>), ...GetPositionalTypes<Rest, P>]
161
+ : never
162
+ : []
163
+ : [];
164
+
165
+ /**
166
+ * Validates that the internal function signature matches the params definition
167
+ */
168
+ type ValidateFunctionSignature<
169
+ T extends DefineFunctionOptions,
170
+ F extends (...args: any[]) => any
171
+ > = F;
172
+
173
+ export function defineFunction<
174
+ const T extends DefineFunctionOptions,
175
+ F extends (...args: any[]) => any
176
+ >(
177
+ name: string,
178
+ fn: ValidateFunctionSignature<T, F>,
179
+ options?: T
180
+ ): DefinedFunction<T, F>;
181
+
182
+ export type DefinedFunction<
183
+ T extends DefineFunctionOptions,
184
+ F extends (...args: any[]) => any
185
+ > = {
186
+ (...args: any[]): ReturnType<F>;
187
+ name: string;
188
+ params: DefineFunctionOptions['params'];
189
+ } & {
190
+ call(thisArg: any, ...args: any[]): ReturnType<F>;
191
+ apply(thisArg: any, args: any[]): ReturnType<F>;
192
+ };
193
+
194
+ export function defineFunction<
195
+ const T extends DefineFunctionOptions,
196
+ F extends (...args: any[]) => any
197
+ >(
198
+ name: string,
199
+ fn: ValidateFunctionSignature<T, F>,
200
+ options?: T
201
+ ) {
202
+ // The external API types remain exactly the same, but internal function accepts positional parameters only
203
+
204
+ type NamedFunction = DefinedFunction<T, F>;
205
+
206
+ /**
207
+ * Function that accepts either positional arguments or a record object.
208
+ * Parameter names are inferred from the params array: name, value, etc.
209
+ * All calls are converted to positional format before calling the internal function.
210
+ */
211
+ const result = function(...args: any[]): ReturnType<F> {
212
+ const rawParams = options?.params;
213
+ if (!rawParams) {
214
+ return (fn as any)(...args);
215
+ }
216
+
217
+ // Normalize params - handle overloaded signatures
218
+ const paramSignatures: ParamDefinition[][] = Array.isArray(rawParams) && rawParams.length > 0 && Array.isArray(rawParams[0])
219
+ ? rawParams.map(sig => [...sig]) as ParamDefinition[][]
220
+ : [[...(rawParams as readonly ParamDefinition[])]];
221
+
222
+ // For direct calls, use the first signature (overloading handled in callWithContext)
223
+ const params = paramSignatures[0]!;
224
+
225
+ // Validate rest parameter position
226
+ validateRestParameterPosition(params);
227
+
228
+ // Parse arguments into a record
229
+ const record = parseArgumentsToRecord(args, params);
230
+
231
+ // Apply defaults and validate
232
+ applyDefaultsAndValidate(record, params);
233
+
234
+ // Convert to positional arguments and call internal function
235
+ const positionalArgs = buildPositionalArgs(record, params);
236
+ return (fn as any)(...positionalArgs);
237
+ } as NamedFunction;
238
+
239
+ /** Allow runtime reflection on the function */
240
+ return new Proxy(result, {
241
+ has(target, prop) {
242
+ if (prop === 'name' || prop === 'options') {
243
+ return true;
244
+ }
245
+ return prop in target;
246
+ },
247
+ get(target, prop) {
248
+ if (prop === 'name') {
249
+ return name;
250
+ } else if (prop === 'options') {
251
+ return options;
252
+ } else if (prop === '_internal') {
253
+ return fn;
254
+ }
255
+ return (target as any)[prop];
256
+ }
257
+ });
258
+ }
259
+
260
+ /** This will be called internally by Jess to functions created with defineFunction */
261
+ export async function callWithContext(context: Context, fn: (...args: any[]) => any, ...args: any[]): Promise<any> {
262
+ const listArg = args.length === 1 && isNode(args[0], N.List)
263
+ ? args[0] as List
264
+ : undefined;
265
+ args = listArg ? [...listArg.get('value')] : args;
266
+ // Only reject record-based calls (plain objects) when there's no params metadata
267
+ // Collections are allowed as positional arguments even without params metadata
268
+ // (e.g., detached rulesets passed to mixins)
269
+ if (!(fn as any)?.options?.params && args.some(arg => isPlainObject(arg) && !isNode(arg))) {
270
+ throw new Error('Record-based call without params is not supported');
271
+ }
272
+
273
+ /** Normalize positional args into a List node for tracking original arguments */
274
+ const originalArgsList: List = listArg
275
+ ? listArg.clone(false)
276
+ : new List(args.map(arg => isNode(arg) ? arg.clone() : arg));
277
+
278
+ const hasParams = !!(fn as any)?.options?.params;
279
+
280
+ if (!hasParams) {
281
+ // No metadata; treat as normal positional function call (sync or async)
282
+ return (fn as any).call(context, ...args);
283
+ }
284
+
285
+ const params = (fn as any)?.options?.params as DefineFunctionOptions['params'] | undefined;
286
+ const options = (fn as any)?.options as DefineFunctionOptions | undefined;
287
+
288
+ // Apply preprocessParams if provided (e.g., for splitting sequences)
289
+ if (options?.preprocessParams && options.preprocessParams.length > 0) {
290
+ for (const preprocessor of options.preprocessParams) {
291
+ const processed = preprocessor(args, context);
292
+ if (isThenable(processed)) {
293
+ args = await processed;
294
+ } else {
295
+ args = processed;
296
+ }
297
+ }
298
+ }
299
+
300
+ // Handle function overloading: params can be an array of param arrays
301
+ // Normalize to always be an array of signatures
302
+ const paramSignatures: ParamDefinition[][] = (() => {
303
+ if (!params) {
304
+ return [];
305
+ }
306
+ // Check if params is an array of arrays (overloaded signatures)
307
+ if (Array.isArray(params) && params.length > 0 && Array.isArray(params[0])) {
308
+ return params.map(sig => [...sig]) as ParamDefinition[][];
309
+ }
310
+ // Single signature - wrap in array
311
+ return [[...(params as readonly ParamDefinition[])]];
312
+ })();
313
+
314
+ let matchedParams: readonly ParamDefinition[] | undefined;
315
+ let record: any;
316
+ let lastError: Error | undefined;
317
+
318
+ // Try each signature until one matches
319
+ for (const signature of paramSignatures) {
320
+ try {
321
+ record = parseCallWithContextArgs(args, signature);
322
+ // Try to build positional args to validate the signature matches
323
+ // We'll do a dry-run validation
324
+ const tempRecord = { ...record };
325
+ let isValid = true;
326
+
327
+ // Check if we have a record object (plain object) in args
328
+ // Collections are treated as positional arguments, not record-based calls
329
+ const hasRecordArg = args.some(arg => isPlainObject(arg));
330
+
331
+ for (let i = 0; i < signature.length; i++) {
332
+ const def = signature[i]!;
333
+ const value = tempRecord[def.name];
334
+
335
+ // Check required parameters
336
+ if (!def.optional && !def.rest && value === undefined) {
337
+ isValid = false;
338
+ break;
339
+ }
340
+
341
+ // Check if we have enough arguments (skip this check if we have a record arg)
342
+ if (!hasRecordArg && !def.rest && i >= args.length && !def.optional) {
343
+ isValid = false;
344
+ break;
345
+ }
346
+ }
347
+
348
+ // Check if we have too many arguments (not counting rest params or record args)
349
+ const hasRest = signature.some(p => p.rest);
350
+ if (!hasRest && !hasRecordArg && args.length > signature.length) {
351
+ isValid = false;
352
+ }
353
+
354
+ if (isValid) {
355
+ matchedParams = signature;
356
+ break;
357
+ }
358
+ } catch (error) {
359
+ lastError = error as Error;
360
+ continue;
361
+ }
362
+ }
363
+
364
+ // If no signature matched, throw an error
365
+ if (!matchedParams) {
366
+ if (lastError) {
367
+ throw lastError;
368
+ }
369
+ throw new Error(`No matching function signature for ${args.length} argument(s)`);
370
+ }
371
+
372
+ // Re-parse with the matched signature to ensure correct record structure
373
+ record = parseCallWithContextArgs(args, matchedParams);
374
+
375
+ /**
376
+ * Create FunctionThis proxy for function execution context.
377
+ * The args property is always a function that returns the arguments.
378
+ */
379
+ context.callStack.at(-1)?.adopt(originalArgsList);
380
+ const functionThis: FunctionThis = {
381
+ context,
382
+ args: () => originalArgsList.eval(context),
383
+ rawArgs: originalArgsList,
384
+ caller: context.caller
385
+ };
386
+
387
+ // Build positional arguments with evaluation, validation, and conversion
388
+ const positionalArgs = await buildCallWithContextPositionalArgs(record, matchedParams, context);
389
+
390
+ // Call the function with the evaluated arguments
391
+ // Mixin functions expect Context as 'this', not FunctionThis
392
+ if ((fn as any)._internal) {
393
+ return ((fn as any)._internal).call(functionThis, ...positionalArgs);
394
+ } else {
395
+ // For mixin functions and other functions that expect Context as 'this'
396
+ return (fn as any).call(context, ...positionalArgs);
397
+ }
398
+ }
399
+
400
+ // ============================================================================
401
+ // HELPER FUNCTIONS
402
+ // ============================================================================
403
+
404
+ /**
405
+ * Validates that rest parameters are in the correct position (last)
406
+ */
407
+ function validateRestParameterPosition(params: readonly ParamDefinition[]): void {
408
+ const restIndex = params.findIndex(p => p.rest);
409
+ if (restIndex >= 0 && restIndex !== params.length - 1) {
410
+ throw new Error('Rest parameter must be the last parameter');
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Applies conversion plugins to a value
416
+ */
417
+ function applyConversionPlugins(value: unknown, plugins: ConversionPlugin[]): unknown {
418
+ let result: unknown = value;
419
+
420
+ // Apply conversion plugins in sequence
421
+ for (const plugin of plugins) {
422
+ result = plugin(result);
423
+ }
424
+
425
+ return result;
426
+ }
427
+
428
+ /**
429
+ * Parses function arguments into a record object
430
+ */
431
+ function parseArgumentsToRecord(args: any[], params: readonly ParamDefinition[]): any {
432
+ const record: any = {};
433
+ const restIndex = params.findIndex(p => (p as any).rest);
434
+ const hasRest = restIndex >= 0;
435
+
436
+ // Handle pure record call (single object argument)
437
+ if (args.length === 1 && isPlainObject(args[0])) {
438
+ const isClassInstance = params?.some((opt) => {
439
+ const types = Array.isArray(opt.type) ? opt.type : [opt.type];
440
+ return types.some(type =>
441
+ typeof type === 'function' && args[0] instanceof type
442
+ );
443
+ });
444
+
445
+ if (!isClassInstance) {
446
+ const input = args[0] as any;
447
+ const isLateProxy = !!input && typeof input === 'object' && '_raw' in input;
448
+ return isLateProxy ? input._raw : { ...input };
449
+ }
450
+ }
451
+
452
+ // Handle hybrid call (positional + record)
453
+ if (args.length > 1 && isPlainObject(args[args.length - 1])) {
454
+ const positionalArgs = args.slice(0, -1);
455
+ const recordArg = args[args.length - 1];
456
+
457
+ // Set values from positional arguments
458
+ if (!hasRest) {
459
+ for (let i = 0; i < positionalArgs.length && i < (params?.length ?? 0); i++) {
460
+ const paramName = params?.[i]?.name;
461
+ if (paramName) {
462
+ record[paramName] = positionalArgs[i];
463
+ }
464
+ }
465
+ } else {
466
+ for (let i = 0; i < (params?.length ?? 0); i++) {
467
+ const def = params[i]!;
468
+ const paramName = def.name;
469
+ if ((def as any).rest) {
470
+ record[paramName] = positionalArgs.slice(i);
471
+ break;
472
+ } else if (i < positionalArgs.length) {
473
+ record[paramName] = positionalArgs[i];
474
+ }
475
+ }
476
+ }
477
+
478
+ // Override with values from record (record takes precedence)
479
+ Object.assign(record, recordArg);
480
+ return record;
481
+ }
482
+
483
+ // Handle pure positional call
484
+ if (!hasRest) {
485
+ for (let i = 0; i < Math.max(args.length, params?.length ?? 0); i++) {
486
+ const paramName = params?.[i]?.name;
487
+ if (paramName) {
488
+ if (i < args.length) {
489
+ record[paramName] = args[i];
490
+ } else if (params?.[i]?.default !== undefined) {
491
+ record[paramName] = params![i]?.default;
492
+ } else if (params?.[i]?.optional) {
493
+ record[paramName] = undefined;
494
+ }
495
+ }
496
+ }
497
+ } else {
498
+ for (let i = 0; i < (params?.length ?? 0); i++) {
499
+ const def = params[i]!;
500
+ const paramName = def.name;
501
+ if ((def as any).rest) {
502
+ record[paramName] = args.slice(i);
503
+ break;
504
+ } else if (i < args.length) {
505
+ record[paramName] = args[i];
506
+ } else if (def.default !== undefined) {
507
+ record[paramName] = def.default;
508
+ } else if (def.optional) {
509
+ record[paramName] = undefined;
510
+ }
511
+ }
512
+ }
513
+
514
+ return record;
515
+ }
516
+
517
+ /**
518
+ * Applies defaults and validates arguments
519
+ */
520
+ function applyDefaultsAndValidate(record: any, params: readonly ParamDefinition[]): void {
521
+ // Apply defaults for missing parameters
522
+ for (const paramDef of params ?? []) {
523
+ const paramName = paramDef.name;
524
+ if (record[paramName] === undefined && paramDef.default !== undefined) {
525
+ record[paramName] = paramDef.default;
526
+ }
527
+ // Normalize rest param to array
528
+ if ((paramDef as any).rest) {
529
+ const current = record[paramName];
530
+ if (current === undefined) {
531
+ record[paramName] = [];
532
+ } else if (!Array.isArray(current)) {
533
+ record[paramName] = [current];
534
+ }
535
+ }
536
+ }
537
+
538
+ validateArguments(record, params);
539
+ }
540
+
541
+ /**
542
+ * Builds positional arguments from record
543
+ */
544
+ function buildPositionalArgs(record: any, params: readonly ParamDefinition[]): any[] {
545
+ const positionalArgs: any[] = [];
546
+
547
+ for (let i = 0; i < (params?.length ?? 0); i++) {
548
+ const def = params![i]!;
549
+ const name = def.name;
550
+
551
+ if ((def as any).rest) {
552
+ const v = record[name];
553
+ const arr: any[] = Array.isArray(v) ? v : (v === undefined ? [] : [v]);
554
+ if ((def as any).lazy) {
555
+ positionalArgs.push(...arr.map(item => createThunk(item, def)));
556
+ } else {
557
+ positionalArgs.push(...arr.map((item) => {
558
+ // Apply conversion plugins if defined
559
+ if (def.convert && item instanceof Dimension) {
560
+ return applyConversionPlugins(item, def.convert);
561
+ }
562
+ return item;
563
+ }));
564
+ }
565
+ } else {
566
+ const v = record[name];
567
+ if ((def as any).lazy) {
568
+ // For optional lazy parameters, if value is undefined, pass undefined directly
569
+ // instead of creating a thunk (which would try to call undefined())
570
+ if (v === undefined && (def.optional || def.default !== undefined)) {
571
+ positionalArgs.push(undefined);
572
+ } else {
573
+ positionalArgs.push(createThunk(v, def));
574
+ }
575
+ } else {
576
+ // Apply conversion plugins if defined
577
+ if (def.convert && v instanceof Dimension) {
578
+ positionalArgs.push(applyConversionPlugins(v, def.convert));
579
+ } else {
580
+ positionalArgs.push(v);
581
+ }
582
+ }
583
+ }
584
+ }
585
+
586
+ return positionalArgs;
587
+ }
588
+
589
+ /**
590
+ * Parses callWithContext arguments into a record
591
+ */
592
+ function parseCallWithContextArgs(args: any[], params: readonly ParamDefinition[] | undefined): any {
593
+ const record: any = {};
594
+ const restIndex = params ? params.findIndex(p => (p as any).rest) : -1;
595
+ const hasRest = (restIndex ?? -1) >= 0;
596
+
597
+ if (!hasRest) {
598
+ for (let i = 0; i < Math.min(args.length, params?.length ?? 0); i++) {
599
+ let arg = args[i];
600
+ // Collections are treated as positional arguments, not record-based calls
601
+ if (isPlainObject(arg) && !isNode(arg)) {
602
+ Object.assign(record, arg);
603
+ continue;
604
+ }
605
+ const paramName = params?.[i]?.name as string;
606
+ if (!paramName) {
607
+ throw new Error('Function does not support this number of arguments');
608
+ }
609
+ record[paramName] = args[i];
610
+ }
611
+ } else {
612
+ for (let i = 0; i < (params?.length ?? 0); i++) {
613
+ const def = params![i]!;
614
+ const paramName = def.name;
615
+ const arg = args[i];
616
+ // Collections are treated as positional arguments, not record-based calls
617
+ if (isPlainObject(arg) && !isNode(arg)) {
618
+ Object.assign(record, arg);
619
+ continue;
620
+ }
621
+ if ((def as any).rest) {
622
+ record[paramName] = args.slice(i);
623
+ break;
624
+ } else {
625
+ record[paramName] = arg;
626
+ }
627
+ }
628
+ }
629
+
630
+ return record;
631
+ }
632
+
633
+ /**
634
+ * Builds positional arguments for callWithContext with evaluation
635
+ */
636
+ async function buildCallWithContextPositionalArgs(
637
+ record: any,
638
+ params: readonly ParamDefinition[] | undefined,
639
+ context: Context
640
+ ): Promise<any[]> {
641
+ const positionalArgs: any[] = [];
642
+
643
+ for (let i = 0; i < (params?.length ?? 0); i++) {
644
+ const def = params![i]!;
645
+ const name = def.name;
646
+
647
+ if ((def as any).rest) {
648
+ const v = record[name];
649
+ const arr: any[] = Array.isArray(v) ? v : (v === undefined ? [] : [v]);
650
+ if ((def as any).lazy) {
651
+ positionalArgs.push(...arr.map(item => createThunk(item, def, context)));
652
+ } else {
653
+ for (const item of arr) {
654
+ let processedItem: any = (isNode(item) && !isEvaluated(item, context)) ? (item as any).eval(context) : item;
655
+ if (isThenable(processedItem)) {
656
+ processedItem = await processedItem;
657
+ }
658
+
659
+ // Validate AFTER evaluation but BEFORE conversion
660
+ validateArgumentIfNeeded(processedItem, def, 'Argument');
661
+
662
+ // Apply conversion plugins if defined
663
+ if (def.convert && processedItem instanceof Dimension) {
664
+ processedItem = applyConversionPlugins(processedItem, def.convert);
665
+ }
666
+ positionalArgs.push(processedItem);
667
+ }
668
+ }
669
+ } else {
670
+ const v = record[name];
671
+ if ((def as any).lazy) {
672
+ // For optional lazy parameters, if value is undefined, pass undefined directly
673
+ // instead of creating a thunk (which would try to call undefined())
674
+ if (v === undefined && (def.optional || def.default !== undefined)) {
675
+ positionalArgs.push(undefined);
676
+ } else {
677
+ positionalArgs.push(createThunk(v, def, context));
678
+ }
679
+ } else {
680
+ let processedValue: any = (isNode(v) && !isEvaluated(v, context)) ? (v as any).eval(context) : v;
681
+
682
+ // Handle async evaluation without truncating remaining parameters.
683
+ if (isThenable(processedValue)) {
684
+ processedValue = await processedValue;
685
+ }
686
+
687
+ // Validate AFTER evaluation but BEFORE conversion
688
+ validateArgumentIfNeeded(processedValue, def, 'Argument');
689
+
690
+ const callerName = context.caller && isNode(context.caller, N.Call)
691
+ ? (() => {
692
+ const n = context.caller!.get('name');
693
+ return typeof n === 'string'
694
+ ? n
695
+ : (isNode(n, N.Reference) ? String(n.get('key')?.valueOf?.() ?? '') : '');
696
+ })()
697
+ : '';
698
+ // Apply conversion plugins if defined
699
+ if (def.convert && processedValue instanceof Dimension) {
700
+ processedValue = applyConversionPlugins(processedValue, def.convert);
701
+ }
702
+ positionalArgs.push(processedValue);
703
+ }
704
+ }
705
+ }
706
+
707
+ return positionalArgs;
708
+ }
709
+
710
+ /**
711
+ * Validates callWithContext arguments from record (before conversion)
712
+ */
713
+ function validateCallWithContextArgs(record: any, params: readonly ParamDefinition[] | undefined): void {
714
+ if (!params) {
715
+ return;
716
+ }
717
+
718
+ for (let i = 0; i < params.length; i++) {
719
+ const def = params[i]!;
720
+ const value = record[def.name];
721
+
722
+ // Skip validation for lazy parameters since they're passed as thunks
723
+ if ((def as any).lazy) {
724
+ continue;
725
+ }
726
+
727
+ // Skip validation for rest parameters as they're validated as arrays
728
+ if ((def as any).rest) {
729
+ continue;
730
+ }
731
+
732
+ // Skip validation for optional parameters that are undefined
733
+ if ((def as any).optional && value === undefined) {
734
+ continue;
735
+ }
736
+
737
+ validateArgument(value, def, 'Argument');
738
+ }
739
+ }
740
+
741
+ /**
742
+ * Creates a thunk function that evaluates a value and validates the result
743
+ */
744
+ function createThunk(val: any, paramDef: any, context?: Context): () => MaybePromise<any> {
745
+ // For direct calls without context, val should be the user's lazy function (e.g., () => new Dimension(...))
746
+ // NOT a thunk. We create a thunk that calls val() and validates the resolved result.
747
+ if (typeof val === 'function' && !context) {
748
+ // Create a thunk that calls val() and validates the resolved result
749
+ // Note: We validate the RESOLVED result when the thunk is called, not the function itself
750
+ return async (): Promise<any> => {
751
+ const result = await val();
752
+ // A thunk should never return a function - if it does, that's an error
753
+ // Check both typeof and instanceof Function to catch all function types
754
+ if (typeof result === 'function' || result instanceof Function) {
755
+ throw new Error(`Thunk for parameter '${paramDef?.name}' returned a function. This indicates val was already a thunk, which should never happen. Original val type: ${typeof val}, result type: ${typeof result}, result constructor: ${result?.constructor?.name}`);
756
+ }
757
+ // Validate the RESOLVED result (not the function itself)
758
+ // This is where lazy parameter validation happens - when the thunk is called and the value is resolved
759
+ // Skip validation for optional parameters that are undefined
760
+ if (paramDef && !(paramDef as any).rest && !(result === undefined && (paramDef.optional || paramDef.default !== undefined))) {
761
+ const validation = validateValue(result, paramDef.type, paramDef.name);
762
+ if (!validation.isValid) {
763
+ throw new TypeError(validation.errorMessage);
764
+ }
765
+ }
766
+ return result;
767
+ };
768
+ }
769
+
770
+ // For callWithContext path or non-function values
771
+ // If val is undefined and parameter is optional, return a thunk that returns undefined
772
+ if (val === undefined && (paramDef?.optional || paramDef?.default !== undefined)) {
773
+ return async (): Promise<any> => {
774
+ return undefined;
775
+ };
776
+ }
777
+ return async (): Promise<any> => {
778
+ let result;
779
+ if (context && isNode(val) && !isEvaluated(val, context)) {
780
+ result = await (val as any).eval(context);
781
+ if (val.hasFlag(F_STATIC) && isNode(result) && result.sourceNode === val) {
782
+ result = val;
783
+ }
784
+ } else if (typeof val === 'function') {
785
+ // If val is a function (lazy parameter), call it
786
+ result = await val();
787
+ } else {
788
+ result = val;
789
+ }
790
+
791
+ // Validate the evaluated result if we have param definition
792
+ // Note: For lazy parameters, we validate the result of calling the function, not the function itself
793
+ // Skip validation for optional parameters that are undefined
794
+ if (paramDef && !(paramDef as any).rest && !(result === undefined && (paramDef.optional || paramDef.default !== undefined))) {
795
+ const validation = validateValue(result, paramDef.type, paramDef.name);
796
+ if (!validation.isValid) {
797
+ throw new TypeError(validation.errorMessage);
798
+ }
799
+ }
800
+
801
+ return result;
802
+ };
803
+ }
804
+
805
+ /**
806
+ * Runtime validation function to check argument types and required parameters for record-based calls
807
+ */
808
+ function validateArguments(record: any, params?: readonly ParamDefinition[]) {
809
+ if (!params) {
810
+ return;
811
+ }
812
+
813
+ // Check that all required parameters are provided
814
+ for (const paramDef of params) {
815
+ const paramName = paramDef.name;
816
+ const expectedType = paramDef.type;
817
+ const isOptional = paramDef.optional || paramDef.default !== undefined;
818
+ const value = record[paramName];
819
+
820
+ // Check if required parameter is missing
821
+ if (!isOptional && value === undefined) {
822
+ throw new TypeError(`Required argument '${paramName}' is missing`);
823
+ }
824
+
825
+ // Skip validation for undefined optional arguments
826
+ if (value === undefined) {
827
+ continue;
828
+ }
829
+
830
+ // For lazy parameters, validate that it's a function (validation of result happens in thunk)
831
+ if ((paramDef as any).lazy) {
832
+ if (typeof value !== 'function') {
833
+ throw new TypeError(`Argument '${paramName}' must be a function (lazy parameter). Got: ${typeof value}`);
834
+ }
835
+ continue;
836
+ }
837
+
838
+ const isRest = (paramDef as any).rest === true;
839
+ if (isRest) {
840
+ if (!Array.isArray(value)) {
841
+ throw new TypeError(`Argument '${paramName}' must be an array (rest parameter)`);
842
+ }
843
+ const elementTypes = Array.isArray(expectedType) ? expectedType : [expectedType];
844
+ for (let idx = 0; idx < (value as any[]).length; idx++) {
845
+ const el = (value as any[])[idx];
846
+ const isValid = (Array.isArray(elementTypes) ? elementTypes : [elementTypes]).some(type => isValidType(el, type));
847
+ if (!isValid) {
848
+ const types = Array.isArray(elementTypes) ? elementTypes : [elementTypes];
849
+ const typeList = types.map((t: any) => typeof t === 'function' ? t.name : t).join(', ');
850
+ const actualType = typeof el === 'object' && el !== null ? el.constructor?.name || typeof el : typeof el;
851
+ throw new TypeError(`Element ${idx} of '${paramName}' must be of type '${typeList}'. Got: ${actualType}`);
852
+ }
853
+ }
854
+ } else {
855
+ const validation = validateValue(value, expectedType, paramName, 'Argument');
856
+ if (!validation.isValid) {
857
+ throw new TypeError(validation.errorMessage);
858
+ }
859
+ }
860
+ }
861
+ }
862
+
863
+ /**
864
+ * Centralized validation result
865
+ */
866
+ interface ValidationResult {
867
+ isValid: boolean;
868
+ errorMessage?: string;
869
+ }
870
+
871
+ /**
872
+ * Validate argument if needed (checks for lazy and undefined values)
873
+ */
874
+ function validateArgumentIfNeeded(
875
+ value: any,
876
+ def: any,
877
+ prefix: string = 'Parameter'
878
+ ): void {
879
+ if (!(def as any).lazy && value !== undefined) {
880
+ const validation = validateValue(value, def.type, def.name, prefix);
881
+ if (!validation.isValid) {
882
+ throw new TypeError(validation.errorMessage);
883
+ }
884
+ }
885
+ }
886
+
887
+ /**
888
+ * Centralized validation function
889
+ */
890
+ function validateValue(value: any, expectedType: ArgType | readonly ArgType[], paramName: string, context: string = 'Argument'): ValidationResult {
891
+ // Handle array of types (union types)
892
+ if (Array.isArray(expectedType)) {
893
+ const isValid = expectedType.some(type => isValidType(value, type));
894
+ if (!isValid) {
895
+ const typeList = expectedType.map((t: any) => typeof t === 'function' ? t.name : t).join(', ');
896
+ const actualType = typeof value === 'object' && value !== null ? value.constructor?.name || typeof value : typeof value;
897
+ return {
898
+ isValid: false,
899
+ errorMessage: `${context} '${paramName}' must be one of: ${typeList}. Got: ${actualType}`
900
+ };
901
+ }
902
+ return { isValid: true };
903
+ }
904
+
905
+ // Handle single type
906
+ if (!isValidType(value, expectedType as ArgType)) {
907
+ const typeName = typeof expectedType === 'function' ? expectedType.name : expectedType;
908
+ const actualType = typeof value === 'object' && value !== null ? value.constructor?.name || typeof value : typeof value;
909
+ return {
910
+ isValid: false,
911
+ errorMessage: `${context} '${paramName}' must be of type '${typeName}'. Got: ${actualType}`
912
+ };
913
+ }
914
+
915
+ return { isValid: true };
916
+ }
917
+
918
+ /**
919
+ * Validate array elements (for rest parameters)
920
+ */
921
+ function validateArrayElements(value: any[], elementTypes: ArgType | readonly ArgType[], paramName: string, context: string = 'Argument'): ValidationResult {
922
+ const types = Array.isArray(elementTypes) ? elementTypes : [elementTypes];
923
+
924
+ for (let idx = 0; idx < value.length; idx++) {
925
+ const el = value[idx];
926
+ const isValid = types.some(type => isValidType(el, type));
927
+ if (!isValid) {
928
+ const typeList = types.map((t: any) => typeof t === 'function' ? t.name : t).join(', ');
929
+ const actualType = typeof el === 'object' && el !== null ? el.constructor?.name || typeof el : typeof el;
930
+ return {
931
+ isValid: false,
932
+ errorMessage: `Element ${idx} of '${paramName}' must be of type '${typeList}'. Got: ${actualType}`
933
+ };
934
+ }
935
+ }
936
+
937
+ return { isValid: true };
938
+ }
939
+
940
+ /**
941
+ * Check if a value matches the expected type
942
+ */
943
+ function isValidType(value: any, expectedType: ArgType): boolean {
944
+ switch (expectedType) {
945
+ case 'string':
946
+ return typeof value === 'string';
947
+ case 'number':
948
+ return typeof value === 'number';
949
+ case 'boolean':
950
+ return typeof value === 'boolean';
951
+ case 'null':
952
+ return value === null;
953
+ case 'undefined':
954
+ return value === undefined;
955
+ default:
956
+ // Check if it's a class constructor
957
+ if (typeof expectedType === 'function') {
958
+ return value instanceof expectedType;
959
+ }
960
+ return false;
961
+ }
962
+ }
963
+
964
+ /**
965
+ * Validates a single argument against its parameter definition
966
+ */
967
+ function validateArgument(value: any, def: any, context: string = 'argument'): void {
968
+ // Skip validation for optional parameters that are undefined
969
+ if ((def as any).optional && value === undefined) {
970
+ return;
971
+ }
972
+
973
+ // For lazy parameters, validate that it's a function
974
+ if ((def as any).lazy) {
975
+ if (typeof value !== 'function') {
976
+ throw new TypeError(
977
+ `${context} '${def.name}' must be a function (lazy parameter). Got: ${typeof value}`
978
+ );
979
+ }
980
+ return;
981
+ }
982
+
983
+ // Validate rest parameters as arrays
984
+ if ((def as any).rest) {
985
+ if (!Array.isArray(value)) {
986
+ throw new TypeError(`${context} '${def.name}' must be an array (rest parameter)`);
987
+ }
988
+ const expectedType = def.type;
989
+ for (let idx = 0; idx < value.length; idx++) {
990
+ const el = value[idx];
991
+ if (!isValidType(el, expectedType as ArgType)) {
992
+ const typeName = typeof expectedType === 'function' ? expectedType.name : expectedType;
993
+ const actualType = typeof el === 'object' && el !== null ? el.constructor?.name || typeof el : typeof el;
994
+ throw new TypeError(`Element ${idx} of '${def.name}' must be of type '${typeName}'. Got: ${actualType}`);
995
+ }
996
+ }
997
+ return;
998
+ }
999
+
1000
+ // Validate regular parameters
1001
+ const expectedType = def.type;
1002
+ const validation = validateValue(value, expectedType, def.name, context);
1003
+ if (!validation.isValid) {
1004
+ throw new TypeError(validation.errorMessage);
1005
+ }
1006
+ }