@fluixi/compiler 1.0.0-alpha.83 → 1.0.0-alpha.85

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 (241) hide show
  1. package/dist/analyze/expr-shape.cjs +62 -1
  2. package/dist/analyze/expr-shape.d.cts +14 -0
  3. package/dist/analyze/expr-shape.d.ts +2 -2
  4. package/dist/analyze/expr-shape.js +1 -1
  5. package/dist/analyze/expr-shape.mjs +41 -1
  6. package/dist/analyze/intrinsics.cjs +80 -1
  7. package/dist/analyze/intrinsics.d.cts +66 -0
  8. package/dist/analyze/intrinsics.d.ts +7 -7
  9. package/dist/analyze/intrinsics.d.ts.map +1 -1
  10. package/dist/analyze/intrinsics.js +3 -3
  11. package/dist/analyze/intrinsics.mjs +59 -1
  12. package/dist/analyze/paren.cjs +134 -0
  13. package/dist/analyze/paren.d.cts +23 -0
  14. package/dist/analyze/paren.d.ts +24 -0
  15. package/dist/analyze/paren.d.ts.map +1 -0
  16. package/dist/analyze/paren.js +168 -0
  17. package/dist/analyze/paren.mjs +113 -0
  18. package/dist/analyze/props-destructure.cjs +226 -1
  19. package/dist/analyze/props-destructure.d.cts +83 -0
  20. package/dist/analyze/props-destructure.d.ts +3 -3
  21. package/dist/analyze/props-destructure.d.ts.map +1 -1
  22. package/dist/analyze/props-destructure.js +4 -4
  23. package/dist/analyze/props-destructure.mjs +205 -1
  24. package/dist/analyze/reactive-bindings.cjs +190 -1
  25. package/dist/analyze/reactive-bindings.d.cts +42 -0
  26. package/dist/analyze/reactive-bindings.d.ts +1 -1
  27. package/dist/analyze/reactive-bindings.js +2 -2
  28. package/dist/analyze/reactive-bindings.mjs +167 -1
  29. package/dist/analyze/reactive-expr.cjs +38 -1
  30. package/dist/analyze/reactive-expr.d.cts +38 -0
  31. package/dist/analyze/reactive-expr.d.ts +4 -4
  32. package/dist/analyze/reactive-expr.d.ts.map +1 -1
  33. package/dist/analyze/reactive-expr.js +2 -2
  34. package/dist/analyze/reactive-expr.mjs +17 -1
  35. package/dist/analyze/static-graph.cjs +811 -1
  36. package/dist/analyze/static-graph.d.cts +102 -0
  37. package/dist/analyze/static-graph.d.ts +1 -1
  38. package/dist/analyze/static-graph.d.ts.map +1 -1
  39. package/dist/analyze/static-graph.js +11 -11
  40. package/dist/analyze/static-graph.mjs +793 -1
  41. package/dist/babel-TGY76XJ7.mjs +636 -0
  42. package/dist/chunk-4PLHS2FP.mjs +158 -0
  43. package/dist/chunk-6DB5FXS4.mjs +1718 -0
  44. package/dist/chunk-F74GFKSL.mjs +16 -0
  45. package/dist/chunk-G6QC2WRJ.mjs +11 -0
  46. package/dist/chunk-RUDJDZAA.mjs +1078 -0
  47. package/dist/codegen/backend.cjs +18 -1
  48. package/dist/codegen/backend.d.cts +35 -0
  49. package/dist/codegen/backends/imperative.cjs +542 -1
  50. package/dist/codegen/backends/imperative.d.cts +11 -0
  51. package/dist/codegen/backends/imperative.d.ts +1 -1
  52. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  53. package/dist/codegen/backends/imperative.js +24 -20
  54. package/dist/codegen/backends/imperative.mjs +519 -1
  55. package/dist/codegen/contract.cjs +52 -1
  56. package/dist/codegen/contract.d.cts +24 -0
  57. package/dist/codegen/contract.d.ts +2 -2
  58. package/dist/codegen/contract.js +2 -2
  59. package/dist/codegen/contract.mjs +31 -1
  60. package/dist/codegen/partial-template.cjs +176 -1
  61. package/dist/codegen/partial-template.d.cts +61 -0
  62. package/dist/codegen/partial-template.d.ts +4 -4
  63. package/dist/codegen/partial-template.js +0 -0
  64. package/dist/codegen/partial-template.mjs +153 -1
  65. package/dist/codegen/serialize-static.cjs +125 -1
  66. package/dist/codegen/serialize-static.d.cts +38 -0
  67. package/dist/codegen/serialize-static.d.ts +3 -3
  68. package/dist/codegen/serialize-static.js +6 -6
  69. package/dist/codegen/serialize-static.mjs +104 -1
  70. package/dist/frontend/babel/build-ir-lit.cjs +1509 -1
  71. package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
  72. package/dist/frontend/babel/build-ir-lit.d.ts +2 -2
  73. package/dist/frontend/babel/build-ir-lit.mjs +1478 -1
  74. package/dist/frontend/babel/build-ir.cjs +1524 -1
  75. package/dist/frontend/babel/build-ir.d.cts +35 -0
  76. package/dist/frontend/babel/build-ir.d.ts +2 -2
  77. package/dist/frontend/babel/build-ir.js +2 -2
  78. package/dist/frontend/babel/build-ir.mjs +1495 -1
  79. package/dist/frontend/babel/index.cjs +2186 -1
  80. package/dist/frontend/babel/index.d.cts +33 -0
  81. package/dist/frontend/babel/index.d.ts +1 -1
  82. package/dist/frontend/babel/index.js +1 -1
  83. package/dist/frontend/babel/index.mjs +2156 -1
  84. package/dist/frontend/babel/lower-template.cjs +1507 -1
  85. package/dist/frontend/babel/lower-template.d.cts +23 -0
  86. package/dist/frontend/babel/lower-template.d.ts +1 -1
  87. package/dist/frontend/babel/lower-template.js +2 -2
  88. package/dist/frontend/babel/lower-template.mjs +1478 -1
  89. package/dist/frontend/babel/plugin.cjs +2132 -1
  90. package/dist/frontend/babel/plugin.d.cts +95 -0
  91. package/dist/frontend/babel/plugin.d.ts +5 -5
  92. package/dist/frontend/babel/plugin.d.ts.map +1 -1
  93. package/dist/frontend/babel/plugin.js +14 -14
  94. package/dist/frontend/babel/plugin.mjs +2103 -1
  95. package/dist/frontend/babel/server-functions.cjs +110 -1
  96. package/dist/frontend/babel/server-functions.d.cts +10 -0
  97. package/dist/frontend/babel/server-functions.mjs +89 -1
  98. package/dist/frontend/babel/types.cjs +18 -1
  99. package/dist/frontend/babel/types.d.cts +33 -0
  100. package/dist/frontend/types.cjs +18 -1
  101. package/dist/frontend/types.d.cts +25 -0
  102. package/dist/frontend/vocabulary.cjs +98 -0
  103. package/dist/frontend/vocabulary.d.cts +79 -0
  104. package/dist/frontend/vocabulary.d.ts +80 -0
  105. package/dist/frontend/vocabulary.d.ts.map +1 -0
  106. package/dist/frontend/vocabulary.js +124 -0
  107. package/dist/frontend/vocabulary.mjs +77 -0
  108. package/dist/index.cjs +1595 -14
  109. package/dist/index.d.cts +27 -0
  110. package/dist/index.d.ts +1 -1
  111. package/dist/index.js +4 -4
  112. package/dist/index.mjs +1575 -14
  113. package/dist/integrations.cjs +4312 -26
  114. package/dist/integrations.d.cts +215 -0
  115. package/dist/integrations.d.ts +9 -9
  116. package/dist/integrations.d.ts.map +1 -1
  117. package/dist/integrations.js +29 -8
  118. package/dist/integrations.mjs +536 -18
  119. package/dist/ir/nodes.cjs +18 -1
  120. package/dist/ir/nodes.d.cts +168 -0
  121. package/dist/ir/nodes.d.ts +6 -6
  122. package/dist/lower/compile-template.cjs +1356 -1
  123. package/dist/lower/compile-template.d.cts +69 -0
  124. package/dist/lower/compile-template.d.ts +3 -3
  125. package/dist/lower/compile-template.js +1 -1
  126. package/dist/lower/compile-template.mjs +1336 -1
  127. package/dist/lower/jsx.cjs +529 -1
  128. package/dist/lower/jsx.d.cts +25 -0
  129. package/dist/lower/jsx.d.ts +1 -1
  130. package/dist/lower/jsx.d.ts.map +1 -1
  131. package/dist/lower/jsx.js +6 -5
  132. package/dist/lower/jsx.mjs +506 -1
  133. package/dist/lower/template.cjs +1061 -1
  134. package/dist/lower/template.d.cts +53 -0
  135. package/dist/lower/template.d.ts +3 -3
  136. package/dist/lower/template.d.ts.map +1 -1
  137. package/dist/lower/template.js +12 -11
  138. package/dist/lower/template.mjs +1042 -1
  139. package/dist/lower/text.cjs +42 -1
  140. package/dist/lower/text.d.cts +10 -0
  141. package/dist/lower/text.d.ts +2 -2
  142. package/dist/lower/text.d.ts.map +1 -1
  143. package/dist/lower/text.js +2 -2
  144. package/dist/lower/text.mjs +21 -1
  145. package/dist/optimize/analyze-static.cjs +112 -1
  146. package/dist/optimize/analyze-static.d.cts +39 -0
  147. package/dist/optimize/analyze-static.d.ts +2 -2
  148. package/dist/optimize/analyze-static.js +2 -2
  149. package/dist/optimize/analyze-static.mjs +91 -1
  150. package/dist/optimize/collapse-strategies.cjs +90 -1
  151. package/dist/optimize/collapse-strategies.d.cts +30 -0
  152. package/dist/optimize/collapse-strategies.d.ts +3 -3
  153. package/dist/optimize/collapse-strategies.mjs +67 -1
  154. package/dist/options.cjs +33 -1
  155. package/dist/options.d.cts +39 -0
  156. package/dist/options.d.ts +2 -2
  157. package/dist/options.mjs +12 -1
  158. package/dist/resolve/builtins.cjs +73 -1
  159. package/dist/resolve/builtins.d.cts +68 -0
  160. package/dist/resolve/builtins.d.ts +8 -8
  161. package/dist/resolve/builtins.d.ts.map +1 -1
  162. package/dist/resolve/builtins.js +4 -4
  163. package/dist/resolve/builtins.mjs +53 -1
  164. package/dist/resolve/component-globals.cjs +234 -14
  165. package/dist/resolve/component-globals.d.cts +80 -0
  166. package/dist/resolve/component-globals.d.ts +5 -5
  167. package/dist/resolve/component-globals.js +10 -10
  168. package/dist/resolve/component-globals.mjs +211 -14
  169. package/dist/resolve/component-resolver.cjs +80 -1
  170. package/dist/resolve/component-resolver.d.cts +68 -0
  171. package/dist/resolve/component-resolver.d.ts +3 -3
  172. package/dist/resolve/component-resolver.d.ts.map +1 -1
  173. package/dist/resolve/component-resolver.js +3 -3
  174. package/dist/resolve/component-resolver.mjs +59 -1
  175. package/dist/resolve/load-directive.cjs +93 -1
  176. package/dist/resolve/load-directive.d.cts +53 -0
  177. package/dist/resolve/load-directive.d.ts +5 -5
  178. package/dist/resolve/load-directive.js +6 -6
  179. package/dist/resolve/load-directive.mjs +72 -1
  180. package/dist/resolve/resolve-ir.cjs +108 -1
  181. package/dist/resolve/resolve-ir.d.cts +53 -0
  182. package/dist/resolve/resolve-ir.d.ts +6 -6
  183. package/dist/resolve/resolve-ir.d.ts.map +1 -1
  184. package/dist/resolve/resolve-ir.js +1 -1
  185. package/dist/resolve/resolve-ir.mjs +85 -1
  186. package/dist/resolve/write-globals.cjs +319 -14
  187. package/dist/resolve/write-globals.d.cts +30 -0
  188. package/dist/resolve/write-globals.js +2 -2
  189. package/dist/resolve/write-globals.mjs +298 -14
  190. package/dist/server-fns-ZYWQTSZU.mjs +78 -0
  191. package/dist/server-functions-PCERFA7A.mjs +82 -0
  192. package/dist/transform/bindings.cjs +71 -1
  193. package/dist/transform/bindings.d.cts +16 -0
  194. package/dist/transform/bindings.d.ts +1 -1
  195. package/dist/transform/bindings.js +1 -1
  196. package/dist/transform/bindings.mjs +50 -1
  197. package/dist/transform/index.cjs +2732 -8
  198. package/dist/transform/index.d.cts +15 -0
  199. package/dist/transform/index.mjs +3773 -17
  200. package/dist/transform/intrinsics.cjs +216 -3
  201. package/dist/transform/intrinsics.d.cts +21 -0
  202. package/dist/transform/intrinsics.js +1 -1
  203. package/dist/transform/intrinsics.mjs +193 -3
  204. package/dist/transform/props.cjs +441 -3
  205. package/dist/transform/props.d.cts +45 -0
  206. package/dist/transform/props.d.ts +1 -1
  207. package/dist/transform/props.d.ts.map +1 -1
  208. package/dist/transform/props.js +4 -4
  209. package/dist/transform/props.mjs +1482 -12
  210. package/dist/transform/server-fn-id.cjs +35 -1
  211. package/dist/transform/server-fn-id.d.cts +9 -0
  212. package/dist/transform/server-fn-id.d.ts +1 -1
  213. package/dist/transform/server-fn-id.js +2 -2
  214. package/dist/transform/server-fn-id.mjs +14 -1
  215. package/dist/transform/server-fns.cjs +114 -2
  216. package/dist/transform/server-fns.d.cts +12 -0
  217. package/dist/transform/server-fns.js +3 -3
  218. package/dist/transform/server-fns.mjs +1155 -11
  219. package/dist/transform/source-locations.cjs +330 -1
  220. package/dist/transform/source-locations.d.cts +43 -0
  221. package/dist/transform/source-locations.d.ts +1 -1
  222. package/dist/transform/source-locations.js +5 -5
  223. package/dist/transform/source-locations.mjs +307 -1
  224. package/dist/transform/templates.cjs +2701 -7
  225. package/dist/transform/templates.d.cts +69 -0
  226. package/dist/transform/templates.d.ts +2 -2
  227. package/dist/transform/templates.d.ts.map +1 -1
  228. package/dist/transform/templates.js +7 -7
  229. package/dist/transform/templates.mjs +3743 -16
  230. package/dist/transform-RWDTQUF5.mjs +893 -0
  231. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  232. package/package.json +6 -5
  233. package/dist/babel-VXKH6MRQ.mjs +0 -1
  234. package/dist/chunk-3SAEGOMQ.mjs +0 -1
  235. package/dist/chunk-5KMMN5QP.mjs +0 -1
  236. package/dist/chunk-IBRM4W7I.mjs +0 -10
  237. package/dist/chunk-OHHZCYIQ.mjs +0 -1
  238. package/dist/chunk-YKZ54NVE.mjs +0 -1
  239. package/dist/server-fns-6QM243HC.mjs +0 -2
  240. package/dist/server-functions-E3LKCZ4R.mjs +0 -1
  241. package/dist/transform-C4ZXRVGP.mjs +0 -8
