@backthread/extractor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (379) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/cluster/domain-grouping.d.ts +113 -0
  4. package/dist/cluster/domain-grouping.d.ts.map +1 -0
  5. package/dist/cluster/domain-grouping.js +277 -0
  6. package/dist/cluster/domain-grouping.js.map +1 -0
  7. package/dist/cluster/grouping-gate.d.ts +54 -0
  8. package/dist/cluster/grouping-gate.d.ts.map +1 -0
  9. package/dist/cluster/grouping-gate.js +0 -0
  10. package/dist/cluster/grouping-gate.js.map +1 -0
  11. package/dist/cluster/louvain.d.ts +88 -0
  12. package/dist/cluster/louvain.d.ts.map +1 -0
  13. package/dist/cluster/louvain.js +674 -0
  14. package/dist/cluster/louvain.js.map +1 -0
  15. package/dist/cluster/overrides.d.ts +19 -0
  16. package/dist/cluster/overrides.d.ts.map +1 -0
  17. package/dist/cluster/overrides.js +32 -0
  18. package/dist/cluster/overrides.js.map +1 -0
  19. package/dist/cluster/subsystem.d.ts +45 -0
  20. package/dist/cluster/subsystem.d.ts.map +1 -0
  21. package/dist/cluster/subsystem.js +299 -0
  22. package/dist/cluster/subsystem.js.map +1 -0
  23. package/dist/cluster/workspaces.d.ts +64 -0
  24. package/dist/cluster/workspaces.d.ts.map +1 -0
  25. package/dist/cluster/workspaces.js +739 -0
  26. package/dist/cluster/workspaces.js.map +1 -0
  27. package/dist/extract.d.ts +52 -0
  28. package/dist/extract.d.ts.map +1 -0
  29. package/dist/extract.js +48 -0
  30. package/dist/extract.js.map +1 -0
  31. package/dist/framework/celery/celery.d.ts +17 -0
  32. package/dist/framework/celery/celery.d.ts.map +1 -0
  33. package/dist/framework/celery/celery.js +524 -0
  34. package/dist/framework/celery/celery.js.map +1 -0
  35. package/dist/framework/contribute-step.d.ts +38 -0
  36. package/dist/framework/contribute-step.d.ts.map +1 -0
  37. package/dist/framework/contribute-step.js +403 -0
  38. package/dist/framework/contribute-step.js.map +1 -0
  39. package/dist/framework/detect-step.d.ts +8 -0
  40. package/dist/framework/detect-step.d.ts.map +1 -0
  41. package/dist/framework/detect-step.js +54 -0
  42. package/dist/framework/detect-step.js.map +1 -0
  43. package/dist/framework/detect-util.d.ts +24 -0
  44. package/dist/framework/detect-util.d.ts.map +1 -0
  45. package/dist/framework/detect-util.js +59 -0
  46. package/dist/framework/detect-util.js.map +1 -0
  47. package/dist/framework/django/django.d.ts +22 -0
  48. package/dist/framework/django/django.d.ts.map +1 -0
  49. package/dist/framework/django/django.js +940 -0
  50. package/dist/framework/django/django.js.map +1 -0
  51. package/dist/framework/fastapi/fastapi.d.ts +27 -0
  52. package/dist/framework/fastapi/fastapi.d.ts.map +1 -0
  53. package/dist/framework/fastapi/fastapi.js +477 -0
  54. package/dist/framework/fastapi/fastapi.js.map +1 -0
  55. package/dist/framework/faststream/faststream.d.ts +19 -0
  56. package/dist/framework/faststream/faststream.d.ts.map +1 -0
  57. package/dist/framework/faststream/faststream.js +765 -0
  58. package/dist/framework/faststream/faststream.js.map +1 -0
  59. package/dist/framework/flask/flask.d.ts +17 -0
  60. package/dist/framework/flask/flask.d.ts.map +1 -0
  61. package/dist/framework/flask/flask.js +507 -0
  62. package/dist/framework/flask/flask.js.map +1 -0
  63. package/dist/framework/graphql/graphql.d.ts +17 -0
  64. package/dist/framework/graphql/graphql.d.ts.map +1 -0
  65. package/dist/framework/graphql/graphql.js +708 -0
  66. package/dist/framework/graphql/graphql.js.map +1 -0
  67. package/dist/framework/grpc/grpc.d.ts +22 -0
  68. package/dist/framework/grpc/grpc.d.ts.map +1 -0
  69. package/dist/framework/grpc/grpc.js +618 -0
  70. package/dist/framework/grpc/grpc.js.map +1 -0
  71. package/dist/framework/litestar/litestar.d.ts +17 -0
  72. package/dist/framework/litestar/litestar.d.ts.map +1 -0
  73. package/dist/framework/litestar/litestar.js +536 -0
  74. package/dist/framework/litestar/litestar.js.map +1 -0
  75. package/dist/framework/nest/nest.d.ts +19 -0
  76. package/dist/framework/nest/nest.d.ts.map +1 -0
  77. package/dist/framework/nest/nest.js +613 -0
  78. package/dist/framework/nest/nest.js.map +1 -0
  79. package/dist/framework/next/next.d.ts +22 -0
  80. package/dist/framework/next/next.d.ts.map +1 -0
  81. package/dist/framework/next/next.js +449 -0
  82. package/dist/framework/next/next.js.map +1 -0
  83. package/dist/framework/node/node.d.ts +24 -0
  84. package/dist/framework/node/node.d.ts.map +1 -0
  85. package/dist/framework/node/node.js +1009 -0
  86. package/dist/framework/node/node.js.map +1 -0
  87. package/dist/framework/orchestrator/orchestrator.d.ts +34 -0
  88. package/dist/framework/orchestrator/orchestrator.d.ts.map +1 -0
  89. package/dist/framework/orchestrator/orchestrator.js +691 -0
  90. package/dist/framework/orchestrator/orchestrator.js.map +1 -0
  91. package/dist/framework/orm/orm.d.ts +61 -0
  92. package/dist/framework/orm/orm.d.ts.map +1 -0
  93. package/dist/framework/orm/orm.js +620 -0
  94. package/dist/framework/orm/orm.js.map +1 -0
  95. package/dist/framework/python/analyze.d.ts +38 -0
  96. package/dist/framework/python/analyze.d.ts.map +1 -0
  97. package/dist/framework/python/analyze.js +98 -0
  98. package/dist/framework/python/analyze.js.map +1 -0
  99. package/dist/framework/python/py-ast.d.ts +130 -0
  100. package/dist/framework/python/py-ast.d.ts.map +1 -0
  101. package/dist/framework/python/py-ast.js +344 -0
  102. package/dist/framework/python/py-ast.js.map +1 -0
  103. package/dist/framework/python-orm/python-orm.d.ts +19 -0
  104. package/dist/framework/python-orm/python-orm.d.ts.map +1 -0
  105. package/dist/framework/python-orm/python-orm.js +516 -0
  106. package/dist/framework/python-orm/python-orm.js.map +1 -0
  107. package/dist/framework/react-native/react-native.d.ts +35 -0
  108. package/dist/framework/react-native/react-native.d.ts.map +1 -0
  109. package/dist/framework/react-native/react-native.js +1181 -0
  110. package/dist/framework/react-native/react-native.js.map +1 -0
  111. package/dist/framework/register.d.ts +2 -0
  112. package/dist/framework/register.d.ts.map +1 -0
  113. package/dist/framework/register.js +59 -0
  114. package/dist/framework/register.js.map +1 -0
  115. package/dist/framework/registry.d.ts +31 -0
  116. package/dist/framework/registry.d.ts.map +1 -0
  117. package/dist/framework/registry.js +70 -0
  118. package/dist/framework/registry.js.map +1 -0
  119. package/dist/framework/routing/expo-router.d.ts +31 -0
  120. package/dist/framework/routing/expo-router.d.ts.map +1 -0
  121. package/dist/framework/routing/expo-router.js +356 -0
  122. package/dist/framework/routing/expo-router.js.map +1 -0
  123. package/dist/framework/routing/index.d.ts +4 -0
  124. package/dist/framework/routing/index.d.ts.map +1 -0
  125. package/dist/framework/routing/index.js +16 -0
  126. package/dist/framework/routing/index.js.map +1 -0
  127. package/dist/framework/routing/next-router.d.ts +45 -0
  128. package/dist/framework/routing/next-router.d.ts.map +1 -0
  129. package/dist/framework/routing/next-router.js +378 -0
  130. package/dist/framework/routing/next-router.js.map +1 -0
  131. package/dist/framework/routing/route-tree.d.ts +73 -0
  132. package/dist/framework/routing/route-tree.d.ts.map +1 -0
  133. package/dist/framework/routing/route-tree.js +120 -0
  134. package/dist/framework/routing/route-tree.js.map +1 -0
  135. package/dist/framework/types.d.ts +230 -0
  136. package/dist/framework/types.d.ts.map +1 -0
  137. package/dist/framework/types.js +25 -0
  138. package/dist/framework/types.js.map +1 -0
  139. package/dist/graph/cross-language.d.ts +11 -0
  140. package/dist/graph/cross-language.d.ts.map +1 -0
  141. package/dist/graph/cross-language.js +123 -0
  142. package/dist/graph/cross-language.js.map +1 -0
  143. package/dist/graph/extract.d.ts +13 -0
  144. package/dist/graph/extract.d.ts.map +1 -0
  145. package/dist/graph/extract.js +79 -0
  146. package/dist/graph/extract.js.map +1 -0
  147. package/dist/graph/file-graph.d.ts +186 -0
  148. package/dist/graph/file-graph.d.ts.map +1 -0
  149. package/dist/graph/file-graph.js +427 -0
  150. package/dist/graph/file-graph.js.map +1 -0
  151. package/dist/graph/http-callsites.d.ts +14 -0
  152. package/dist/graph/http-callsites.d.ts.map +1 -0
  153. package/dist/graph/http-callsites.js +107 -0
  154. package/dist/graph/http-callsites.js.map +1 -0
  155. package/dist/graph/incremental.d.ts +122 -0
  156. package/dist/graph/incremental.d.ts.map +1 -0
  157. package/dist/graph/incremental.js +448 -0
  158. package/dist/graph/incremental.js.map +1 -0
  159. package/dist/graph/language.d.ts +31 -0
  160. package/dist/graph/language.d.ts.map +1 -0
  161. package/dist/graph/language.js +146 -0
  162. package/dist/graph/language.js.map +1 -0
  163. package/dist/graph/noise-filter.d.ts +46 -0
  164. package/dist/graph/noise-filter.d.ts.map +1 -0
  165. package/dist/graph/noise-filter.js +199 -0
  166. package/dist/graph/noise-filter.js.map +1 -0
  167. package/dist/graph/python-adapter.d.ts +36 -0
  168. package/dist/graph/python-adapter.d.ts.map +1 -0
  169. package/dist/graph/python-adapter.js +402 -0
  170. package/dist/graph/python-adapter.js.map +1 -0
  171. package/dist/graph/python-manifest.d.ts +22 -0
  172. package/dist/graph/python-manifest.d.ts.map +1 -0
  173. package/dist/graph/python-manifest.js +137 -0
  174. package/dist/graph/python-manifest.js.map +1 -0
  175. package/dist/graph/python-stdlib.d.ts +2 -0
  176. package/dist/graph/python-stdlib.d.ts.map +1 -0
  177. package/dist/graph/python-stdlib.js +53 -0
  178. package/dist/graph/python-stdlib.js.map +1 -0
  179. package/dist/graph/ts-morph-adapter.d.ts +65 -0
  180. package/dist/graph/ts-morph-adapter.d.ts.map +1 -0
  181. package/dist/graph/ts-morph-adapter.js +265 -0
  182. package/dist/graph/ts-morph-adapter.js.map +1 -0
  183. package/dist/graph/types.d.ts +37 -0
  184. package/dist/graph/types.d.ts.map +1 -0
  185. package/dist/graph/types.js +50 -0
  186. package/dist/graph/types.js.map +1 -0
  187. package/dist/index.d.ts +45 -0
  188. package/dist/index.d.ts.map +1 -0
  189. package/dist/index.js +51 -0
  190. package/dist/index.js.map +1 -0
  191. package/dist/infra/aws/aws-parse.d.ts +39 -0
  192. package/dist/infra/aws/aws-parse.d.ts.map +1 -0
  193. package/dist/infra/aws/aws-parse.js +149 -0
  194. package/dist/infra/aws/aws-parse.js.map +1 -0
  195. package/dist/infra/aws/aws.d.ts +6 -0
  196. package/dist/infra/aws/aws.d.ts.map +1 -0
  197. package/dist/infra/aws/aws.js +425 -0
  198. package/dist/infra/aws/aws.js.map +1 -0
  199. package/dist/infra/azure/azure-parse.d.ts +73 -0
  200. package/dist/infra/azure/azure-parse.d.ts.map +1 -0
  201. package/dist/infra/azure/azure-parse.js +178 -0
  202. package/dist/infra/azure/azure-parse.js.map +1 -0
  203. package/dist/infra/azure/azure.d.ts +12 -0
  204. package/dist/infra/azure/azure.d.ts.map +1 -0
  205. package/dist/infra/azure/azure.js +673 -0
  206. package/dist/infra/azure/azure.js.map +1 -0
  207. package/dist/infra/cloudflare/cloudflare.d.ts +50 -0
  208. package/dist/infra/cloudflare/cloudflare.d.ts.map +1 -0
  209. package/dist/infra/cloudflare/cloudflare.js +382 -0
  210. package/dist/infra/cloudflare/cloudflare.js.map +1 -0
  211. package/dist/infra/cloudflare/wrangler-parse.d.ts +6 -0
  212. package/dist/infra/cloudflare/wrangler-parse.d.ts.map +1 -0
  213. package/dist/infra/cloudflare/wrangler-parse.js +278 -0
  214. package/dist/infra/cloudflare/wrangler-parse.js.map +1 -0
  215. package/dist/infra/compose/compose-parse.d.ts +24 -0
  216. package/dist/infra/compose/compose-parse.d.ts.map +1 -0
  217. package/dist/infra/compose/compose-parse.js +77 -0
  218. package/dist/infra/compose/compose-parse.js.map +1 -0
  219. package/dist/infra/compose/compose.d.ts +12 -0
  220. package/dist/infra/compose/compose.d.ts.map +1 -0
  221. package/dist/infra/compose/compose.js +201 -0
  222. package/dist/infra/compose/compose.js.map +1 -0
  223. package/dist/infra/convex/convex-parse.d.ts +28 -0
  224. package/dist/infra/convex/convex-parse.d.ts.map +1 -0
  225. package/dist/infra/convex/convex-parse.js +74 -0
  226. package/dist/infra/convex/convex-parse.js.map +1 -0
  227. package/dist/infra/convex/convex.d.ts +18 -0
  228. package/dist/infra/convex/convex.d.ts.map +1 -0
  229. package/dist/infra/convex/convex.js +199 -0
  230. package/dist/infra/convex/convex.js.map +1 -0
  231. package/dist/infra/digitalocean/digitalocean.d.ts +33 -0
  232. package/dist/infra/digitalocean/digitalocean.d.ts.map +1 -0
  233. package/dist/infra/digitalocean/digitalocean.js +204 -0
  234. package/dist/infra/digitalocean/digitalocean.js.map +1 -0
  235. package/dist/infra/firebase/firebase.d.ts +43 -0
  236. package/dist/infra/firebase/firebase.d.ts.map +1 -0
  237. package/dist/infra/firebase/firebase.js +271 -0
  238. package/dist/infra/firebase/firebase.js.map +1 -0
  239. package/dist/infra/fly/fly-parse.d.ts +52 -0
  240. package/dist/infra/fly/fly-parse.d.ts.map +1 -0
  241. package/dist/infra/fly/fly-parse.js +114 -0
  242. package/dist/infra/fly/fly-parse.js.map +1 -0
  243. package/dist/infra/fly/fly.d.ts +15 -0
  244. package/dist/infra/fly/fly.d.ts.map +1 -0
  245. package/dist/infra/fly/fly.js +265 -0
  246. package/dist/infra/fly/fly.js.map +1 -0
  247. package/dist/infra/gcp/gcp-parse.d.ts +24 -0
  248. package/dist/infra/gcp/gcp-parse.d.ts.map +1 -0
  249. package/dist/infra/gcp/gcp-parse.js +123 -0
  250. package/dist/infra/gcp/gcp-parse.js.map +1 -0
  251. package/dist/infra/gcp/gcp.d.ts +10 -0
  252. package/dist/infra/gcp/gcp.d.ts.map +1 -0
  253. package/dist/infra/gcp/gcp.js +502 -0
  254. package/dist/infra/gcp/gcp.js.map +1 -0
  255. package/dist/infra/heroku/heroku-parse.d.ts +33 -0
  256. package/dist/infra/heroku/heroku-parse.d.ts.map +1 -0
  257. package/dist/infra/heroku/heroku-parse.js +63 -0
  258. package/dist/infra/heroku/heroku-parse.js.map +1 -0
  259. package/dist/infra/heroku/heroku.d.ts +24 -0
  260. package/dist/infra/heroku/heroku.d.ts.map +1 -0
  261. package/dist/infra/heroku/heroku.js +253 -0
  262. package/dist/infra/heroku/heroku.js.map +1 -0
  263. package/dist/infra/image-resolve.d.ts +56 -0
  264. package/dist/infra/image-resolve.d.ts.map +1 -0
  265. package/dist/infra/image-resolve.js +229 -0
  266. package/dist/infra/image-resolve.js.map +1 -0
  267. package/dist/infra/infra-step.d.ts +39 -0
  268. package/dist/infra/infra-step.d.ts.map +1 -0
  269. package/dist/infra/infra-step.js +57 -0
  270. package/dist/infra/infra-step.js.map +1 -0
  271. package/dist/infra/k8s/index.d.ts +78 -0
  272. package/dist/infra/k8s/index.d.ts.map +1 -0
  273. package/dist/infra/k8s/index.js +251 -0
  274. package/dist/infra/k8s/index.js.map +1 -0
  275. package/dist/infra/kamal/kamal-parse.d.ts +23 -0
  276. package/dist/infra/kamal/kamal-parse.d.ts.map +1 -0
  277. package/dist/infra/kamal/kamal-parse.js +66 -0
  278. package/dist/infra/kamal/kamal-parse.js.map +1 -0
  279. package/dist/infra/kamal/kamal.d.ts +17 -0
  280. package/dist/infra/kamal/kamal.d.ts.map +1 -0
  281. package/dist/infra/kamal/kamal.js +162 -0
  282. package/dist/infra/kamal/kamal.js.map +1 -0
  283. package/dist/infra/netlify/netlify.d.ts +33 -0
  284. package/dist/infra/netlify/netlify.d.ts.map +1 -0
  285. package/dist/infra/netlify/netlify.js +247 -0
  286. package/dist/infra/netlify/netlify.js.map +1 -0
  287. package/dist/infra/opentofu/opentofu.d.ts +3 -0
  288. package/dist/infra/opentofu/opentofu.d.ts.map +1 -0
  289. package/dist/infra/opentofu/opentofu.js +157 -0
  290. package/dist/infra/opentofu/opentofu.js.map +1 -0
  291. package/dist/infra/pulumi/pulumi-parse.d.ts +60 -0
  292. package/dist/infra/pulumi/pulumi-parse.d.ts.map +1 -0
  293. package/dist/infra/pulumi/pulumi-parse.js +155 -0
  294. package/dist/infra/pulumi/pulumi-parse.js.map +1 -0
  295. package/dist/infra/pulumi/pulumi.d.ts +23 -0
  296. package/dist/infra/pulumi/pulumi.d.ts.map +1 -0
  297. package/dist/infra/pulumi/pulumi.js +260 -0
  298. package/dist/infra/pulumi/pulumi.js.map +1 -0
  299. package/dist/infra/railway/railway-parse.d.ts +54 -0
  300. package/dist/infra/railway/railway-parse.d.ts.map +1 -0
  301. package/dist/infra/railway/railway-parse.js +200 -0
  302. package/dist/infra/railway/railway-parse.js.map +1 -0
  303. package/dist/infra/railway/railway.d.ts +19 -0
  304. package/dist/infra/railway/railway.d.ts.map +1 -0
  305. package/dist/infra/railway/railway.js +397 -0
  306. package/dist/infra/railway/railway.js.map +1 -0
  307. package/dist/infra/register.d.ts +2 -0
  308. package/dist/infra/register.d.ts.map +1 -0
  309. package/dist/infra/register.js +81 -0
  310. package/dist/infra/register.js.map +1 -0
  311. package/dist/infra/registry.d.ts +64 -0
  312. package/dist/infra/registry.d.ts.map +1 -0
  313. package/dist/infra/registry.js +205 -0
  314. package/dist/infra/registry.js.map +1 -0
  315. package/dist/infra/relevance.d.ts +16 -0
  316. package/dist/infra/relevance.d.ts.map +1 -0
  317. package/dist/infra/relevance.js +132 -0
  318. package/dist/infra/relevance.js.map +1 -0
  319. package/dist/infra/render/render-parse.d.ts +76 -0
  320. package/dist/infra/render/render-parse.d.ts.map +1 -0
  321. package/dist/infra/render/render-parse.js +155 -0
  322. package/dist/infra/render/render-parse.js.map +1 -0
  323. package/dist/infra/render/render.d.ts +11 -0
  324. package/dist/infra/render/render.d.ts.map +1 -0
  325. package/dist/infra/render/render.js +303 -0
  326. package/dist/infra/render/render.js.map +1 -0
  327. package/dist/infra/sst/sst-parse.d.ts +25 -0
  328. package/dist/infra/sst/sst-parse.d.ts.map +1 -0
  329. package/dist/infra/sst/sst-parse.js +45 -0
  330. package/dist/infra/sst/sst-parse.js.map +1 -0
  331. package/dist/infra/sst/sst.d.ts +19 -0
  332. package/dist/infra/sst/sst.d.ts.map +1 -0
  333. package/dist/infra/sst/sst.js +236 -0
  334. package/dist/infra/sst/sst.js.map +1 -0
  335. package/dist/infra/supabase/supabase-parse.d.ts +34 -0
  336. package/dist/infra/supabase/supabase-parse.d.ts.map +1 -0
  337. package/dist/infra/supabase/supabase-parse.js +113 -0
  338. package/dist/infra/supabase/supabase-parse.js.map +1 -0
  339. package/dist/infra/supabase/supabase.d.ts +15 -0
  340. package/dist/infra/supabase/supabase.d.ts.map +1 -0
  341. package/dist/infra/supabase/supabase.js +198 -0
  342. package/dist/infra/supabase/supabase.js.map +1 -0
  343. package/dist/infra/terraform/hcl-parse.d.ts +34 -0
  344. package/dist/infra/terraform/hcl-parse.d.ts.map +1 -0
  345. package/dist/infra/terraform/hcl-parse.js +203 -0
  346. package/dist/infra/terraform/hcl-parse.js.map +1 -0
  347. package/dist/infra/terraform/terraform.d.ts +14 -0
  348. package/dist/infra/terraform/terraform.d.ts.map +1 -0
  349. package/dist/infra/terraform/terraform.js +264 -0
  350. package/dist/infra/terraform/terraform.js.map +1 -0
  351. package/dist/infra/types.d.ts +151 -0
  352. package/dist/infra/types.d.ts.map +1 -0
  353. package/dist/infra/types.js +14 -0
  354. package/dist/infra/types.js.map +1 -0
  355. package/dist/infra/vercel/vercel-parse.d.ts +70 -0
  356. package/dist/infra/vercel/vercel-parse.d.ts.map +1 -0
  357. package/dist/infra/vercel/vercel-parse.js +194 -0
  358. package/dist/infra/vercel/vercel-parse.js.map +1 -0
  359. package/dist/infra/vercel/vercel.d.ts +30 -0
  360. package/dist/infra/vercel/vercel.d.ts.map +1 -0
  361. package/dist/infra/vercel/vercel.js +523 -0
  362. package/dist/infra/vercel/vercel.js.map +1 -0
  363. package/dist/infra/walk.d.ts +36 -0
  364. package/dist/infra/walk.d.ts.map +1 -0
  365. package/dist/infra/walk.js +85 -0
  366. package/dist/infra/walk.js.map +1 -0
  367. package/dist/safety.d.ts +13 -0
  368. package/dist/safety.d.ts.map +1 -0
  369. package/dist/safety.js +67 -0
  370. package/dist/safety.js.map +1 -0
  371. package/dist/types.d.ts +47 -0
  372. package/dist/types.d.ts.map +1 -0
  373. package/dist/types.js +111 -0
  374. package/dist/types.js.map +1 -0
  375. package/dist/version.d.ts +2 -0
  376. package/dist/version.d.ts.map +1 -0
  377. package/dist/version.js +35 -0
  378. package/dist/version.js.map +1 -0
  379. package/package.json +65 -0