@@ -1 +1,793 @@
1
- import{parse as De}from"@babel/parser";import{parseTemplate as Me}from"@fluixi/template-parser";var L="@fluixi/reactive/signal",W={$signal:{export:"signal",module:L,returns:"signal-handle"},$memo:{export:"memo",module:L,returns:"memo-handle"},$effect:{export:"effect",module:L,returns:"effect"},$store:{export:"store",module:"@fluixi/reactive/store",returns:"store-handle"},$resource:{export:"resource",module:L,returns:"resource-handle"},$selector:{export:"createSelector",module:L,returns:"memo-accessor"},$deferred:{export:"createDeferred",module:L,returns:"memo-accessor"},$untrack:{export:"untrack",module:L,returns:"plain"},$untrackStore:{export:"untrackStore",module:"@fluixi/reactive/store",returns:"plain"}},de={signal:"signal-handle",memo:"memo-handle",effect:"effect",store:"store-handle",createSignal:["signal-accessor","signal-setter"],createMemo:"memo-accessor",createEffect:"effect",createRenderEffect:"effect",createStore:"reactive-object",resource:"resource-handle",createResource:"reactive-object",createSelector:"memo-accessor",createDeferred:"memo-accessor"},Re=["@fluixi/reactive","@fluixi/reactive/signal","@fluixi/reactive/store","@fluixi/core"],Ve=new RegExp(`\\$(?:${Object.keys(W).map(t=>t.slice(1)).join("|")})\\s*\\(`);function ue(t){return Object.prototype.hasOwnProperty.call(W,t)}function le(t){return Re.includes(t)}function T(t,i){if(t)switch(t.type){case"Identifier":i.add(t.name);return;case"ObjectPattern":for(let r of t.properties??[])r.type==="RestElement"?T(r.argument,i):T(r.value,i);return;case"ArrayPattern":for(let r of t.elements??[])T(r,i);return;case"AssignmentPattern":T(t.left,i);return;case"RestElement":T(t.argument,i);return}}function G(t,i){if(!(!t||typeof t!="object"||typeof t.type!="string")){i(t);for(let r of Object.keys(t)){if(r==="loc"||r==="leadingComments"||r==="trailingComments")continue;let e=t[r];if(Array.isArray(e))for(let o of e)G(o,i);else e&&typeof e=="object"&&G(e,i)}}}function we(t,i){if(t.type!=="CallExpression")return;let r=t.callee;if(r?.type!=="Identifier")return;let e=r.name,o=i.primitives.get(e);if(o)return o;let a=W[e];if(a&&!i.shadowed.has(e))return a.returns}function ke(t,i,r){if(Array.isArray(i)){t.type==="ArrayPattern"&&t.elements.forEach((e,o)=>{let a=i[o];e?.type==="Identifier"&&a&&r.set(e.name,a)});return}t.type==="Identifier"&&r.set(t.name,i)}function fe(t){let i={kinds:new Map,primitives:new Map,shadowed:new Set},r=t;G(r,e=>{let o=new Set;if(e.type==="VariableDeclarator")T(e.id,o);else if(e.type==="FunctionDeclaration"||e.type==="ClassDeclaration")T(e.id,o);else if(e.type==="ImportDefaultSpecifier"||e.type==="ImportNamespaceSpecifier")T(e.local,o);else if(e.type==="ImportSpecifier")T(e.local,o);else if(e.type==="FunctionExpression"||e.type==="ArrowFunctionExpression"||e.type==="FunctionDeclaration")for(let a of e.params??[])T(a,o);for(let a of o)W[a]&&i.shadowed.add(a)});for(let e of r.body??[])if(e.type==="ImportDeclaration"&&le(e.source?.value))for(let o of e.specifiers??[]){if(o.type!=="ImportSpecifier")continue;let a=o.imported,I=a.type==="Identifier"?a.name:a.value,D=de[I];D&&i.primitives.set(o.local.name,D)}return G(r,e=>{if(e.type!=="VariableDeclarator"||!e.init)return;let o=we(e.init,i);o&&ke(e.id,o,i.kinds)}),i}var H=["Show","For","Index","Switch","Match","Portal","Dynamic","ErrorBoundary"],q=["Suspense","SuspenseList","Await"],z=["Router","Outlet","Redirect","Link"],Xe=[...H,...q,...z],We=new Set([...H,...q]);var Oe={signal:"state",createSignal:"state",memo:"memo",createMemo:"memo",effect:"effect",createEffect:"effect",store:"store",createStore:"store",resource:"resource",createResource:"resource"},Te=new Set(["memo","effect","resource"]),pe=new Set([...H,...q,...z]),me={Router:"routes",Link:"href",Redirect:"to",Show:"when",Match:"when",For:"each",Index:"each",Dynamic:"component",Portal:"mount",Await:"value"},Ce=new Set(z),ge=t=>Ce.has(t)?"router":"control",Pe=new Set(["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"]);function Ae(t){return t.replace(/\\/g,"/").replace(/^\.?\/+/,"")}function M(t,i,r=[]){if(!(!t||typeof t.type!="string")){i(t,r),r.push(t);for(let e of Object.keys(t)){if(e==="loc"||e==="parent")continue;let o=t[e];if(Array.isArray(o))for(let a of o)M(a,i,r);else o&&typeof o.type=="string"&&M(o,i,r)}r.pop()}}function $e(t){let r=[...t].reverse().find(e=>e.type==="VariableDeclarator")?.id;if(r?.type==="Identifier")return r.name;if(r?.type==="ArrayPattern"){let e=r.elements?.[0];if(e?.type==="Identifier")return e.name}}function je(t){if(t.type==="FunctionDeclaration"){let i=t.id?.name;return i&&i[0]===i[0]?.toUpperCase()?i:void 0}if(t.type==="VariableDeclarator"){let i=t.id,r=t.init;if(i?.type!=="Identifier"||!r||r.type!=="ArrowFunctionExpression"&&r.type!=="FunctionExpression")return;let e=i.name;return e[0]===e[0]?.toUpperCase()?e:void 0}}function B(t){let i=new Set;return M(t,(r,e)=>{if(r.type!=="Identifier")return;let o=e[e.length-1];o?.type==="MemberExpression"&&o.property===r&&!o.computed||o?.type==="ObjectProperty"&&o.key===r&&!o.computed||i.add(r.name)}),i}function Fe(t){let i=[],r=t.quasis??[],e=t.expressions??[];return r.forEach((o,a)=>{let I=o.value;if(i.push({kind:"static",text:I?.cooked??I?.raw??"",start:o.start??0}),a<e.length){let D=e[a];i.push({kind:"hole",index:a,start:D.start??0,end:D.end??0})}}),i}function _e(t){let i=[0];for(let r=0;r<t.length;r++)t.charCodeAt(r)===10&&i.push(r+1);return r=>{let e=0,o=i.length-1;for(;e<o;){let a=e+o+1>>1;i[a]<=r?e=a:o=a-1}return{line:e+1,column:r-i[e]}}}function he(t){let i="",r=[];for(let e of t.attributes)e.kind!=="Attribute"||e.value?.kind!=="static"||(e.name==="id"?i=`#${e.value.value}`:e.name==="class"&&r.push(...String(e.value.value).split(/\s+/).filter(Boolean).slice(0,2)));return`${t.tag}${i}${r.map(e=>`.${e}`).join("")}`}function Ne(t){return t?t.kind==="hole"?[t.hole]:t.kind==="mixed"?t.parts.flatMap(i=>"hole"in i?[i.hole]:[]):[]:[]}function ye(t){let i=t.name?.name??"element",r="",e=[];for(let o of t.attributes??[]){if(o.type!=="JSXAttribute")continue;let a=o.name?.name,I=o.value;I?.type==="StringLiteral"&&(a==="id"?r=`#${I.value}`:(a==="class"||a==="className")&&e.push(...String(I.value).split(/\s+/).filter(Boolean).slice(0,2)))}return`${i}${r}${e.map(o=>`.${o}`).join("")}`}function Le(t,i){for(let r of t.attributes??[]){if(r.type!=="JSXAttribute"||r.name?.name!==i)continue;let e=r.value;return e?.type==="JSXExpressionContainer"?e.expression:void 0}}function et(t,i={}){let r=(i.routesDir??"src/routes").replace(/^\.?\/+|\/+$/g,""),e=(i.apiDir??"src/api").replace(/^\.?\/+|\/+$/g,""),o=[],a=[],I=new Map,D=new Map,F=new Map,Q=[],te=[],Y=[],Z=new Map,ne=[],re=new Map,J=0;for(let n of t){if(!/\.(tsx?|jsx?)$/.test(n.path))continue;let s;try{s=De(n.code,{sourceType:"module",plugins:["jsx","typescript"],errorRecovery:!0}).program}catch{continue}let{primitives:g,shadowed:R}=fe(s),w=new Map,A=new Map,x=new Map;D.set(n.path,w),I.set(n.path,A),F.set(n.path,x);let Se=Ae(n.path).startsWith(`${r}/`),_=new Map,xe=null,ve=()=>xe??=_e(n.code);M(s,(c,f)=>{let d=je(c),u=c.loc?.start;if(!d||!u)return;let N=J++;_.set(c,N),w.set(d,N),re.set(N,B(c)),Se&&o.push(N),a.push({node:{id:N,label:d,kind:Pe.has(d)?"handler":"component",deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:u.line,column:u.column}},reads:new Set,file:n.path})}),M(s,(c,f)=>{if(c.type==="ImportDeclaration"){let k=c.source?.value;for(let V of c.specifiers??[]){let $=V.local?.name;$&&k?.startsWith(".")&&x.set($,k)}return}if(c.type!=="CallExpression")return;let d=c.callee;if(d?.type!=="Identifier")return;let u=d.name,N=u.startsWith("$")&&ue(u)&&!R.has(u);if(!N&&!g.has(u))return;let l=Oe[N?u.slice(1):u],p=c.loc?.start;if(!l||!p)return;let y=J++,C=$e(f)??`${l}${y}`;w.set(C,y);let E;for(let k=f.length-1;k>=0;k--){let V=_.get(f[k]);if(V!==void 0){E=V;break}}a.push({node:{id:y,label:C,kind:l,deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:p.line,column:p.column},...E!==void 0?{createdIn:E}:{}},reads:Te.has(l)?B(c.arguments?.[0]):new Set,file:n.path})}),M(s,(c,f)=>{if(c.type!=="JSXOpeningElement")return;let d=c.name?.name;if(!d||d[0]!==d[0]?.toUpperCase())return;let u;for(let l=f.length-1;l>=0;l--){let p=_.get(f[l]);if(p!==void 0){u=p;break}}if(!(w.has(d)||x.has(d))&&pe.has(d)){let l=c.loc?.start;if(!l)return;let p=J++,y=me[d],C=y?Le(c,y):void 0,E=f[f.length-1];E?.type==="JSXElement"&&_.set(E,p),a.push({node:{id:p,label:d,kind:ge(d),deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:l.line,column:l.column},...u!==void 0?{createdIn:u}:{}},reads:C?B(C):new Set,file:n.path});return}u!==void 0&&Q.push({tag:d,file:n.path,owner:u})}),M(s,(c,f)=>{if(c.type!=="JSXExpressionContainer")return;let d=c.expression;if(!d||d.type==="JSXEmptyExpression")return;let u=d.loc?.start;if(!u)return;let N=f[f.length-1],l=N?.type==="JSXAttribute"?N.name?.name:void 0,p=[...f].reverse().find(E=>E.type==="JSXElement"||E.type==="JSXOpeningElement"),y=p?.type==="JSXOpeningElement"?p:p?.openingElement;if(!y)return;let C={kind:l?"attribute":"content",...l?{name:l}:{},element:ye(y),source:{file:n.path,line:u.line,column:u.column}};for(let E of B(d))Y.push({file:n.path,name:E,target:C})});let se=c=>{let f=c.openingElement??void 0,d=f?.name?.name;if(!f||!d)return;let u=c.loc?.start,N=u?{file:n.path,line:u.line,column:u.column}:void 0,l=[];for(let p of c.children??[]){if(p?.type!=="JSXElement")continue;let y=se(p);y&&l.push(y)}if(d[0]===d[0]?.toUpperCase()){let p={label:d,children:l,...N?{at:N}:{}},y=_.get(c)??w.get(d);return y!==void 0?p.owner=y:ne.push({node:p,tag:d,file:n.path}),p}return{label:ye(f),children:l,...N?{at:N}:{}}};M(s,(c,f)=>{if(c.type!=="JSXElement")return;let d;for(let l=f.length-1;l>=0;l--){let p=f[l];if(p.type==="JSXElement")return;let y=_.get(p);if(y!==void 0){d=y;break}}if(d===void 0)return;let u=se(c);if(!u)return;let N=Z.get(d);N?N.push(u):Z.set(d,[u])}),M(s,(c,f)=>{if(c.type!=="TaggedTemplateExpression")return;let d=c.tag?.name;if(d!=="html"&&d!=="svg")return;let u=c.quasi,N=u?.expressions??[],l=ve(),p;try{p=Me(Fe(u),{svg:d==="svg"}).root.children}catch{return}let y=v=>v==null?void 0:N[v],C=v=>{let m=y(v);return m?B(m):new Set},E=(v,m,b,h)=>{let S=m!==void 0?l(m):y(b)?.loc?.start??c.loc?.start;if(!S)return;let P=J++;return a.push({node:{id:P,label:v,kind:ge(v),deps:[],writes:[],runs:0,lastPulse:0,source:{file:n.path,line:S.line,column:S.column},...h!==void 0?{createdIn:h}:{}},reads:C(b),file:n.path}),P},k=(v,m,b)=>{let h=y(v),S=h?.loc?.start;if(!h||!S)return;let P={kind:b?"attribute":"content",...b?{name:b}:{},element:m,source:{file:n.path,line:S.line,column:S.column}};for(let j of B(h))Y.push({file:n.path,name:j,target:P})},V=v=>{let m=he(v);for(let b of v.attributes)switch(b.kind){case"Attribute":for(let h of Ne(b.value))k(h,m,b.name);break;case"PropertyBinding":case"BindDirective":k(b.hole,m,b.name);break;case"ClassDirective":k(b.hole,m,"class");break;case"StyleDirective":k(b.hole,m,"style");break;default:break}},$=(v,m,b)=>{for(let h of v)switch(h.kind){case"Element":{let S=h.attributes.find(O=>O.kind==="IfDirective"),P=h.attributes.find(O=>O.kind==="EachDirective"),j=m;S?.kind==="IfDirective"?j=E("Show",h.loc?.start,S.hole,m)??m:P?.kind==="EachDirective"&&(j=E("For",h.loc?.start,P.hole,m)??m),V(h),$(h.children,j,he(h));break}case"Component":{let S=h.tag,P=w.has(S)||x.has(S);if(S&&!P&&pe.has(S)){let j=me[S],O=j?h.attributes.find(ce=>"name"in ce&&ce.name===j):void 0,Ie=O&&"hole"in O?O.hole:O&&"value"in O?Ne(O.value)[0]:void 0,Ee=E(S,h.loc?.start,Ie,m);$(h.children,Ee??m,b);break}S&&m!==void 0&&Q.push({tag:S,file:n.path,owner:m}),$(h.children,m,b);break}case"Fragment":$(h.children,m,b);break;case"Expression":k(h.hole,b,void 0);break;default:break}},ae;for(let v=f.length-1;v>=0;v--){let m=_.get(f[v]);if(m!==void 0){ae=m;break}}$(p,ae,"template")}),M(s,(c,f)=>{if(c.type!=="ObjectProperty"||c.computed)return;let d=c.key?.name??c.key?.value;if(d!=="component"&&d!=="Component")return;let u=c.value;if(u?.type!=="Identifier")return;let l=[...f].reverse().find(p=>p.type==="VariableDeclarator")?.id?.name;l&&te.push({via:l,tag:u.name,file:n.path})}),M(s,c=>{if(!(c.type!=="ExportNamedDeclaration"&&c.type!=="ExportDefaultDeclaration"))for(let f of w.keys())A.set(f,w.get(f))})}let U=(n,s)=>{let g=D.get(n)?.get(s);if(g!==void 0)return g;let R=F.get(n)?.get(s);if(R)for(let[w,A]of I){if(!Ke(n,R,w))continue;let x=A.get(s);if(x!==void 0)return x}};for(let n of a){let s=new Set;for(let g of n.reads){let R=U(n.file,g);R!==void 0&&R!==n.node.id&&s.add(R)}n.node.deps=[...s]}let X=new Map;for(let n of I.values())for(let[s,g]of n)X.set(s,X.has(s)?null:g);let K=new Map(a.map(n=>[n.node.id,n.node]));for(let n of ne){let s=U(n.file,n.tag)??X.get(n.tag)??void 0;s!==void 0&&K.get(s)?.kind==="component"&&(n.node.owner=s)}for(let[n,s]of Z){let g=K.get(n);g&&s.length&&(g.dom=s)}for(let n of Y){let s=U(n.file,n.name),g=s!==void 0?K.get(s):void 0;!g||g.kind==="component"||(g.targets??=[]).push(n.target)}for(let n of te){let s=U(n.file,n.tag)??X.get(n.tag)??void 0;if(s===void 0)continue;let g=a.find(x=>x.file===n.file&&x.node.kind==="router"&&x.node.id!==s&&x.reads.has(n.via))?.node.id,R=a.find(x=>x.file===n.file&&(x.node.kind==="component"||x.node.kind==="handler")&&x.node.id!==s&&re.get(x.node.id)?.has(n.via))?.node.id,w=g??R,A=K.get(s);A&&A.createdIn===void 0&&w!==void 0&&(A.createdIn=w)}for(let n of Q){let s=U(n.file,n.tag)??X.get(n.tag)??void 0;if(s===void 0||s===n.owner)continue;let g=K.get(s);g&&g.kind==="component"&&g.createdIn===void 0&&(g.createdIn=n.owner)}let ie=(n,s)=>{let g=a.filter(R=>R.node.kind===n&&R.node.label===s);return g.length===1?g[0].node.id:void 0},ee=ie("router","Outlet")??ie("router","Router");if(ee!==void 0)for(let n of o){let s=K.get(n);s&&s.kind==="component"&&s.createdIn===void 0&&n!==ee&&(s.createdIn=ee)}let oe=a.filter(n=>n.node.kind==="handler"&&n.node.createdIn===void 0);if(oe.length>0){let n=J++;a.push({node:{id:n,label:"api",kind:"handler",deps:[],writes:[],runs:0,lastPulse:0,source:{file:e,line:1,column:0}},reads:new Set,file:e});for(let s of oe)s.node.createdIn=n}return{t:Date.now(),nodes:a.map(n=>n.node),static:!0}}var be=t=>t.replace(/\.(tsx?|jsx?|mts|cts|mjs|cjs)$/,"");function Ke(t,i,r){let e=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",o=(e?e.split("/"):[]).concat(i.split("/")),a=[];for(let F of o)F==="."||F===""||(F===".."?a.pop():a.push(F));let I=be(a.join("/")),D=be(r);return D===I||D===`${I}/index`}export{et as analyzeReactiveGraph};
1
+ /*! @fluixi/compiler v1.0.0-alpha.85 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+
3
+ // src/analyze/static-graph.ts
4
+ import { parse } from "@babel/parser";
5
+ import {
6
+ parseTemplate
7
+ } from "@fluixi/template-parser";
8
+
9
+ // src/analyze/intrinsics.ts
10
+ var REACTIVE_MODULE = "@fluixi/reactive/signal";
11
+ var INTRINSICS = {
12
+ $signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
13
+ $memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
14
+ $effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
15
+ $store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
16
+ $resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
17
+ // No short runtime form for these yet, so the intrinsic stands for the `create*`
18
+ // name. Still worth having: no import to write, and when a shorter form is
19
+ // designed, the change is this line rather than a compiler pass.
20
+ $selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
21
+ $deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
22
+ // Not value constructors, but the compiler has to know them: they change what a read
23
+ // does. `untrack` suppresses dependency collection, which is exactly the kind of thing
24
+ // dependency analysis must not guess at.
25
+ $untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
26
+ $untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
27
+ };
28
+ var RUNTIME_PRIMITIVES = {
29
+ signal: "signal-handle",
30
+ memo: "memo-handle",
31
+ effect: "effect",
32
+ store: "store-handle",
33
+ createSignal: ["signal-accessor", "signal-setter"],
34
+ createMemo: "memo-accessor",
35
+ createEffect: "effect",
36
+ createRenderEffect: "effect",
37
+ createStore: "reactive-object",
38
+ resource: "resource-handle",
39
+ createResource: "reactive-object",
40
+ createSelector: "memo-accessor",
41
+ createDeferred: "memo-accessor"
42
+ };
43
+ var PRIMITIVE_MODULES = [
44
+ "@fluixi/reactive",
45
+ "@fluixi/reactive/signal",
46
+ "@fluixi/reactive/store",
47
+ "@fluixi/core"
48
+ ];
49
+ var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
50
+ function isIntrinsicName(name) {
51
+ return Object.prototype.hasOwnProperty.call(INTRINSICS, name);
52
+ }
53
+ function isPrimitiveModule(source) {
54
+ return PRIMITIVE_MODULES.includes(source);
55
+ }
56
+
57
+ // src/analyze/reactive-bindings.ts
58
+ function patternNames(node, out) {
59
+ if (!node) return;
60
+ switch (node.type) {
61
+ case "Identifier":
62
+ out.add(node.name);
63
+ return;
64
+ case "ObjectPattern":
65
+ for (const p of node.properties ?? []) {
66
+ if (p.type === "RestElement") patternNames(p.argument, out);
67
+ else patternNames(p.value, out);
68
+ }
69
+ return;
70
+ case "ArrayPattern":
71
+ for (const e of node.elements ?? []) patternNames(e, out);
72
+ return;
73
+ case "AssignmentPattern":
74
+ patternNames(node.left, out);
75
+ return;
76
+ case "RestElement":
77
+ patternNames(node.argument, out);
78
+ return;
79
+ }
80
+ }
81
+ function walk(root, visit) {
82
+ if (!root || typeof root !== "object" || typeof root.type !== "string") return;
83
+ visit(root);
84
+ for (const key of Object.keys(root)) {
85
+ if (key === "loc" || key === "leadingComments" || key === "trailingComments") continue;
86
+ const value = root[key];
87
+ if (Array.isArray(value)) for (const item of value) walk(item, visit);
88
+ else if (value && typeof value === "object") walk(value, visit);
89
+ }
90
+ }
91
+ function calledPrimitive(node, bindings) {
92
+ if (node.type !== "CallExpression") return void 0;
93
+ const callee = node.callee;
94
+ if (callee?.type !== "Identifier") return void 0;
95
+ const name = callee.name;
96
+ const imported = bindings.primitives.get(name);
97
+ if (imported) return imported;
98
+ const intrinsic = INTRINSICS[name];
99
+ if (intrinsic && !bindings.shadowed.has(name)) return intrinsic.returns;
100
+ return void 0;
101
+ }
102
+ function classify(id, returns, kinds) {
103
+ if (Array.isArray(returns)) {
104
+ if (id.type === "ArrayPattern") {
105
+ id.elements.forEach((element, index) => {
106
+ const kind = returns[index];
107
+ if (element?.type === "Identifier" && kind) kinds.set(element.name, kind);
108
+ });
109
+ }
110
+ return;
111
+ }
112
+ if (id.type === "Identifier") kinds.set(id.name, returns);
113
+ }
114
+ function resolveReactiveBindings(program) {
115
+ const bindings = { kinds: /* @__PURE__ */ new Map(), primitives: /* @__PURE__ */ new Map(), shadowed: /* @__PURE__ */ new Set() };
116
+ const root = program;
117
+ walk(root, (node) => {
118
+ const names = /* @__PURE__ */ new Set();
119
+ if (node.type === "VariableDeclarator") patternNames(node.id, names);
120
+ else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") patternNames(node.id, names);
121
+ else if (node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier") patternNames(node.local, names);
122
+ else if (node.type === "ImportSpecifier") patternNames(node.local, names);
123
+ else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration") {
124
+ for (const p of node.params ?? []) patternNames(p, names);
125
+ }
126
+ for (const name of names) if (INTRINSICS[name]) bindings.shadowed.add(name);
127
+ });
128
+ for (const statement of root.body ?? []) {
129
+ if (statement.type !== "ImportDeclaration") continue;
130
+ if (!isPrimitiveModule(statement.source?.value)) continue;
131
+ for (const specifier of statement.specifiers ?? []) {
132
+ if (specifier.type !== "ImportSpecifier") continue;
133
+ const importedNode = specifier.imported;
134
+ const imported = importedNode.type === "Identifier" ? importedNode.name : importedNode.value;
135
+ const returns = RUNTIME_PRIMITIVES[imported];
136
+ if (returns) bindings.primitives.set(specifier.local.name, returns);
137
+ }
138
+ }
139
+ walk(root, (node) => {
140
+ if (node.type !== "VariableDeclarator" || !node.init) return;
141
+ const returns = calledPrimitive(node.init, bindings);
142
+ if (returns) classify(node.id, returns, bindings.kinds);
143
+ });
144
+ return bindings;
145
+ }
146
+
147
+ // src/resolve/builtins.ts
148
+ var DOM_CONTROL_FLOW = [
149
+ "Show",
150
+ "For",
151
+ "Index",
152
+ "Switch",
153
+ "Match",
154
+ "Portal",
155
+ "Dynamic",
156
+ "ErrorBoundary"
157
+ ];
158
+ var CORE_CONTROL_FLOW = ["Suspense", "SuspenseList", "Await"];
159
+ var ROUTER_COMPONENTS = ["Router", "Outlet", "Redirect", "Link"];
160
+ var BUILTIN_COMPONENTS = [
161
+ ...DOM_CONTROL_FLOW,
162
+ ...CORE_CONTROL_FLOW,
163
+ ...ROUTER_COMPONENTS
164
+ ];
165
+ var RESERVED_COMPONENTS = /* @__PURE__ */ new Set([
166
+ ...DOM_CONTROL_FLOW,
167
+ ...CORE_CONTROL_FLOW
168
+ ]);
169
+
170
+ // src/analyze/static-graph.ts
171
+ var PRIMITIVE_KIND = {
172
+ signal: "state",
173
+ createSignal: "state",
174
+ memo: "memo",
175
+ createMemo: "memo",
176
+ effect: "effect",
177
+ createEffect: "effect",
178
+ store: "store",
179
+ createStore: "store",
180
+ resource: "resource",
181
+ createResource: "resource"
182
+ };
183
+ var READS = /* @__PURE__ */ new Set(["memo", "effect", "resource"]);
184
+ var DIRECTIVES = /* @__PURE__ */ new Set([
185
+ ...DOM_CONTROL_FLOW,
186
+ ...CORE_CONTROL_FLOW,
187
+ // The router is supplied without an import too. Without these, an app whose root renders
188
+ // `<Router>` has a root component connected to nothing at all.
189
+ ...ROUTER_COMPONENTS
190
+ ]);
191
+ var TRACKED_PROP = {
192
+ Router: "routes",
193
+ Link: "href",
194
+ Redirect: "to",
195
+ Show: "when",
196
+ Match: "when",
197
+ For: "each",
198
+ Index: "each",
199
+ Dynamic: "component",
200
+ Portal: "mount",
201
+ Await: "value"
202
+ };
203
+ var ROUTER = new Set(ROUTER_COMPONENTS);
204
+ var directiveKind = (tag) => ROUTER.has(tag) ? "router" : "control";
205
+ var HTTP_METHODS = /* @__PURE__ */ new Set([
206
+ "GET",
207
+ "POST",
208
+ "PUT",
209
+ "PATCH",
210
+ "DELETE",
211
+ "HEAD",
212
+ "OPTIONS"
213
+ ]);
214
+ function normalizePath(path) {
215
+ return path.replace(/\\/g, "/").replace(/^\.?\/+/, "");
216
+ }
217
+ function walk2(node, visit, stack = []) {
218
+ if (!node || typeof node.type !== "string") return;
219
+ visit(node, stack);
220
+ stack.push(node);
221
+ for (const key of Object.keys(node)) {
222
+ if (key === "loc" || key === "parent") continue;
223
+ const value = node[key];
224
+ if (Array.isArray(value)) for (const child of value) walk2(child, visit, stack);
225
+ else if (value && typeof value.type === "string") walk2(value, visit, stack);
226
+ }
227
+ stack.pop();
228
+ }
229
+ function declaredName(stack) {
230
+ const declarator = [...stack].reverse().find((n) => n.type === "VariableDeclarator");
231
+ const id = declarator?.id;
232
+ if (id?.type === "Identifier") return id.name;
233
+ if (id?.type === "ArrayPattern") {
234
+ const first = id.elements?.[0];
235
+ if (first?.type === "Identifier") return first.name;
236
+ }
237
+ return void 0;
238
+ }
239
+ function componentName(node) {
240
+ if (node.type === "FunctionDeclaration") {
241
+ const name = node.id?.name;
242
+ return name && name[0] === name[0]?.toUpperCase() ? name : void 0;
243
+ }
244
+ if (node.type === "VariableDeclarator") {
245
+ const id = node.id;
246
+ const init = node.init;
247
+ if (id?.type !== "Identifier" || !init) return void 0;
248
+ if (init.type !== "ArrowFunctionExpression" && init.type !== "FunctionExpression") return void 0;
249
+ const name = id.name;
250
+ return name[0] === name[0]?.toUpperCase() ? name : void 0;
251
+ }
252
+ return void 0;
253
+ }
254
+ function mentions(node) {
255
+ const names = /* @__PURE__ */ new Set();
256
+ walk2(node, (n, stack) => {
257
+ if (n.type !== "Identifier") return;
258
+ const parent = stack[stack.length - 1];
259
+ if (parent?.type === "MemberExpression" && parent.property === n && !parent.computed) return;
260
+ if (parent?.type === "ObjectProperty" && parent.key === n && !parent.computed) return;
261
+ names.add(n.name);
262
+ });
263
+ return names;
264
+ }
265
+ function templatePieces(quasi) {
266
+ const pieces = [];
267
+ const quasis = quasi.quasis ?? [];
268
+ const expressions = quasi.expressions ?? [];
269
+ quasis.forEach((q, i) => {
270
+ const value = q.value;
271
+ pieces.push({ kind: "static", text: value?.cooked ?? value?.raw ?? "", start: q.start ?? 0 });
272
+ if (i < expressions.length) {
273
+ const e = expressions[i];
274
+ pieces.push({ kind: "hole", index: i, start: e.start ?? 0, end: e.end ?? 0 });
275
+ }
276
+ });
277
+ return pieces;
278
+ }
279
+ function positionsIn(code) {
280
+ const starts = [0];
281
+ for (let i = 0; i < code.length; i++) if (code.charCodeAt(i) === 10) starts.push(i + 1);
282
+ return (offset) => {
283
+ let low = 0;
284
+ let high = starts.length - 1;
285
+ while (low < high) {
286
+ const mid = low + high + 1 >> 1;
287
+ if (starts[mid] <= offset) low = mid;
288
+ else high = mid - 1;
289
+ }
290
+ return { line: low + 1, column: offset - starts[low] };
291
+ };
292
+ }
293
+ function describeTemplateElement(el) {
294
+ let id = "";
295
+ const classes = [];
296
+ for (const attr of el.attributes) {
297
+ if (attr.kind !== "Attribute" || attr.value?.kind !== "static") continue;
298
+ if (attr.name === "id") id = `#${attr.value.value}`;
299
+ else if (attr.name === "class") {
300
+ classes.push(...String(attr.value.value).split(/\s+/).filter(Boolean).slice(0, 2));
301
+ }
302
+ }
303
+ return `${el.tag}${id}${classes.map((c) => `.${c}`).join("")}`;
304
+ }
305
+ function valueHoles(value) {
306
+ if (!value) return [];
307
+ if (value.kind === "hole") return [value.hole];
308
+ if (value.kind === "mixed") return value.parts.flatMap((p) => "hole" in p ? [p.hole] : []);
309
+ return [];
310
+ }
311
+ function describeJsx(opening) {
312
+ const tag = opening.name?.name ?? "element";
313
+ let id = "";
314
+ const classes = [];
315
+ for (const attr of opening.attributes ?? []) {
316
+ if (attr.type !== "JSXAttribute") continue;
317
+ const name = attr.name?.name;
318
+ const value = attr.value;
319
+ if (value?.type !== "StringLiteral") continue;
320
+ if (name === "id") id = `#${value.value}`;
321
+ else if (name === "class" || name === "className") {
322
+ classes.push(...String(value.value).split(/\s+/).filter(Boolean).slice(0, 2));
323
+ }
324
+ }
325
+ return `${tag}${id}${classes.map((c) => `.${c}`).join("")}`;
326
+ }
327
+ function trackedExpression(opening, prop) {
328
+ for (const attr of opening.attributes ?? []) {
329
+ if (attr.type !== "JSXAttribute" || attr.name?.name !== prop) continue;
330
+ const value = attr.value;
331
+ return value?.type === "JSXExpressionContainer" ? value.expression : void 0;
332
+ }
333
+ return void 0;
334
+ }
335
+ function analyzeReactiveGraph(files, options = {}) {
336
+ const routesDir = (options.routesDir ?? "src/routes").replace(/^\.?\/+|\/+$/g, "");
337
+ const apiDir = (options.apiDir ?? "src/api").replace(/^\.?\/+|\/+$/g, "");
338
+ const fileRoutes = [];
339
+ const pending = [];
340
+ const exported = /* @__PURE__ */ new Map();
341
+ const locals = /* @__PURE__ */ new Map();
342
+ const imports = /* @__PURE__ */ new Map();
343
+ const usages = [];
344
+ const routeRefs = [];
345
+ const holes = [];
346
+ const domFor = /* @__PURE__ */ new Map();
347
+ const unresolved = [];
348
+ const componentMentions = /* @__PURE__ */ new Map();
349
+ let seq = 0;
350
+ for (const file of files) {
351
+ if (!/\.(tsx?|jsx?)$/.test(file.path)) continue;
352
+ let program;
353
+ try {
354
+ program = parse(file.code, {
355
+ sourceType: "module",
356
+ plugins: ["jsx", "typescript"],
357
+ errorRecovery: true
358
+ }).program;
359
+ } catch {
360
+ continue;
361
+ }
362
+ const { primitives, shadowed } = resolveReactiveBindings(program);
363
+ const here = /* @__PURE__ */ new Map();
364
+ const sold = /* @__PURE__ */ new Map();
365
+ const from = /* @__PURE__ */ new Map();
366
+ locals.set(file.path, here);
367
+ exported.set(file.path, sold);
368
+ imports.set(file.path, from);
369
+ const inRoutesDir = normalizePath(file.path).startsWith(`${routesDir}/`);
370
+ const components = /* @__PURE__ */ new Map();
371
+ let positionAt = null;
372
+ const positionOf = () => positionAt ??= positionsIn(file.code);
373
+ walk2(program, (node, stack) => {
374
+ const name = componentName(node);
375
+ const at = node.loc?.start;
376
+ if (!name || !at) return;
377
+ const id = seq++;
378
+ components.set(node, id);
379
+ here.set(name, id);
380
+ componentMentions.set(id, mentions(node));
381
+ if (inRoutesDir) fileRoutes.push(id);
382
+ pending.push({
383
+ node: {
384
+ id,
385
+ label: name,
386
+ kind: HTTP_METHODS.has(name) ? "handler" : "component",
387
+ deps: [],
388
+ writes: [],
389
+ runs: 0,
390
+ lastPulse: 0,
391
+ source: { file: file.path, line: at.line, column: at.column }
392
+ },
393
+ reads: /* @__PURE__ */ new Set(),
394
+ file: file.path
395
+ });
396
+ });
397
+ walk2(program, (node, stack) => {
398
+ if (node.type === "ImportDeclaration") {
399
+ const source = node.source?.value;
400
+ for (const spec of node.specifiers ?? []) {
401
+ const local = spec.local?.name;
402
+ if (local && source?.startsWith(".")) from.set(local, source);
403
+ }
404
+ return;
405
+ }
406
+ if (node.type !== "CallExpression") return;
407
+ const callee = node.callee;
408
+ if (callee?.type !== "Identifier") return;
409
+ const name = callee.name;
410
+ const intrinsic = name.startsWith("$") && isIntrinsicName(name) && !shadowed.has(name);
411
+ if (!intrinsic && !primitives.has(name)) return;
412
+ const kind = PRIMITIVE_KIND[intrinsic ? name.slice(1) : name];
413
+ const at = node.loc?.start;
414
+ if (!kind || !at) return;
415
+ const id = seq++;
416
+ const label = declaredName(stack) ?? `${kind}${id}`;
417
+ here.set(label, id);
418
+ let owner;
419
+ for (let i = stack.length - 1; i >= 0; i--) {
420
+ const found = components.get(stack[i]);
421
+ if (found !== void 0) {
422
+ owner = found;
423
+ break;
424
+ }
425
+ }
426
+ pending.push({
427
+ node: {
428
+ id,
429
+ label,
430
+ kind,
431
+ deps: [],
432
+ writes: [],
433
+ runs: 0,
434
+ lastPulse: 0,
435
+ source: { file: file.path, line: at.line, column: at.column },
436
+ ...owner !== void 0 ? { createdIn: owner } : {}
437
+ },
438
+ // Only what reads can read: a signal's initial value is not a dependency.
439
+ reads: READS.has(kind) ? mentions(node.arguments?.[0]) : /* @__PURE__ */ new Set(),
440
+ file: file.path
441
+ });
442
+ });
443
+ walk2(program, (node, stack) => {
444
+ if (node.type !== "JSXOpeningElement") return;
445
+ const tag = node.name?.name;
446
+ if (!tag || tag[0] !== tag[0]?.toUpperCase()) return;
447
+ let owner;
448
+ for (let i = stack.length - 1; i >= 0; i--) {
449
+ const found = components.get(stack[i]);
450
+ if (found !== void 0) {
451
+ owner = found;
452
+ break;
453
+ }
454
+ }
455
+ const own = here.has(tag) || from.has(tag);
456
+ if (!own && DIRECTIVES.has(tag)) {
457
+ const at = node.loc?.start;
458
+ if (!at) return;
459
+ const id = seq++;
460
+ const prop = TRACKED_PROP[tag];
461
+ const tracked = prop ? trackedExpression(node, prop) : void 0;
462
+ const element = stack[stack.length - 1];
463
+ if (element?.type === "JSXElement") components.set(element, id);
464
+ pending.push({
465
+ node: {
466
+ id,
467
+ label: tag,
468
+ kind: directiveKind(tag),
469
+ deps: [],
470
+ writes: [],
471
+ runs: 0,
472
+ lastPulse: 0,
473
+ source: { file: file.path, line: at.line, column: at.column },
474
+ ...owner !== void 0 ? { createdIn: owner } : {}
475
+ },
476
+ reads: tracked ? mentions(tracked) : /* @__PURE__ */ new Set(),
477
+ file: file.path
478
+ });
479
+ return;
480
+ }
481
+ if (owner !== void 0) usages.push({ tag, file: file.path, owner });
482
+ });
483
+ walk2(program, (node, stack) => {
484
+ if (node.type !== "JSXExpressionContainer") return;
485
+ const expr = node.expression;
486
+ if (!expr || expr.type === "JSXEmptyExpression") return;
487
+ const at = expr.loc?.start;
488
+ if (!at) return;
489
+ const parent = stack[stack.length - 1];
490
+ const attribute = parent?.type === "JSXAttribute" ? parent.name?.name : void 0;
491
+ const holder = [...stack].reverse().find((n) => n.type === "JSXElement" || n.type === "JSXOpeningElement");
492
+ const opening = holder?.type === "JSXOpeningElement" ? holder : holder?.openingElement;
493
+ if (!opening) return;
494
+ const target = {
495
+ kind: attribute ? "attribute" : "content",
496
+ ...attribute ? { name: attribute } : {},
497
+ element: describeJsx(opening),
498
+ source: { file: file.path, line: at.line, column: at.column }
499
+ };
500
+ for (const name of mentions(expr)) holes.push({ file: file.path, name, target });
501
+ });
502
+ const describeTree = (el) => {
503
+ const opening = el.openingElement ?? void 0;
504
+ const tag = opening?.name?.name;
505
+ if (!opening || !tag) return void 0;
506
+ const at = el.loc?.start;
507
+ const where = at ? { file: file.path, line: at.line, column: at.column } : void 0;
508
+ const children = [];
509
+ for (const child of el.children ?? []) {
510
+ if (child?.type !== "JSXElement") continue;
511
+ const sub = describeTree(child);
512
+ if (sub) children.push(sub);
513
+ }
514
+ if (tag[0] === tag[0]?.toUpperCase()) {
515
+ const node = { label: tag, children, ...where ? { at: where } : {} };
516
+ const id = components.get(el) ?? here.get(tag);
517
+ if (id !== void 0) node.owner = id;
518
+ else unresolved.push({ node, tag, file: file.path });
519
+ return node;
520
+ }
521
+ return { label: describeJsx(opening), children, ...where ? { at: where } : {} };
522
+ };
523
+ walk2(program, (node, stack) => {
524
+ if (node.type !== "JSXElement") return;
525
+ let owner;
526
+ for (let i = stack.length - 1; i >= 0; i--) {
527
+ const found = stack[i];
528
+ if (found.type === "JSXElement") return;
529
+ const id = components.get(found);
530
+ if (id !== void 0) {
531
+ owner = id;
532
+ break;
533
+ }
534
+ }
535
+ if (owner === void 0) return;
536
+ const tree = describeTree(node);
537
+ if (!tree) return;
538
+ const held = domFor.get(owner);
539
+ if (held) held.push(tree);
540
+ else domFor.set(owner, [tree]);
541
+ });
542
+ walk2(program, (node, stack) => {
543
+ if (node.type !== "TaggedTemplateExpression") return;
544
+ const tagName = node.tag?.name;
545
+ if (tagName !== "html" && tagName !== "svg") return;
546
+ const quasi = node.quasi;
547
+ const expressions = quasi?.expressions ?? [];
548
+ const positionAt2 = positionOf();
549
+ let children;
550
+ try {
551
+ children = parseTemplate(templatePieces(quasi), { svg: tagName === "svg" }).root.children;
552
+ } catch {
553
+ return;
554
+ }
555
+ const holeExpr = (index) => index == null ? void 0 : expressions[index];
556
+ const readsOf = (index) => {
557
+ const expr = holeExpr(index);
558
+ return expr ? mentions(expr) : /* @__PURE__ */ new Set();
559
+ };
560
+ const addControl = (tag, offset, hole, owner2) => {
561
+ const at = offset !== void 0 ? positionAt2(offset) : holeExpr(hole)?.loc?.start ?? node.loc?.start;
562
+ if (!at) return void 0;
563
+ const id = seq++;
564
+ pending.push({
565
+ node: {
566
+ id,
567
+ label: tag,
568
+ kind: directiveKind(tag),
569
+ deps: [],
570
+ writes: [],
571
+ runs: 0,
572
+ lastPulse: 0,
573
+ source: { file: file.path, line: at.line, column: at.column },
574
+ ...owner2 !== void 0 ? { createdIn: owner2 } : {}
575
+ },
576
+ reads: readsOf(hole),
577
+ file: file.path
578
+ });
579
+ return id;
580
+ };
581
+ const addTarget = (index, element, attribute) => {
582
+ const expr = holeExpr(index);
583
+ const at = expr?.loc?.start;
584
+ if (!expr || !at) return;
585
+ const target = {
586
+ kind: attribute ? "attribute" : "content",
587
+ ...attribute ? { name: attribute } : {},
588
+ element,
589
+ source: { file: file.path, line: at.line, column: at.column }
590
+ };
591
+ for (const name of mentions(expr)) holes.push({ file: file.path, name, target });
592
+ };
593
+ const elementTargets = (el) => {
594
+ const element = describeTemplateElement(el);
595
+ for (const attr of el.attributes) {
596
+ switch (attr.kind) {
597
+ case "Attribute":
598
+ for (const hole of valueHoles(attr.value)) addTarget(hole, element, attr.name);
599
+ break;
600
+ case "PropertyBinding":
601
+ case "BindDirective":
602
+ addTarget(attr.hole, element, attr.name);
603
+ break;
604
+ case "ClassDirective":
605
+ addTarget(attr.hole, element, "class");
606
+ break;
607
+ case "StyleDirective":
608
+ addTarget(attr.hole, element, "style");
609
+ break;
610
+ // A handler is not a read, and neither is a ref, a spread or a use.
611
+ default:
612
+ break;
613
+ }
614
+ }
615
+ };
616
+ const visit = (nodes, owner2, holder) => {
617
+ for (const child of nodes) {
618
+ switch (child.kind) {
619
+ case "Element": {
620
+ const ifDir = child.attributes.find((a) => a.kind === "IfDirective");
621
+ const eachDir = child.attributes.find((a) => a.kind === "EachDirective");
622
+ let inner = owner2;
623
+ if (ifDir?.kind === "IfDirective") inner = addControl("Show", child.loc?.start, ifDir.hole, owner2) ?? owner2;
624
+ else if (eachDir?.kind === "EachDirective") inner = addControl("For", child.loc?.start, eachDir.hole, owner2) ?? owner2;
625
+ elementTargets(child);
626
+ visit(child.children, inner, describeTemplateElement(child));
627
+ break;
628
+ }
629
+ case "Component": {
630
+ const tag = child.tag;
631
+ const own = here.has(tag) || from.has(tag);
632
+ if (tag && !own && DIRECTIVES.has(tag)) {
633
+ const prop = TRACKED_PROP[tag];
634
+ const tracked = prop ? child.attributes.find(
635
+ (a) => "name" in a && a.name === prop
636
+ ) : void 0;
637
+ const hole = tracked && "hole" in tracked ? tracked.hole : tracked && "value" in tracked ? valueHoles(tracked.value)[0] : void 0;
638
+ const id = addControl(tag, child.loc?.start, hole, owner2);
639
+ visit(child.children, id ?? owner2, holder);
640
+ break;
641
+ }
642
+ if (tag && owner2 !== void 0) usages.push({ tag, file: file.path, owner: owner2 });
643
+ visit(child.children, owner2, holder);
644
+ break;
645
+ }
646
+ case "Fragment":
647
+ visit(child.children, owner2, holder);
648
+ break;
649
+ case "Expression":
650
+ addTarget(child.hole, holder, void 0);
651
+ break;
652
+ default:
653
+ break;
654
+ }
655
+ }
656
+ };
657
+ let owner;
658
+ for (let i = stack.length - 1; i >= 0; i--) {
659
+ const found = components.get(stack[i]);
660
+ if (found !== void 0) {
661
+ owner = found;
662
+ break;
663
+ }
664
+ }
665
+ visit(children, owner, "template");
666
+ });
667
+ walk2(program, (node, stack) => {
668
+ if (node.type !== "ObjectProperty" || node.computed) return;
669
+ const key = node.key?.name ?? node.key?.value;
670
+ if (key !== "component" && key !== "Component") return;
671
+ const value = node.value;
672
+ if (value?.type !== "Identifier") return;
673
+ const holder = [...stack].reverse().find((n) => n.type === "VariableDeclarator");
674
+ const via = holder?.id?.name;
675
+ if (via) routeRefs.push({ via, tag: value.name, file: file.path });
676
+ });
677
+ walk2(program, (node) => {
678
+ if (node.type !== "ExportNamedDeclaration" && node.type !== "ExportDefaultDeclaration") return;
679
+ for (const name of here.keys()) sold.set(name, here.get(name));
680
+ });
681
+ }
682
+ const resolve = (file, name) => {
683
+ const local = locals.get(file)?.get(name);
684
+ if (local !== void 0) return local;
685
+ const source = imports.get(file)?.get(name);
686
+ if (!source) return void 0;
687
+ for (const [path, names] of exported) {
688
+ if (!sameModule(file, source, path)) continue;
689
+ const id = names.get(name);
690
+ if (id !== void 0) return id;
691
+ }
692
+ return void 0;
693
+ };
694
+ for (const entry of pending) {
695
+ const deps = /* @__PURE__ */ new Set();
696
+ for (const name of entry.reads) {
697
+ const id = resolve(entry.file, name);
698
+ if (id !== void 0 && id !== entry.node.id) deps.add(id);
699
+ }
700
+ entry.node.deps = [...deps];
701
+ }
702
+ const unique = /* @__PURE__ */ new Map();
703
+ for (const names of exported.values()) {
704
+ for (const [name, id] of names) unique.set(name, unique.has(name) ? null : id);
705
+ }
706
+ const byId = new Map(pending.map((p) => [p.node.id, p.node]));
707
+ for (const entry of unresolved) {
708
+ const id = resolve(entry.file, entry.tag) ?? unique.get(entry.tag) ?? void 0;
709
+ if (id !== void 0 && byId.get(id)?.kind === "component") entry.node.owner = id;
710
+ }
711
+ for (const [id, dom] of domFor) {
712
+ const node = byId.get(id);
713
+ if (node && dom.length) node.dom = dom;
714
+ }
715
+ for (const hole of holes) {
716
+ const id = resolve(hole.file, hole.name);
717
+ const node = id !== void 0 ? byId.get(id) : void 0;
718
+ if (!node || node.kind === "component") continue;
719
+ (node.targets ??= []).push(hole.target);
720
+ }
721
+ for (const ref of routeRefs) {
722
+ const named = resolve(ref.file, ref.tag) ?? unique.get(ref.tag) ?? void 0;
723
+ if (named === void 0) continue;
724
+ const router = pending.find(
725
+ (p) => p.file === ref.file && p.node.kind === "router" && p.node.id !== named && p.reads.has(ref.via)
726
+ )?.node.id;
727
+ const mentions2 = pending.find(
728
+ (p) => p.file === ref.file && (p.node.kind === "component" || p.node.kind === "handler") && p.node.id !== named && componentMentions.get(p.node.id)?.has(ref.via)
729
+ )?.node.id;
730
+ const holder = router ?? mentions2;
731
+ const node = byId.get(named);
732
+ if (node && node.createdIn === void 0 && holder !== void 0) node.createdIn = holder;
733
+ }
734
+ for (const use of usages) {
735
+ const id = resolve(use.file, use.tag) ?? unique.get(use.tag) ?? void 0;
736
+ if (id === void 0 || id === use.owner) continue;
737
+ const node = byId.get(id);
738
+ if (node && node.kind === "component" && node.createdIn === void 0) node.createdIn = use.owner;
739
+ }
740
+ const only = (kind, label) => {
741
+ const found = pending.filter((p) => p.node.kind === kind && p.node.label === label);
742
+ return found.length === 1 ? found[0].node.id : void 0;
743
+ };
744
+ const routeOwner = only("router", "Outlet") ?? only("router", "Router");
745
+ if (routeOwner !== void 0) {
746
+ for (const id of fileRoutes) {
747
+ const node = byId.get(id);
748
+ if (node && node.kind === "component" && node.createdIn === void 0 && id !== routeOwner) {
749
+ node.createdIn = routeOwner;
750
+ }
751
+ }
752
+ }
753
+ const loose = pending.filter(
754
+ (p) => p.node.kind === "handler" && p.node.createdIn === void 0
755
+ );
756
+ if (loose.length > 0) {
757
+ const id = seq++;
758
+ pending.push({
759
+ node: {
760
+ id,
761
+ label: "api",
762
+ kind: "handler",
763
+ deps: [],
764
+ writes: [],
765
+ runs: 0,
766
+ lastPulse: 0,
767
+ // The directory, since there is no line of anyone's source to point at.
768
+ source: { file: apiDir, line: 1, column: 0 }
769
+ },
770
+ reads: /* @__PURE__ */ new Set(),
771
+ file: apiDir
772
+ });
773
+ for (const p of loose) p.node.createdIn = id;
774
+ }
775
+ return { t: Date.now(), nodes: pending.map((p) => p.node), static: true };
776
+ }
777
+ var withoutExtension = (path) => path.replace(/\.(tsx?|jsx?|mts|cts|mjs|cjs)$/, "");
778
+ function sameModule(importer, specifier, candidate) {
779
+ const base = importer.includes("/") ? importer.slice(0, importer.lastIndexOf("/")) : "";
780
+ const parts = (base ? base.split("/") : []).concat(specifier.split("/"));
781
+ const stack = [];
782
+ for (const part of parts) {
783
+ if (part === "." || part === "") continue;
784
+ if (part === "..") stack.pop();
785
+ else stack.push(part);
786
+ }
787
+ const resolved = withoutExtension(stack.join("/"));
788
+ const target = withoutExtension(candidate);
789
+ return target === resolved || target === `${resolved}/index`;
790
+ }
791
+ export {
792
+ analyzeReactiveGraph
793
+ };