@@ -0,0 +1,673 @@
1
+ // Azure InfraAdapter (v0).
2
+ //
3
+ // Multi-config cluster adapter. Parses:
4
+ // • ARM JSON templates (`$schema` deploymentTemplate or Microsoft.* resources[])
5
+ // • Bicep (light) (regex-only declarations; full DSL evaluation DEFERRED)
6
+ // • Azure Functions (function.json / host.json)
7
+ // • AKS / k8s manifests (Deployment / Service / Ingress YAML)
8
+ //
9
+ // App Service slot config beyond presence is DEFERRED.
10
+ //
11
+ // Node kinds emitted:
12
+ // worker — Microsoft.Web/sites (App), MS Functions, k8s Deployment,
13
+ // Azure Function (from function.json)
14
+ // queue — Microsoft.ServiceBus/*, Microsoft.EventHub/*,
15
+ // Microsoft.EventGrid/*, Storage Queues
16
+ // datastore — Microsoft.Storage/*, Microsoft.Sql/*, Microsoft.DocumentDB/*,
17
+ // Microsoft.Cache/Redis, Microsoft.DBfor*, Microsoft.DBforMySQL/*,
18
+ // Microsoft.DBforPostgreSQL/*
19
+ // secret-store — Microsoft.KeyVault/vaults, Microsoft.AppConfiguration/*
20
+ // container — Microsoft.ContainerService/*, Microsoft.ContainerInstance/*
21
+ // cdn — Microsoft.Cdn/*, Microsoft.FrontDoor/*,
22
+ // Microsoft.Network/frontDoors
23
+ // external-api — Microsoft.CognitiveServices/* (Paid AI)
24
+ // static-site — Microsoft.Web/staticSites
25
+ //
26
+ // classificationsNeeded:
27
+ // One per ARM/Bicep resource. provider `azure/arm` — shares the azure
28
+ // taxonomy with Terraform's `azurerm_*` entries (same LLM classify cache).
29
+ //
30
+ // Edges:
31
+ // calls — ARM rawText cross-references (resourceId / dependsOn /
32
+ // symbolic name), ARM → k8s AKS cluster, Service→Deployment
33
+ // routing, Ingress→Service routing
34
+ // subscribes — Azure Function with queueTrigger / serviceBusTrigger binding
35
+ // writes — Azure Function with queue / blob / cosmosDB output binding
36
+ // stores-in — Azure Function with cosmosDB trigger / blob output
37
+ //
38
+ // v0 scope notes (all DEFERRED):
39
+ // • Full Bicep DSL expression evaluation (parameters, variables, `if()`)
40
+ // • App Service deployment slot config (beyond structural node presence)
41
+ // • Module recursion for Bicep module declarations
42
+ // • Cross-manifest k8s label matching beyond selector name alignment
43
+ // • Azure Policy / Management Group / Monitor resources (emit with heuristic kind)
44
+ import { readFileSync } from 'node:fs';
45
+ import { basename, relative } from 'node:path';
46
+ import { walkRepo } from '../walk.js';
47
+ import { workloadSourceRoots } from '../k8s/index.js';
48
+ import { buildDockerfileIndex, resolveImageToSourceRoots } from '../image-resolve.js';
49
+ import { parseArmTemplate, parseBicep, parseFunctionJson, parseHostJson, parseAksYaml, isArmTemplate, } from './azure-parse.js';
50
+ // ---------------------------------------------------------------------------
51
+ // Filesystem walk
52
+ const AZURE_SKIP_DIRS = [
53
+ 'node_modules',
54
+ '.git',
55
+ 'dist',
56
+ '.wrangler',
57
+ '.terraform',
58
+ '.next',
59
+ 'build',
60
+ 'coverage',
61
+ 'vendor',
62
+ '__pycache__',
63
+ ];
64
+ function findAzureFiles(repoDir) {
65
+ const result = { arm: [], bicep: [], functionJson: [], hostJson: [], aksYaml: [] };
66
+ walkRepo(repoDir, {
67
+ skipDirs: AZURE_SKIP_DIRS,
68
+ onFile: (abs, e) => {
69
+ if (e.name.endsWith('.bicep')) {
70
+ result.bicep.push(abs);
71
+ }
72
+ else if (e.name === 'function.json') {
73
+ result.functionJson.push(abs);
74
+ }
75
+ else if (e.name === 'host.json') {
76
+ result.hostJson.push(abs);
77
+ }
78
+ else if (e.name.endsWith('.yaml') || e.name.endsWith('.yml')) {
79
+ result.aksYaml.push(abs);
80
+ }
81
+ else if (e.name.endsWith('.json') && e.name !== 'function.json' && e.name !== 'host.json') {
82
+ result.arm.push(abs);
83
+ }
84
+ },
85
+ });
86
+ return result;
87
+ }
88
+ const ARM_KIND_RULES = [
89
+ // Functions / App Service compute
90
+ { re: /^Microsoft\.Web\/sites\/functions$/i, kind: 'worker' },
91
+ { re: /^Microsoft\.Web\/sites$/i, kind: 'worker' },
92
+ { re: /^Microsoft\.Web\/staticSites$/i, kind: 'static-site' },
93
+ { re: /^Microsoft\.Web\/serverfarms$/i, kind: 'worker' }, // App Service plan — compute host
94
+ // Azure Functions standalone resource type (legacy / early naming)
95
+ { re: /^Microsoft\.Functions\//i, kind: 'worker' },
96
+ // Messaging / eventing
97
+ { re: /^Microsoft\.ServiceBus\//i, kind: 'queue' },
98
+ { re: /^Microsoft\.EventHub\//i, kind: 'queue' },
99
+ { re: /^Microsoft\.EventGrid\//i, kind: 'queue' },
100
+ // Container services
101
+ { re: /^Microsoft\.ContainerService\//i, kind: 'container' },
102
+ { re: /^Microsoft\.ContainerInstance\//i, kind: 'container' },
103
+ { re: /^Microsoft\.ContainerRegistry\//i, kind: 'container' },
104
+ // Storage / datastores
105
+ { re: /^Microsoft\.Storage\//i, kind: 'datastore' },
106
+ { re: /^Microsoft\.Sql\//i, kind: 'datastore' },
107
+ { re: /^Microsoft\.DocumentDB\//i, kind: 'datastore' }, // Cosmos DB
108
+ { re: /^Microsoft\.Cache\/Redis/i, kind: 'datastore' },
109
+ { re: /^Microsoft\.DBforMySQL\//i, kind: 'datastore' },
110
+ { re: /^Microsoft\.DBforPostgreSQL\//i, kind: 'datastore' },
111
+ { re: /^Microsoft\.DBforMariaDB\//i, kind: 'datastore' },
112
+ { re: /^Microsoft\.Synapse\//i, kind: 'datastore' },
113
+ { re: /^Microsoft\.DataFactory\//i, kind: 'datastore' },
114
+ // Secret / config stores
115
+ { re: /^Microsoft\.KeyVault\//i, kind: 'secret-store' },
116
+ { re: /^Microsoft\.AppConfiguration\//i, kind: 'secret-store' },
117
+ // CDN / edge
118
+ { re: /^Microsoft\.Cdn\//i, kind: 'cdn' },
119
+ { re: /^Microsoft\.Network\/frontDoors/i, kind: 'cdn' },
120
+ { re: /^Microsoft\.FrontDoor\//i, kind: 'cdn' },
121
+ // Paid AI services
122
+ { re: /^Microsoft\.CognitiveServices\//i, kind: 'external-api' },
123
+ { re: /^Microsoft\.MachineLearning\//i, kind: 'external-api' },
124
+ { re: /^Microsoft\.MachineLearningServices\//i, kind: 'external-api' },
125
+ // Search
126
+ { re: /^Microsoft\.Search\//i, kind: 'external-api' },
127
+ ];
128
+ function heuristicArmKind(resourceType, armKind) {
129
+ for (const rule of ARM_KIND_RULES) {
130
+ if (rule.re.test(resourceType)) {
131
+ // Microsoft.Web/sites with kind='functionapp' stays 'worker' — same Backthread
132
+ // module kind as a plain App Service site. We don't demote or re-classify;
133
+ // the distinction is surfaced in node metadata (armKind) so the LLM
134
+ // classifier can annotate it further. Both are compute, both are worker.
135
+ void armKind; // acknowledged — no kind override needed for current rules
136
+ return { kind: rule.kind };
137
+ }
138
+ }
139
+ return { kind: 'datastore' }; // least-bad fallback (see Terraform adapter rationale)
140
+ }
141
+ // ---------------------------------------------------------------------------
142
+ // Node-id helpers (adapter-local; registry prefixes `azure:`)
143
+ const armNodeId = (type, name) => `arm:${type.replace(/\s+/g, '_')}/${name}`;
144
+ const bicepNodeId = (symbolicName) => `bicep:${symbolicName}`;
145
+ const funcNodeId = (fnName) => `func:${fnName}`;
146
+ const k8sDeploymentId = (name) => `k8s:deployment:${name}`;
147
+ const k8sServiceId = (name) => `k8s:service:${name}`;
148
+ // ---------------------------------------------------------------------------
149
+ // Source-root helpers.
150
+ /** Normalize a repo-relative path: backslashes→/, collapse `.`/`./`, strip trailing `/`. */
151
+ function normalizeRoot(p) {
152
+ return p.replace(/\\/g, '/').replace(/^\.(?:\/|$)/, '').replace(/\/+$/, '');
153
+ }
154
+ /**
155
+ * Resolve container image refs out of an ARM/Bicep resource's raw text (ARM
156
+ * `"image": "…"` JSON or Bicep `image: '…'`) via the resolver. Only
157
+ * plain literal refs — an ARM/Bicep expression (`[concat(…)]`, `${…}`,
158
+ * `resourceId(…)`) is skipped (unresolvable → honest "Other", never guess).
159
+ */
160
+ function azureImageRoots(rawText, index) {
161
+ if (!index)
162
+ return [];
163
+ const roots = new Set();
164
+ const re = /(?:"image"|\bimage)\s*:\s*['"]([^'"]+)['"]/gi;
165
+ let m;
166
+ while ((m = re.exec(rawText)) !== null) {
167
+ const v = m[1];
168
+ if (!v || /[[\]${}()]/.test(v))
169
+ continue; // an expression, not a literal image
170
+ for (const r of resolveImageToSourceRoots(v, index))
171
+ roots.add(r);
172
+ }
173
+ return [...roots].sort();
174
+ }
175
+ export function buildAzureGraph(inputs, root, dockerfileIndex) {
176
+ const nodes = new Map();
177
+ const edges = [];
178
+ const classificationsNeeded = [];
179
+ const seen = new Set(); // dedup edges: `${source}→${target}→${kind}`
180
+ const addNode = (n) => {
181
+ if (!nodes.has(n.id))
182
+ nodes.set(n.id, n);
183
+ };
184
+ const addEdge = (e) => {
185
+ const key = `${e.source}→${e.target}→${e.kind}`;
186
+ if (e.source === e.target)
187
+ return;
188
+ if (seen.has(key))
189
+ return;
190
+ seen.add(key);
191
+ edges.push(e);
192
+ };
193
+ // -------------------------------------------------------------------------
194
+ // 1. ARM resources
195
+ for (const r of inputs.armResources) {
196
+ const id = armNodeId(r.type, r.name);
197
+ const { kind } = heuristicArmKind(r.type, r.armKind);
198
+ // container resources (Container Apps/Instances) reference an
199
+ // image; resolve it to a build context.
200
+ const roots = /container/i.test(r.type) ? azureImageRoots(r.rawText, dockerfileIndex) : [];
201
+ addNode({
202
+ id,
203
+ label: r.name || r.type,
204
+ kind,
205
+ provenance: 'inferred', // upgraded to llm-classified by classify step
206
+ metadata: {
207
+ provider: 'azure/arm',
208
+ resourceType: r.type,
209
+ ...(r.armKind !== undefined ? { armKind: r.armKind } : {}),
210
+ },
211
+ ...(roots.length ? { sourceRoots: roots } : {}),
212
+ });
213
+ classificationsNeeded.push({
214
+ provider: 'azure/arm',
215
+ resourceType: r.type,
216
+ forNodeId: id,
217
+ });
218
+ }
219
+ // ARM cross-resource edges: scan each resource's rawText for references to
220
+ // other resources' names. Uses `calls` (structural dependency, honest verb
221
+ // without knowing the actual runtime relationship — mirrors Terraform adapter).
222
+ for (const src of inputs.armResources) {
223
+ const srcId = armNodeId(src.type, src.name);
224
+ for (const tgt of inputs.armResources) {
225
+ if (src === tgt)
226
+ continue;
227
+ const tgtId = armNodeId(tgt.type, tgt.name);
228
+ if (armTextReferences(src.rawText, tgt)) {
229
+ addEdge({ source: srcId, target: tgtId, kind: 'calls', metadata: { via: 'arm-ref' } });
230
+ }
231
+ }
232
+ }
233
+ // -------------------------------------------------------------------------
234
+ // 2. Bicep resources (light regex extraction)
235
+ for (const r of inputs.bicepResources) {
236
+ if (r.isModule) {
237
+ // Module declarations: emit as worker (they wrap compute), provenance inferred.
238
+ // We don't know the type from the path — no classificationsNeeded emitted.
239
+ addNode({
240
+ id: bicepNodeId(r.symbolicName),
241
+ label: r.symbolicName,
242
+ kind: 'worker',
243
+ provenance: 'inferred',
244
+ metadata: { provider: 'azure/bicep', bicepPath: r.type, isModule: true },
245
+ });
246
+ continue;
247
+ }
248
+ const id = bicepNodeId(r.symbolicName);
249
+ const { kind } = heuristicArmKind(r.type);
250
+ const roots = /container/i.test(r.type) ? azureImageRoots(r.rawText, dockerfileIndex) : [];
251
+ addNode({
252
+ id,
253
+ label: r.symbolicName,
254
+ kind,
255
+ provenance: 'inferred',
256
+ metadata: {
257
+ provider: 'azure/arm', // intentionally azure/arm — same LLM classify cache
258
+ resourceType: r.type,
259
+ apiVersion: r.apiVersion,
260
+ },
261
+ ...(roots.length ? { sourceRoots: roots } : {}),
262
+ });
263
+ classificationsNeeded.push({
264
+ provider: 'azure/arm',
265
+ resourceType: r.type,
266
+ forNodeId: id,
267
+ });
268
+ }
269
+ // Bicep cross-resource edges (symbolic name references in rawText).
270
+ for (const src of inputs.bicepResources) {
271
+ const srcId = bicepNodeId(src.symbolicName);
272
+ for (const tgt of inputs.bicepResources) {
273
+ if (src === tgt)
274
+ continue;
275
+ const tgtId = bicepNodeId(tgt.symbolicName);
276
+ if (rawTextReferencesSymbol(src.rawText, tgt.symbolicName)) {
277
+ addEdge({ source: srcId, target: tgtId, kind: 'calls', metadata: { via: 'bicep-ref' } });
278
+ }
279
+ }
280
+ }
281
+ // -------------------------------------------------------------------------
282
+ // 3. Azure Functions
283
+ for (const fn of inputs.functionJsons) {
284
+ const fnId = funcNodeId(fn.functionName);
285
+ // Every function → worker node (provenance: declared — function.json IS the declaration)
286
+ // the function's folder (holding function.json) is its source root.
287
+ const fnRoots = fn.sourceDir ? [normalizeRoot(fn.sourceDir)].filter((d) => d.length > 0) : [];
288
+ addNode({
289
+ id: fnId,
290
+ label: fn.functionName,
291
+ kind: 'worker',
292
+ provenance: 'declared',
293
+ metadata: { provider: 'azure/functions', source: 'function.json' },
294
+ ...(fnRoots.length ? { sourceRoots: fnRoots } : {}),
295
+ });
296
+ // Bindings → edges
297
+ for (const binding of fn.bindings) {
298
+ const bType = binding.type.toLowerCase();
299
+ if (bType === 'httptrigger' || bType === 'http') {
300
+ // httpTrigger = this function IS an HTTP endpoint — no structural edge needed.
301
+ // http output binding = response — also no separate node.
302
+ continue;
303
+ }
304
+ if (bType === 'queuetrigger' || bType === 'servicebustrigger' || bType === 'eventhubstrigger') {
305
+ // This function SUBSCRIBES to a queue/topic.
306
+ const resourceName = binding.queueName ?? binding.topicName ?? binding.connection ?? bType;
307
+ const queueId = `queue:func-queue:${resourceName}`;
308
+ addNode({
309
+ id: queueId,
310
+ label: resourceName,
311
+ kind: 'queue',
312
+ provenance: 'inferred',
313
+ metadata: { provider: 'azure/functions', bindingType: binding.type },
314
+ });
315
+ addEdge({
316
+ source: fnId,
317
+ target: queueId,
318
+ kind: 'subscribes',
319
+ metadata: { binding: binding.name, bindingType: binding.type },
320
+ });
321
+ continue;
322
+ }
323
+ if (bType === 'timertrigger') {
324
+ // Timer trigger: no structural target node — cron schedule.
325
+ continue;
326
+ }
327
+ if (bType === 'blobtrigger') {
328
+ // Blob trigger: the function reads from storage.
329
+ const resourceName = binding.connection ?? 'blob-storage';
330
+ const blobId = `datastore:func-blob:${resourceName}`;
331
+ addNode({
332
+ id: blobId,
333
+ label: resourceName,
334
+ kind: 'datastore',
335
+ provenance: 'inferred',
336
+ metadata: { provider: 'azure/functions', bindingType: 'blobTrigger' },
337
+ });
338
+ addEdge({
339
+ source: fnId,
340
+ target: blobId,
341
+ kind: 'reads',
342
+ metadata: { binding: binding.name, bindingType: binding.type },
343
+ });
344
+ continue;
345
+ }
346
+ if (bType === 'cosmosdbtrigger') {
347
+ // CosmosDB trigger: subscribes to change feed → treat as reads from datastore.
348
+ const resourceName = binding.connection ?? 'cosmos-db';
349
+ const cosmosId = `datastore:func-cosmos:${resourceName}`;
350
+ addNode({
351
+ id: cosmosId,
352
+ label: resourceName,
353
+ kind: 'datastore',
354
+ provenance: 'inferred',
355
+ metadata: { provider: 'azure/functions', bindingType: 'cosmosDBTrigger' },
356
+ });
357
+ addEdge({
358
+ source: fnId,
359
+ target: cosmosId,
360
+ kind: 'reads',
361
+ metadata: { binding: binding.name, bindingType: binding.type },
362
+ });
363
+ continue;
364
+ }
365
+ // Output bindings (direction === 'out')
366
+ if (binding.direction === 'out') {
367
+ if (bType === 'queue' || bType === 'servicebus' || bType === 'eventhub') {
368
+ const resourceName = binding.queueName ?? binding.topicName ?? binding.connection ?? bType;
369
+ const queueId = `queue:func-queue:${resourceName}`;
370
+ addNode({
371
+ id: queueId,
372
+ label: resourceName,
373
+ kind: 'queue',
374
+ provenance: 'inferred',
375
+ metadata: { provider: 'azure/functions', bindingType: binding.type },
376
+ });
377
+ addEdge({
378
+ source: fnId,
379
+ target: queueId,
380
+ kind: 'writes',
381
+ metadata: { binding: binding.name, bindingType: binding.type },
382
+ });
383
+ }
384
+ else if (bType === 'blob' || bType === 'table') {
385
+ const resourceName = binding.connection ?? 'blob-storage';
386
+ const blobId = `datastore:func-blob:${resourceName}`;
387
+ addNode({
388
+ id: blobId,
389
+ label: resourceName,
390
+ kind: 'datastore',
391
+ provenance: 'inferred',
392
+ metadata: { provider: 'azure/functions', bindingType: binding.type },
393
+ });
394
+ addEdge({
395
+ source: fnId,
396
+ target: blobId,
397
+ kind: 'stores-in',
398
+ metadata: { binding: binding.name, bindingType: binding.type },
399
+ });
400
+ }
401
+ else if (bType === 'cosmosdb') {
402
+ const resourceName = binding.connection ?? 'cosmos-db';
403
+ const cosmosId = `datastore:func-cosmos:${resourceName}`;
404
+ addNode({
405
+ id: cosmosId,
406
+ label: resourceName,
407
+ kind: 'datastore',
408
+ provenance: 'inferred',
409
+ metadata: { provider: 'azure/functions', bindingType: 'cosmosDB' },
410
+ });
411
+ addEdge({
412
+ source: fnId,
413
+ target: cosmosId,
414
+ kind: 'stores-in',
415
+ metadata: { binding: binding.name, bindingType: binding.type },
416
+ });
417
+ }
418
+ }
419
+ }
420
+ }
421
+ // -------------------------------------------------------------------------
422
+ // 4. AKS / k8s manifests
423
+ const k8sDeployments = new Map();
424
+ const k8sServices = new Map();
425
+ for (const manifest of inputs.k8sManifests) {
426
+ const kind = manifest.kind;
427
+ if (kind === 'Deployment' || kind === 'StatefulSet' || kind === 'DaemonSet') {
428
+ const id = k8sDeploymentId(manifest.name);
429
+ // attribute the AKS workload's code via its container image(s).
430
+ const roots = dockerfileIndex ? workloadSourceRoots(manifest.rawObj, dockerfileIndex) : [];
431
+ addNode({
432
+ id,
433
+ label: manifest.name,
434
+ kind: 'container',
435
+ provenance: 'declared',
436
+ metadata: {
437
+ provider: 'azure/aks',
438
+ k8sKind: kind,
439
+ namespace: manifest.namespace,
440
+ },
441
+ ...(roots.length ? { sourceRoots: roots } : {}),
442
+ });
443
+ k8sDeployments.set(manifest.name, manifest);
444
+ }
445
+ else if (kind === 'Service') {
446
+ k8sServices.set(manifest.name, manifest);
447
+ // Service itself is routing metadata — not a separate node; becomes edges below.
448
+ }
449
+ else if (kind === 'Ingress') {
450
+ // Ingress → service → deployment chain.
451
+ for (const backend of manifest.ingressBackends ?? []) {
452
+ const svc = k8sServices.get(backend);
453
+ if (svc?.selector) {
454
+ // Find a Deployment that matches the selector (simple name heuristic).
455
+ for (const [depName] of k8sDeployments) {
456
+ if (Object.values(svc.selector).some((v) => v === depName || depName.startsWith(v))) {
457
+ addEdge({
458
+ source: k8sDeploymentId(manifest.name + '-ingress'),
459
+ target: k8sDeploymentId(depName),
460
+ kind: 'calls',
461
+ metadata: { via: 'ingress→service→deployment' },
462
+ });
463
+ }
464
+ }
465
+ }
466
+ }
467
+ }
468
+ }
469
+ // Service routing: a Service with selector → calls the matching Deployment.
470
+ for (const [svcName, svc] of k8sServices) {
471
+ if (!svc.selector)
472
+ continue;
473
+ for (const [depName] of k8sDeployments) {
474
+ // Heuristic: if the deployment name matches the service name or any selector value.
475
+ if (depName === svcName ||
476
+ Object.values(svc.selector).some((v) => v === depName || depName.startsWith(v))) {
477
+ // A Service routes TO a Deployment — express as `calls`.
478
+ addEdge({
479
+ source: k8sServiceId(svcName),
480
+ target: k8sDeploymentId(depName),
481
+ kind: 'calls',
482
+ metadata: { via: 'k8s-service-selector' },
483
+ });
484
+ }
485
+ }
486
+ }
487
+ // ARM → AKS cluster: ARM ContainerService/managedClusters resources `calls`
488
+ // k8s Deployment nodes found in the same repo — the ARM template manages them.
489
+ const armAksNodes = [...nodes.values()].filter((n) => n.kind === 'container' && n.provenance === 'inferred');
490
+ const aksDeploymentNodes = [...nodes.values()].filter((n) => n.kind === 'container' && n.provenance === 'declared');
491
+ if (armAksNodes.length > 0 && aksDeploymentNodes.length > 0) {
492
+ for (const aksArm of armAksNodes) {
493
+ for (const dep of aksDeploymentNodes) {
494
+ addEdge({ source: aksArm.id, target: dep.id, kind: 'calls', metadata: { via: 'aks-manages' } });
495
+ }
496
+ }
497
+ }
498
+ return {
499
+ root,
500
+ adapter: 'azure',
501
+ nodes: [...nodes.values()],
502
+ edges,
503
+ classificationsNeeded,
504
+ };
505
+ }
506
+ // ---------------------------------------------------------------------------
507
+ // Reference scanning helpers
508
+ /**
509
+ * Determine whether an ARM resource's rawText references the target — by name,
510
+ * resourceId() call, or dependsOn. Bias: MISS over INVENT (same as Terraform).
511
+ */
512
+ function armTextReferences(rawText, target) {
513
+ if (!target.name)
514
+ return false;
515
+ // Look for the name outside of description/comments heuristic:
516
+ // In JSON rawText the name always appears as a JSON string value `"<name>"`
517
+ // so we require quote delimiters which greatly reduces prose false positives.
518
+ // Also look for resourceId references that include the type or name.
519
+ const quotedName = `"${target.name}"`;
520
+ const typeRef = target.type.toLowerCase();
521
+ // Only fire if either the quoted name appears somewhere meaningful or
522
+ // a resourceId pattern with the type shows up.
523
+ if (rawText.includes(quotedName)) {
524
+ // Additional guard: the name reference must not only appear as the resource's
525
+ // own `"name"` key value — but we can't easily avoid that without a full JSON
526
+ // walk. Accept the false positive rate as acceptable for v0 (same as TF adapter).
527
+ return true;
528
+ }
529
+ // resourceId("Microsoft.X/Y", ...) references.
530
+ if (rawText.toLowerCase().includes(`resourceid("${typeRef}`))
531
+ return true;
532
+ return false;
533
+ }
534
+ /**
535
+ * Whether rawText references the Bicep symbolic name as a traversal.
536
+ * Requires the name to appear at a word boundary (not as a substring of
537
+ * another identifier).
538
+ */
539
+ function rawTextReferencesSymbol(rawText, symbolicName) {
540
+ if (!symbolicName)
541
+ return false;
542
+ // Bicep references look like `symbolicName.property` or `${symbolicName.x}`.
543
+ const re = new RegExp(`(?<![\\w])${symbolicName}(?=\\.)`, '');
544
+ return re.test(rawText);
545
+ }
546
+ // ---------------------------------------------------------------------------
547
+ // Detect helpers: identify Azure-bearing files without reading them
548
+ function looksLikeArmTemplate(text) {
549
+ const parsed = tryParseJson(text);
550
+ if (parsed === null)
551
+ return false;
552
+ return isArmTemplate(parsed);
553
+ }
554
+ function tryParseJson(text) {
555
+ try {
556
+ return JSON.parse(text);
557
+ }
558
+ catch {
559
+ return null;
560
+ }
561
+ }
562
+ // ---------------------------------------------------------------------------
563
+ // InfraAdapter
564
+ /** Detect: true if the repo contains at least one recognizable Azure surface. */
565
+ async function detectAzure(repoDir) {
566
+ const files = findAzureFiles(repoDir);
567
+ if (files.bicep.length > 0)
568
+ return true;
569
+ if (files.functionJson.length > 0)
570
+ return true;
571
+ // Check for ARM templates among JSON files (don't read all JSON — check a few).
572
+ for (const file of files.arm.slice(0, 20)) {
573
+ try {
574
+ const text = readFileSync(file, 'utf8');
575
+ if (looksLikeArmTemplate(text))
576
+ return true;
577
+ }
578
+ catch {
579
+ // skip unreadable
580
+ }
581
+ }
582
+ // Check for k8s manifests among YAML files (check a few).
583
+ for (const file of files.aksYaml.slice(0, 20)) {
584
+ try {
585
+ const text = readFileSync(file, 'utf8');
586
+ const docs = parseAksYaml(text);
587
+ if (docs.length > 0)
588
+ return true;
589
+ }
590
+ catch {
591
+ // skip
592
+ }
593
+ }
594
+ return false;
595
+ }
596
+ /** Extract: walk all Azure-relevant files and build the InfraGraph. */
597
+ async function extractAzure(repoDir) {
598
+ const files = findAzureFiles(repoDir);
599
+ const inputs = {
600
+ armResources: [],
601
+ bicepResources: [],
602
+ functionJsons: [],
603
+ k8sManifests: [],
604
+ };
605
+ // ARM JSON
606
+ for (const file of files.arm) {
607
+ try {
608
+ const text = readFileSync(file, 'utf8');
609
+ const resources = parseArmTemplate(text);
610
+ if (resources.length > 0)
611
+ inputs.armResources.push(...resources);
612
+ }
613
+ catch (err) {
614
+ console.warn(` [azure] skipping unparseable ${relative(repoDir, file)}: ${err.message}`);
615
+ }
616
+ }
617
+ // Bicep
618
+ for (const file of files.bicep) {
619
+ try {
620
+ const text = readFileSync(file, 'utf8');
621
+ inputs.bicepResources.push(...parseBicep(text));
622
+ }
623
+ catch (err) {
624
+ console.warn(` [azure] skipping unparseable ${relative(repoDir, file)}: ${err.message}`);
625
+ }
626
+ }
627
+ // Azure Functions
628
+ for (const file of files.functionJson) {
629
+ try {
630
+ const text = readFileSync(file, 'utf8');
631
+ // Function name = parent directory name.
632
+ const fnDirAbs = file.slice(0, -'/function.json'.length);
633
+ const fnName = basename(fnDirAbs);
634
+ const parsed = parseFunctionJson(text, fnName);
635
+ if (parsed) {
636
+ // the function's folder (repo-relative) is its source root.
637
+ parsed.sourceDir = (relative(repoDir, fnDirAbs) || '').split('\\').join('/');
638
+ inputs.functionJsons.push(parsed);
639
+ }
640
+ }
641
+ catch (err) {
642
+ console.warn(` [azure] skipping unparseable ${relative(repoDir, file)}: ${err.message}`);
643
+ }
644
+ }
645
+ // host.json presence is a detect signal only; we don't need to parse it for topology.
646
+ for (const file of files.hostJson) {
647
+ try {
648
+ parseHostJson(readFileSync(file, 'utf8'));
649
+ }
650
+ catch (err) {
651
+ console.warn(` [azure] skipping unparseable ${relative(repoDir, file)}: ${err.message}`);
652
+ }
653
+ }
654
+ // AKS YAML
655
+ for (const file of files.aksYaml) {
656
+ try {
657
+ const text = readFileSync(file, 'utf8');
658
+ const manifests = parseAksYaml(text);
659
+ inputs.k8sManifests.push(...manifests);
660
+ }
661
+ catch (err) {
662
+ console.warn(` [azure] skipping unparseable ${relative(repoDir, file)}: ${err.message}`);
663
+ }
664
+ }
665
+ // Dockerfile index for AKS workload image→source attribution.
666
+ return buildAzureGraph(inputs, repoDir, buildDockerfileIndex(repoDir));
667
+ }
668
+ export const azureAdapter = {
669
+ name: 'azure',
670
+ detect: detectAzure,
671
+ extract: extractAzure,
672
+ };
673
+ //# sourceMappingURL=azure.js.map