@intentius/chant-lexicon-terraform 0.124.52 → 0.124.55

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 (641) hide show
  1. package/README.md +14 -10
  2. package/dist/__fixtures__/pr-loop/estate.component.d.ts +7 -0
  3. package/dist/__fixtures__/pr-loop/estate.component.d.ts.map +1 -0
  4. package/dist/__fixtures__/pr-loop/estate.component.js +7 -0
  5. package/dist/__fixtures__/report/generate.d.ts +26 -0
  6. package/dist/__fixtures__/report/generate.d.ts.map +1 -0
  7. package/dist/__fixtures__/report/generate.js +58 -0
  8. package/dist/applied-state.d.ts +27 -0
  9. package/dist/applied-state.d.ts.map +1 -0
  10. package/dist/applied-state.js +44 -0
  11. package/dist/backend-config.d.ts +53 -0
  12. package/dist/backend-config.d.ts.map +1 -0
  13. package/dist/backend-config.js +136 -0
  14. package/dist/behaviour/kinds.d.ts.map +1 -1
  15. package/dist/behaviour/kinds.js +4 -0
  16. package/dist/behaviour/predict.d.ts.map +1 -1
  17. package/dist/behaviour/predict.js +6 -2
  18. package/dist/behaviour/reference-catalog.d.ts +16 -5
  19. package/dist/behaviour/reference-catalog.d.ts.map +1 -1
  20. package/dist/behaviour/reference-catalog.js +16 -5
  21. package/dist/behaviour/request.d.ts.map +1 -1
  22. package/dist/behaviour/request.js +3 -2
  23. package/dist/changed-roots.d.ts +6 -4
  24. package/dist/changed-roots.d.ts.map +1 -1
  25. package/dist/changed-roots.js +14 -18
  26. package/dist/ci-setup.d.ts +11 -0
  27. package/dist/ci-setup.d.ts.map +1 -0
  28. package/dist/ci-setup.js +41 -0
  29. package/dist/commands.d.ts.map +1 -1
  30. package/dist/commands.js +4 -3
  31. package/dist/components/capability-plugin.d.ts +105 -9
  32. package/dist/components/capability-plugin.d.ts.map +1 -1
  33. package/dist/components/capability-plugin.js +357 -36
  34. package/dist/components/compose-group.d.ts +145 -0
  35. package/dist/components/compose-group.d.ts.map +1 -0
  36. package/dist/components/compose-group.js +407 -0
  37. package/dist/components/placeholder-preview.d.ts +78 -0
  38. package/dist/components/placeholder-preview.d.ts.map +1 -0
  39. package/dist/components/placeholder-preview.js +254 -0
  40. package/dist/components/release-inputs.d.ts +29 -0
  41. package/dist/components/release-inputs.d.ts.map +1 -0
  42. package/dist/components/release-inputs.js +57 -0
  43. package/dist/components/trace-facts.d.ts +16 -0
  44. package/dist/components/trace-facts.d.ts.map +1 -0
  45. package/dist/components/trace-facts.js +19 -0
  46. package/dist/compose/apply-events.d.ts +46 -0
  47. package/dist/compose/apply-events.d.ts.map +1 -0
  48. package/dist/compose/apply-events.js +77 -0
  49. package/dist/compose/estate.d.ts +194 -0
  50. package/dist/compose/estate.d.ts.map +1 -0
  51. package/dist/compose/estate.js +363 -0
  52. package/dist/compose/hcl.d.ts +99 -0
  53. package/dist/compose/hcl.d.ts.map +1 -0
  54. package/dist/compose/hcl.js +302 -0
  55. package/dist/compose/module-address.d.ts +24 -0
  56. package/dist/compose/module-address.d.ts.map +1 -0
  57. package/dist/compose/module-address.js +43 -0
  58. package/dist/compose/root.d.ts +127 -0
  59. package/dist/compose/root.d.ts.map +1 -0
  60. package/dist/compose/root.js +586 -0
  61. package/dist/compose/run.d.ts +183 -0
  62. package/dist/compose/run.d.ts.map +1 -0
  63. package/dist/compose/run.js +447 -0
  64. package/dist/compose/slice.d.ts +102 -0
  65. package/dist/compose/slice.d.ts.map +1 -0
  66. package/dist/compose/slice.js +249 -0
  67. package/dist/compose/state-address.d.ts +28 -0
  68. package/dist/compose/state-address.d.ts.map +1 -0
  69. package/dist/compose/state-address.js +154 -0
  70. package/dist/compose/state-merge.d.ts +52 -0
  71. package/dist/compose/state-merge.d.ts.map +1 -0
  72. package/dist/compose/state-merge.js +135 -0
  73. package/dist/compose.d.ts +179 -0
  74. package/dist/compose.d.ts.map +1 -0
  75. package/dist/compose.js +482 -0
  76. package/dist/composites/terraform-apply-op.d.ts.map +1 -1
  77. package/dist/composites/terraform-apply-op.js +7 -3
  78. package/dist/cone.d.ts +53 -0
  79. package/dist/cone.d.ts.map +1 -0
  80. package/dist/cone.js +119 -0
  81. package/dist/config.d.ts +59 -13
  82. package/dist/config.d.ts.map +1 -1
  83. package/dist/config.js +43 -9
  84. package/dist/cost-hold.d.ts +27 -0
  85. package/dist/cost-hold.d.ts.map +1 -0
  86. package/dist/cost-hold.js +21 -0
  87. package/dist/describe-resources.d.ts +74 -12
  88. package/dist/describe-resources.d.ts.map +1 -1
  89. package/dist/describe-resources.js +374 -66
  90. package/dist/drift-read.d.ts +33 -0
  91. package/dist/drift-read.d.ts.map +1 -0
  92. package/dist/drift-read.js +243 -0
  93. package/dist/drift-record.d.ts +147 -0
  94. package/dist/drift-record.d.ts.map +1 -0
  95. package/dist/drift-record.js +383 -0
  96. package/dist/drift-rows.d.ts +61 -0
  97. package/dist/drift-rows.d.ts.map +1 -0
  98. package/dist/drift-rows.js +108 -0
  99. package/dist/exit-codes.d.ts +55 -0
  100. package/dist/exit-codes.d.ts.map +1 -0
  101. package/dist/exit-codes.js +48 -0
  102. package/dist/hcl/edges.d.ts.map +1 -1
  103. package/dist/hcl/edges.js +24 -1
  104. package/dist/hcl/files.d.ts +61 -0
  105. package/dist/hcl/files.d.ts.map +1 -0
  106. package/dist/hcl/files.js +221 -0
  107. package/dist/hcl/instances.d.ts +82 -0
  108. package/dist/hcl/instances.d.ts.map +1 -0
  109. package/dist/hcl/instances.js +390 -0
  110. package/dist/hcl/parse.d.ts +81 -9
  111. package/dist/hcl/parse.d.ts.map +1 -1
  112. package/dist/hcl/parse.js +114 -16
  113. package/dist/hcl/roots.d.ts.map +1 -1
  114. package/dist/hcl/roots.js +5 -0
  115. package/dist/hcl/suppressions.d.ts.map +1 -1
  116. package/dist/hcl/suppressions.js +8 -2
  117. package/dist/index.d.ts +13 -2
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +24 -2
  120. package/dist/integrity.json +8 -5
  121. package/dist/lint/audit-catalog.d.ts.map +1 -1
  122. package/dist/lint/audit-catalog.js +27 -3
  123. package/dist/lint/audit-lineage.d.ts +14 -2
  124. package/dist/lint/audit-lineage.d.ts.map +1 -1
  125. package/dist/lint/post-synth/index.d.ts.map +1 -1
  126. package/dist/lint/post-synth/index.js +4 -0
  127. package/dist/lint/post-synth/record-store.d.ts +54 -0
  128. package/dist/lint/post-synth/record-store.d.ts.map +1 -0
  129. package/dist/lint/post-synth/record-store.js +104 -0
  130. package/dist/lint/post-synth/tf001.d.ts +2 -2
  131. package/dist/lint/post-synth/tf001.js +2 -2
  132. package/dist/lint/post-synth/tf024.d.ts +35 -11
  133. package/dist/lint/post-synth/tf024.d.ts.map +1 -1
  134. package/dist/lint/post-synth/tf024.js +92 -20
  135. package/dist/lint/post-synth/tf046.d.ts +64 -0
  136. package/dist/lint/post-synth/tf046.d.ts.map +1 -0
  137. package/dist/lint/post-synth/tf046.js +175 -0
  138. package/dist/lint/post-synth/tf047.d.ts +36 -0
  139. package/dist/lint/post-synth/tf047.d.ts.map +1 -0
  140. package/dist/lint/post-synth/tf047.js +94 -0
  141. package/dist/live-plan-reasons.d.ts +21 -0
  142. package/dist/live-plan-reasons.d.ts.map +1 -0
  143. package/dist/live-plan-reasons.js +47 -0
  144. package/dist/lock-rows.d.ts +36 -0
  145. package/dist/lock-rows.d.ts.map +1 -0
  146. package/dist/lock-rows.js +60 -0
  147. package/dist/lock-timeout.d.ts +22 -0
  148. package/dist/lock-timeout.d.ts.map +1 -0
  149. package/dist/lock-timeout.js +32 -0
  150. package/dist/lsp/option-keys.d.ts.map +1 -1
  151. package/dist/lsp/option-keys.js +2 -0
  152. package/dist/manifest.json +1 -1
  153. package/dist/module-catalog/index.d.ts +69 -0
  154. package/dist/module-catalog/index.d.ts.map +1 -0
  155. package/dist/module-catalog/index.js +110 -0
  156. package/dist/module-catalog/refresh-cli.d.ts +4 -0
  157. package/dist/module-catalog/refresh-cli.d.ts.map +1 -0
  158. package/dist/module-catalog/refresh-cli.js +64 -0
  159. package/dist/module-catalog/static-tier.d.ts +6 -0
  160. package/dist/module-catalog/static-tier.d.ts.map +1 -0
  161. package/dist/module-catalog/static-tier.js +1650 -0
  162. package/dist/module-catalog/types.d.ts +65 -0
  163. package/dist/module-catalog/types.d.ts.map +1 -0
  164. package/dist/module-catalog/types.js +33 -0
  165. package/dist/okf/index.md +3 -1
  166. package/dist/okf/rules/TF024.md +2 -2
  167. package/dist/okf/rules/TF046.md +11 -0
  168. package/dist/okf/rules/TF047.md +11 -0
  169. package/dist/op/activities/index.d.ts +6 -2
  170. package/dist/op/activities/index.d.ts.map +1 -1
  171. package/dist/op/activities/index.js +5 -1
  172. package/dist/op/activities/live-detect.d.ts +4 -3
  173. package/dist/op/activities/live-detect.d.ts.map +1 -1
  174. package/dist/op/activities/live-detect.js +57 -32
  175. package/dist/op/activities/pin-rollout.d.ts +2 -0
  176. package/dist/op/activities/pin-rollout.d.ts.map +1 -1
  177. package/dist/op/activities/pin-rollout.js +1 -0
  178. package/dist/op/activities/terraform.d.ts +182 -5
  179. package/dist/op/activities/terraform.d.ts.map +1 -1
  180. package/dist/op/activities/terraform.js +224 -24
  181. package/dist/op/activity-contracts.d.ts +27 -0
  182. package/dist/op/activity-contracts.d.ts.map +1 -1
  183. package/dist/op/activity-contracts.js +19 -1
  184. package/dist/op/builders.d.ts +7 -1
  185. package/dist/op/builders.d.ts.map +1 -1
  186. package/dist/op/builders.js +9 -0
  187. package/dist/pin/consumers.d.ts +35 -0
  188. package/dist/pin/consumers.d.ts.map +1 -0
  189. package/dist/pin/consumers.js +70 -0
  190. package/dist/pin/edit.d.ts.map +1 -1
  191. package/dist/pin/edit.js +35 -0
  192. package/dist/pin/rollout.d.ts +2 -0
  193. package/dist/pin/rollout.d.ts.map +1 -1
  194. package/dist/pin/rollout.js +14 -11
  195. package/dist/plan-shape.d.ts +30 -0
  196. package/dist/plan-shape.d.ts.map +1 -0
  197. package/dist/plan-shape.js +125 -0
  198. package/dist/plugin.d.ts.map +1 -1
  199. package/dist/plugin.js +37 -18
  200. package/dist/registry/address.d.ts +63 -0
  201. package/dist/registry/address.d.ts.map +1 -0
  202. package/dist/registry/address.js +65 -0
  203. package/dist/registry/catalog-read.d.ts +14 -0
  204. package/dist/registry/catalog-read.d.ts.map +1 -0
  205. package/dist/registry/catalog-read.js +58 -0
  206. package/dist/registry/deprecated.d.ts +37 -0
  207. package/dist/registry/deprecated.d.ts.map +1 -0
  208. package/dist/registry/deprecated.js +43 -0
  209. package/dist/registry/docs.d.ts +96 -0
  210. package/dist/registry/docs.d.ts.map +1 -0
  211. package/dist/registry/docs.js +210 -0
  212. package/dist/registry/edge/edge.d.ts +46 -0
  213. package/dist/registry/edge/edge.d.ts.map +1 -0
  214. package/dist/registry/edge/edge.js +194 -0
  215. package/dist/registry/edge/index.d.ts +11 -0
  216. package/dist/registry/edge/index.d.ts.map +1 -0
  217. package/dist/registry/edge/index.js +10 -0
  218. package/dist/registry/edge/lambda-edge.d.ts +76 -0
  219. package/dist/registry/edge/lambda-edge.d.ts.map +1 -0
  220. package/dist/registry/edge/lambda-edge.js +95 -0
  221. package/dist/registry/edge/sigv4-web.d.ts +33 -0
  222. package/dist/registry/edge/sigv4-web.d.ts.map +1 -0
  223. package/dist/registry/edge/sigv4-web.js +56 -0
  224. package/dist/registry/edge/token-source.d.ts +73 -0
  225. package/dist/registry/edge/token-source.d.ts.map +1 -0
  226. package/dist/registry/edge/token-source.js +115 -0
  227. package/dist/registry/edge/worker.d.ts +45 -0
  228. package/dist/registry/edge/worker.d.ts.map +1 -0
  229. package/dist/registry/edge/worker.js +26 -0
  230. package/dist/registry/handler.d.ts +25 -0
  231. package/dist/registry/handler.d.ts.map +1 -0
  232. package/dist/registry/handler.js +75 -0
  233. package/dist/registry/headers-file.d.ts +21 -0
  234. package/dist/registry/headers-file.d.ts.map +1 -0
  235. package/dist/registry/headers-file.js +57 -0
  236. package/dist/registry/index.d.ts +31 -0
  237. package/dist/registry/index.d.ts.map +1 -0
  238. package/dist/registry/index.js +30 -0
  239. package/dist/registry/mirror-paths.d.ts +9 -0
  240. package/dist/registry/mirror-paths.d.ts.map +1 -0
  241. package/dist/registry/mirror-paths.js +8 -0
  242. package/dist/registry/mirror.d.ts +130 -0
  243. package/dist/registry/mirror.d.ts.map +1 -0
  244. package/dist/registry/mirror.js +319 -0
  245. package/dist/registry/proxies.d.ts +73 -0
  246. package/dist/registry/proxies.d.ts.map +1 -0
  247. package/dist/registry/proxies.js +111 -0
  248. package/dist/registry/reader.d.ts +57 -0
  249. package/dist/registry/reader.d.ts.map +1 -0
  250. package/dist/registry/reader.js +198 -0
  251. package/dist/registry/semver.d.ts +16 -0
  252. package/dist/registry/semver.d.ts.map +1 -0
  253. package/dist/registry/semver.js +24 -0
  254. package/dist/registry/serve.d.ts +24 -0
  255. package/dist/registry/serve.d.ts.map +1 -0
  256. package/dist/registry/serve.js +64 -0
  257. package/dist/registry/source-forms.d.ts +79 -0
  258. package/dist/registry/source-forms.d.ts.map +1 -0
  259. package/dist/registry/source-forms.js +202 -0
  260. package/dist/registry/targets/artifactory.d.ts +28 -0
  261. package/dist/registry/targets/artifactory.d.ts.map +1 -0
  262. package/dist/registry/targets/artifactory.js +206 -0
  263. package/dist/registry/targets/fake-artifactory.d.ts +30 -0
  264. package/dist/registry/targets/fake-artifactory.d.ts.map +1 -0
  265. package/dist/registry/targets/fake-artifactory.js +142 -0
  266. package/dist/registry/targets/fake-gitlab.d.ts +39 -0
  267. package/dist/registry/targets/fake-gitlab.d.ts.map +1 -0
  268. package/dist/registry/targets/fake-gitlab.js +136 -0
  269. package/dist/registry/targets/fake-hcp.d.ts +50 -0
  270. package/dist/registry/targets/fake-hcp.d.ts.map +1 -0
  271. package/dist/registry/targets/fake-hcp.js +202 -0
  272. package/dist/registry/targets/fake-http.d.ts +31 -0
  273. package/dist/registry/targets/fake-http.d.ts.map +1 -0
  274. package/dist/registry/targets/fake-http.js +87 -0
  275. package/dist/registry/targets/fake-nexus.d.ts +27 -0
  276. package/dist/registry/targets/fake-nexus.d.ts.map +1 -0
  277. package/dist/registry/targets/fake-nexus.js +137 -0
  278. package/dist/registry/targets/gitlab.d.ts +53 -0
  279. package/dist/registry/targets/gitlab.d.ts.map +1 -0
  280. package/dist/registry/targets/gitlab.js +187 -0
  281. package/dist/registry/targets/hcp.d.ts +29 -0
  282. package/dist/registry/targets/hcp.d.ts.map +1 -0
  283. package/dist/registry/targets/hcp.js +310 -0
  284. package/dist/registry/targets/hosted.d.ts +62 -0
  285. package/dist/registry/targets/hosted.d.ts.map +1 -0
  286. package/dist/registry/targets/hosted.js +74 -0
  287. package/dist/registry/targets/index.d.ts +18 -0
  288. package/dist/registry/targets/index.d.ts.map +1 -0
  289. package/dist/registry/targets/index.js +17 -0
  290. package/dist/registry/targets/module-target.d.ts +68 -0
  291. package/dist/registry/targets/module-target.d.ts.map +1 -0
  292. package/dist/registry/targets/module-target.js +63 -0
  293. package/dist/registry/targets/nexus.d.ts +43 -0
  294. package/dist/registry/targets/nexus.d.ts.map +1 -0
  295. package/dist/registry/targets/nexus.js +250 -0
  296. package/dist/registry/targets/zip.d.ts +55 -0
  297. package/dist/registry/targets/zip.d.ts.map +1 -0
  298. package/dist/registry/targets/zip.js +278 -0
  299. package/dist/registry/writer.d.ts +101 -0
  300. package/dist/registry/writer.d.ts.map +1 -0
  301. package/dist/registry/writer.js +109 -0
  302. package/dist/report.d.ts +15 -6
  303. package/dist/report.d.ts.map +1 -1
  304. package/dist/report.js +28 -55
  305. package/dist/rules/record-store.ts +122 -0
  306. package/dist/rules/tf001.ts +2 -2
  307. package/dist/rules/tf024.ts +105 -22
  308. package/dist/rules/tf046.ts +204 -0
  309. package/dist/rules/tf047.ts +114 -0
  310. package/dist/skills/chant-terraform.md +1 -1
  311. package/dist/state/azure-blob.d.ts +9 -0
  312. package/dist/state/azure-blob.d.ts.map +1 -0
  313. package/dist/state/azure-blob.js +8 -0
  314. package/dist/state/backend.d.ts +158 -0
  315. package/dist/state/backend.d.ts.map +1 -0
  316. package/dist/state/backend.js +406 -0
  317. package/dist/state/exec.d.ts +39 -0
  318. package/dist/state/exec.d.ts.map +1 -0
  319. package/dist/state/exec.js +80 -0
  320. package/dist/state/gcs.d.ts +8 -0
  321. package/dist/state/gcs.d.ts.map +1 -0
  322. package/dist/state/gcs.js +7 -0
  323. package/dist/state/index.d.ts +15 -0
  324. package/dist/state/index.d.ts.map +1 -0
  325. package/dist/state/index.js +14 -0
  326. package/dist/state/locks.d.ts +105 -0
  327. package/dist/state/locks.d.ts.map +1 -0
  328. package/dist/state/locks.js +130 -0
  329. package/dist/state/object-store.d.ts +8 -0
  330. package/dist/state/object-store.d.ts.map +1 -0
  331. package/dist/state/object-store.js +7 -0
  332. package/dist/state/root-states.d.ts +131 -0
  333. package/dist/state/root-states.d.ts.map +1 -0
  334. package/dist/state/root-states.js +241 -0
  335. package/dist/state/s3.d.ts +21 -0
  336. package/dist/state/s3.d.ts.map +1 -0
  337. package/dist/state/s3.js +19 -0
  338. package/dist/state/store.d.ts +51 -0
  339. package/dist/state/store.d.ts.map +1 -0
  340. package/dist/state/store.js +185 -0
  341. package/dist/state-ops.d.ts +255 -0
  342. package/dist/state-ops.d.ts.map +1 -0
  343. package/dist/state-ops.js +305 -0
  344. package/dist/state-reads.d.ts +57 -0
  345. package/dist/state-reads.d.ts.map +1 -0
  346. package/dist/state-reads.js +104 -0
  347. package/dist/terragrunt/affected.d.ts.map +1 -1
  348. package/dist/terragrunt/affected.js +2 -1
  349. package/dist/used-sources.d.ts +54 -0
  350. package/dist/used-sources.d.ts.map +1 -0
  351. package/dist/used-sources.js +157 -0
  352. package/package.json +24 -4
  353. package/src/__fixtures__/ACCEPTANCE.md +69 -7
  354. package/src/__fixtures__/compose/apply-failed-in-app.jsonl +12 -0
  355. package/src/__fixtures__/compose/state-app.json +66 -0
  356. package/src/__fixtures__/compose/state-edge.json +40 -0
  357. package/src/__fixtures__/compose/state-net.json +58 -0
  358. package/src/__fixtures__/compose/three-app.plan.json +184 -0
  359. package/src/__fixtures__/compose/three-composed.plan.json +509 -0
  360. package/src/__fixtures__/compose/three-edge.plan.json +144 -0
  361. package/src/__fixtures__/compose/three-net.plan.json +174 -0
  362. package/src/__fixtures__/compose/unknown-composed.plan.json +228 -0
  363. package/src/__fixtures__/compose/working-after-apply.json +145 -0
  364. package/src/__fixtures__/config-blocks/app/main.tf +61 -0
  365. package/src/__fixtures__/config-blocks/app/modules/network/main.tf +4 -0
  366. package/src/__fixtures__/config-blocks/app-json/main.tf.json +39 -0
  367. package/src/__fixtures__/config-files/shadow/main.tf +3 -0
  368. package/src/__fixtures__/config-files/shadow/main.tofu +3 -0
  369. package/src/__fixtures__/config-files/shadow/other.tf +3 -0
  370. package/src/__fixtures__/config-files/tf/main.tf +11 -0
  371. package/src/__fixtures__/config-files/tf-json/main.tf.json +18 -0
  372. package/src/__fixtures__/config-files/tofu/main.tofu +11 -0
  373. package/src/__fixtures__/config-files/tofu-json/main.tofu.json +18 -0
  374. package/src/__fixtures__/config-files/tofu-only/main.tofu +3 -0
  375. package/src/__fixtures__/drift-record/README.md +16 -0
  376. package/src/__fixtures__/drift-record/live-plan-sections.json +27 -0
  377. package/src/__fixtures__/drift-rows/live-root-plan.json +70 -0
  378. package/src/__fixtures__/drift-rows/refresh-plan.json +61 -0
  379. package/src/__fixtures__/instance-forms/app/main.tf +110 -0
  380. package/src/__fixtures__/instance-forms/app/modules/svc/main.tf +3 -0
  381. package/src/__fixtures__/instance-vars/app/main.tf +52 -0
  382. package/src/__fixtures__/instance-vars/app/modules/app/main.tf +12 -0
  383. package/src/__fixtures__/instance-vars/app/modules/edge/main.tf +3 -0
  384. package/src/__fixtures__/instance-vars/app/terraform.tfvars +1 -0
  385. package/src/__fixtures__/live-module-keyed/live-graph.json +259 -0
  386. package/src/__fixtures__/live-module-keyed/live-plan.json +87 -0
  387. package/src/__fixtures__/live-module-keyed/root/estate.chdf.hcl +1 -0
  388. package/src/__fixtures__/live-module-keyed/root/main.tf +21 -0
  389. package/src/__fixtures__/live-module-keyed/root/modules/app/main.tf +17 -0
  390. package/src/__fixtures__/live-module-keyed/root/modules/edge/main.tf +7 -0
  391. package/src/__fixtures__/live-module-keyed/root/versions.tf +30 -0
  392. package/src/__fixtures__/live-module-keyed/show-state.json +146 -0
  393. package/src/__fixtures__/pr-loop/README.md +50 -0
  394. package/src/__fixtures__/pr-loop/chant.config.json +13 -0
  395. package/src/__fixtures__/pr-loop/estate.component.ts +10 -0
  396. package/src/__fixtures__/pr-loop/roots/a/main.tf +11 -0
  397. package/src/__fixtures__/pr-loop/roots/app/main.tf +19 -0
  398. package/src/__fixtures__/pr-loop/roots/b/main.tf +7 -0
  399. package/src/__fixtures__/pr-loop/roots/dns/main.tf +3 -0
  400. package/src/__fixtures__/pr-loop/roots/net/main.tf +7 -0
  401. package/src/__fixtures__/report/applied.show.json +51 -0
  402. package/src/__fixtures__/report/generate.ts +63 -0
  403. package/src/__fixtures__/report/plan.show.json +200 -0
  404. package/src/__fixtures__/report/tf-apply/change-set.json +170 -0
  405. package/src/__fixtures__/report/tf-apply/report.json +338 -0
  406. package/src/__fixtures__/report/tf-plan/change-set.json +170 -0
  407. package/src/__fixtures__/report/tf-plan/report.json +320 -0
  408. package/src/__fixtures__/three-cloud-azure.graph.json +290 -0
  409. package/src/__fixtures__/used-sources/root/extra.tofu +1 -0
  410. package/src/__fixtures__/used-sources/root/main.tf +31 -0
  411. package/src/__fixtures__/used-sources/root/modules/net/main.tf +14 -0
  412. package/src/__fixtures__/used-sources/root/modules/net/versions.tf.json +7 -0
  413. package/src/__fixtures__/used-sources/unit/terragrunt.hcl +3 -0
  414. package/src/applied-state.ts +52 -0
  415. package/src/backend-config.test.ts +105 -0
  416. package/src/backend-config.ts +133 -0
  417. package/src/behaviour/kinds.ts +4 -0
  418. package/src/behaviour/predict.ts +5 -2
  419. package/src/behaviour/reference-catalog.plugin.test.ts +65 -0
  420. package/src/behaviour/reference-catalog.ts +16 -5
  421. package/src/behaviour/request.ts +3 -2
  422. package/src/change-set-instances.test.ts +98 -0
  423. package/src/changed-roots.ts +14 -16
  424. package/src/ci-setup.ts +42 -0
  425. package/src/commands.ts +4 -3
  426. package/src/components/capability-plugin.test.ts +198 -19
  427. package/src/components/capability-plugin.ts +383 -35
  428. package/src/components/change-set-graph.e2e.test.ts +11 -5
  429. package/src/components/compose-group.test.ts +486 -0
  430. package/src/components/compose-group.ts +489 -0
  431. package/src/components/demo-composed-roots.e2e.test.ts +440 -0
  432. package/src/components/member-outputs.test.ts +76 -0
  433. package/src/components/placeholder-preview.test.ts +147 -0
  434. package/src/components/placeholder-preview.ts +257 -0
  435. package/src/components/pr-loop-compose.tofu.e2e.test.ts +363 -0
  436. package/src/components/pr-loop.tofu.test.ts +113 -57
  437. package/src/components/release-inputs.ts +69 -0
  438. package/src/components/trace-facts.test.ts +21 -0
  439. package/src/components/trace-facts.ts +27 -0
  440. package/src/compose/apply-events.test.ts +62 -0
  441. package/src/compose/apply-events.ts +100 -0
  442. package/src/compose/estate.choudoufu.e2e.test.ts +112 -0
  443. package/src/compose/estate.test.ts +421 -0
  444. package/src/compose/estate.ts +443 -0
  445. package/src/compose/hcl.ts +311 -0
  446. package/src/compose/module-address.ts +49 -0
  447. package/src/compose/root.test.ts +416 -0
  448. package/src/compose/root.ts +592 -0
  449. package/src/compose/run.test.ts +440 -0
  450. package/src/compose/run.tofu.test.ts +176 -0
  451. package/src/compose/run.ts +527 -0
  452. package/src/compose/slice.test.ts +184 -0
  453. package/src/compose/slice.ts +290 -0
  454. package/src/compose/state-address.ts +157 -0
  455. package/src/compose/state-merge.test.ts +131 -0
  456. package/src/compose/state-merge.ts +148 -0
  457. package/src/compose.test.ts +248 -0
  458. package/src/compose.ts +627 -0
  459. package/src/composites/terraform-apply-op.test.ts +9 -0
  460. package/src/composites/terraform-apply-op.ts +7 -3
  461. package/src/cone.ts +138 -0
  462. package/src/config-file-listers.test.ts +265 -0
  463. package/src/config.ts +44 -9
  464. package/src/cost-hold.ts +29 -0
  465. package/src/describe-resources.engine-facts.test.ts +411 -0
  466. package/src/describe-resources.live-module-keyed.test.ts +290 -0
  467. package/src/describe-resources.ts +416 -70
  468. package/src/drift-read.ts +284 -0
  469. package/src/drift-record.test.ts +223 -0
  470. package/src/drift-record.ts +455 -0
  471. package/src/drift-rows.test.ts +135 -0
  472. package/src/drift-rows.ts +137 -0
  473. package/src/exit-codes.test.ts +23 -0
  474. package/src/exit-codes.ts +59 -0
  475. package/src/hcl/config-blocks.test.ts +174 -0
  476. package/src/hcl/edges.ts +21 -1
  477. package/src/hcl/files.ts +234 -0
  478. package/src/hcl/instance-forms.test.ts +94 -0
  479. package/src/hcl/instances.test.ts +137 -0
  480. package/src/hcl/instances.ts +422 -0
  481. package/src/hcl/parse.test.ts +139 -1
  482. package/src/hcl/parse.ts +149 -16
  483. package/src/hcl/roots.ts +6 -0
  484. package/src/hcl/suppressions.ts +8 -2
  485. package/src/index.ts +79 -0
  486. package/src/lint/audit-catalog.ts +29 -3
  487. package/src/lint/audit-lineage.ts +14 -2
  488. package/src/lint/post-synth/fixtures/TF024/live-with-record-store/main.tf +18 -0
  489. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/estate.chdf.hcl +1 -0
  490. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/main.tf +10 -0
  491. package/src/lint/post-synth/fixtures/TF046/azurerm-no-resource-group/main.tf +15 -0
  492. package/src/lint/post-synth/fixtures/TF046/backend-config-only/main.tf +14 -0
  493. package/src/lint/post-synth/fixtures/TF046/derived-s3/backend.tf +7 -0
  494. package/src/lint/post-synth/fixtures/TF046/derived-s3/main.tf +9 -0
  495. package/src/lint/post-synth/fixtures/TF046/explicit-local/main.tf +16 -0
  496. package/src/lint/post-synth/fixtures/TF046/explicit-s3-beside-local-backend/main.tf +15 -0
  497. package/src/lint/post-synth/fixtures/TF046/implied-local/main.tf +9 -0
  498. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/estate.chdf.hcl +1 -0
  499. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/main.tf +5 -0
  500. package/src/lint/post-synth/fixtures/TF047/clear/main.tf +12 -0
  501. package/src/lint/post-synth/fixtures/TF047/refused/main.tf +12 -0
  502. package/src/lint/post-synth/fixtures/TF047/unknown-module/main.tf +12 -0
  503. package/src/lint/post-synth/fixtures/TF047/unknown-version/main.tf +12 -0
  504. package/src/lint/post-synth/index.ts +4 -0
  505. package/src/lint/post-synth/record-store.ts +122 -0
  506. package/src/lint/post-synth/tf001.ts +2 -2
  507. package/src/lint/post-synth/tf024.test.ts +26 -5
  508. package/src/lint/post-synth/tf024.ts +105 -22
  509. package/src/lint/post-synth/tf046.test.ts +137 -0
  510. package/src/lint/post-synth/tf046.ts +204 -0
  511. package/src/lint/post-synth/tf047.test.ts +56 -0
  512. package/src/lint/post-synth/tf047.ts +114 -0
  513. package/src/live-plan-reasons.ts +54 -0
  514. package/src/lock-rows.test.ts +70 -0
  515. package/src/lock-rows.ts +82 -0
  516. package/src/lock-timeout.ts +34 -0
  517. package/src/lsp/completions.test.ts +1 -1
  518. package/src/lsp/option-keys.ts +2 -0
  519. package/src/module-catalog/index.test.ts +93 -0
  520. package/src/module-catalog/index.ts +159 -0
  521. package/src/module-catalog/refresh-cli.ts +68 -0
  522. package/src/module-catalog/static-tier.ts +1659 -0
  523. package/src/module-catalog/types.ts +88 -0
  524. package/src/op/activities/choudoufu-plan-set-op.test.ts +111 -0
  525. package/src/op/activities/index.ts +9 -0
  526. package/src/op/activities/live-detect.ts +55 -26
  527. package/src/op/activities/pin-rollout.ts +3 -0
  528. package/src/op/activities/registry.test.ts +2 -1
  529. package/src/op/activities/terraform.test.ts +55 -0
  530. package/src/op/activities/terraform.ts +312 -27
  531. package/src/op/activity-contracts.test.ts +1 -0
  532. package/src/op/activity-contracts.ts +24 -1
  533. package/src/op/builders.ts +14 -0
  534. package/src/op-wave-step.test.ts +109 -0
  535. package/src/pin/__fixtures__/consumers/live/dev/main.tf +4 -0
  536. package/src/pin/__fixtures__/consumers/live/prod/main.tf +21 -0
  537. package/src/pin/__fixtures__/consumers/units/vpc/terragrunt.hcl +7 -0
  538. package/src/pin/bundle.test.ts +2 -0
  539. package/src/pin/consumers.test.ts +57 -0
  540. package/src/pin/consumers.ts +95 -0
  541. package/src/pin/edit.ts +30 -0
  542. package/src/pin/rollout.ts +16 -11
  543. package/src/plan-shape.test.ts +148 -0
  544. package/src/plan-shape.ts +128 -0
  545. package/src/plugin.ts +39 -19
  546. package/src/registry/__fixtures__/docs/documented/.terraform-docs.yml +3 -0
  547. package/src/registry/__fixtures__/docs/documented/README.md +1 -0
  548. package/src/registry/__fixtures__/docs/documented/main.tf +8 -0
  549. package/src/registry/__fixtures__/docs/json/main.tf.json +14 -0
  550. package/src/registry/__fixtures__/docs/vpc/README.md +3 -0
  551. package/src/registry/__fixtures__/docs/vpc/examples/complete/main.tf +5 -0
  552. package/src/registry/__fixtures__/docs/vpc/examples/simple/README.md +1 -0
  553. package/src/registry/__fixtures__/docs/vpc/examples/simple/main.tf +4 -0
  554. package/src/registry/__fixtures__/docs/vpc/main.tf +14 -0
  555. package/src/registry/__fixtures__/docs/vpc/outputs.tf +9 -0
  556. package/src/registry/__fixtures__/docs/vpc/variables.tf +16 -0
  557. package/src/registry/__fixtures__/proxied-root/main.tf +12 -0
  558. package/src/registry/address.ts +100 -0
  559. package/src/registry/catalog-read.ts +56 -0
  560. package/src/registry/deprecated.test.ts +139 -0
  561. package/src/registry/deprecated.ts +76 -0
  562. package/src/registry/docs.test.ts +140 -0
  563. package/src/registry/docs.ts +299 -0
  564. package/src/registry/edge/bundle.test.ts +50 -0
  565. package/src/registry/edge/edge.test.ts +176 -0
  566. package/src/registry/edge/edge.ts +211 -0
  567. package/src/registry/edge/index.ts +10 -0
  568. package/src/registry/edge/lambda-edge.ts +127 -0
  569. package/src/registry/edge/sigv4-web.ts +79 -0
  570. package/src/registry/edge/token-source.test.ts +258 -0
  571. package/src/registry/edge/token-source.ts +169 -0
  572. package/src/registry/edge/worker.ts +61 -0
  573. package/src/registry/handler.ts +89 -0
  574. package/src/registry/headers-file.ts +61 -0
  575. package/src/registry/index.ts +31 -0
  576. package/src/registry/mirror-paths.ts +10 -0
  577. package/src/registry/mirror.test.ts +198 -0
  578. package/src/registry/mirror.ts +395 -0
  579. package/src/registry/proxies.test.ts +153 -0
  580. package/src/registry/proxies.ts +132 -0
  581. package/src/registry/reader.ts +225 -0
  582. package/src/registry/registry.test.ts +262 -0
  583. package/src/registry/semver.ts +34 -0
  584. package/src/registry/serve.ts +82 -0
  585. package/src/registry/source-forms.test.ts +87 -0
  586. package/src/registry/source-forms.ts +216 -0
  587. package/src/registry/targets/artifactory.test.ts +248 -0
  588. package/src/registry/targets/artifactory.ts +257 -0
  589. package/src/registry/targets/fake-artifactory.ts +158 -0
  590. package/src/registry/targets/fake-gitlab.ts +161 -0
  591. package/src/registry/targets/fake-hcp.ts +233 -0
  592. package/src/registry/targets/fake-http.ts +97 -0
  593. package/src/registry/targets/fake-nexus.ts +152 -0
  594. package/src/registry/targets/gitlab.test.ts +208 -0
  595. package/src/registry/targets/gitlab.ts +223 -0
  596. package/src/registry/targets/hcp.test.ts +230 -0
  597. package/src/registry/targets/hcp.ts +360 -0
  598. package/src/registry/targets/hosted.ts +117 -0
  599. package/src/registry/targets/index.ts +17 -0
  600. package/src/registry/targets/module-target.ts +131 -0
  601. package/src/registry/targets/nexus.test.ts +220 -0
  602. package/src/registry/targets/nexus.ts +314 -0
  603. package/src/registry/targets/zip.test.ts +65 -0
  604. package/src/registry/targets/zip.ts +287 -0
  605. package/src/registry/writer.ts +155 -0
  606. package/src/report.test.ts +82 -1
  607. package/src/report.ts +31 -54
  608. package/src/signal-only-root.test.ts +72 -0
  609. package/src/skills/chant-terraform.md +1 -1
  610. package/src/state/azure-blob.ts +8 -0
  611. package/src/state/backend-verdict.test.ts +187 -0
  612. package/src/state/backend.test.ts +127 -0
  613. package/src/state/backend.ts +488 -0
  614. package/src/state/exec.ts +111 -0
  615. package/src/state/gcs.ts +7 -0
  616. package/src/state/index.ts +15 -0
  617. package/src/state/locks.test.ts +84 -0
  618. package/src/state/locks.ts +201 -0
  619. package/src/state/object-store.ts +7 -0
  620. package/src/state/root-states-floci.e2e.test.ts +66 -0
  621. package/src/state/root-states.test.ts +462 -0
  622. package/src/state/root-states.ts +309 -0
  623. package/src/state/s3.ts +21 -0
  624. package/src/state/store.ts +225 -0
  625. package/src/state-ops.test.ts +182 -0
  626. package/src/state-ops.ts +462 -0
  627. package/src/state-reads.ts +116 -0
  628. package/src/terragrunt/affected.ts +2 -1
  629. package/src/used-sources.test.ts +75 -0
  630. package/src/used-sources.ts +204 -0
  631. package/src/workspace-kinds.test.ts +4 -17
  632. package/workspace-kinds.json +1 -24
  633. package/dist/workspace-member.d.ts +0 -30
  634. package/dist/workspace-member.d.ts.map +0 -1
  635. package/dist/workspace-member.js +0 -91
  636. package/schemas/pulumi.schema.json +0 -34
  637. package/src/testdata/pulumi-member/Pulumi.yaml +0 -2
  638. package/src/testdata/pulumi-member/stack-export.json +0 -53
  639. package/src/testdata/pulumi-unexported/Pulumi.yaml +0 -2
  640. package/src/workspace-member.test.ts +0 -89
  641. package/src/workspace-member.ts +0 -126
@@ -0,0 +1,305 @@
1
+ /**
2
+ * The binary runs outside op waves (#4618): the state-lock release, a state
3
+ * migration's writes and an ephemeral copy's plan and apply, as fixed
4
+ * operations of the terraform lexicon, with the gate and the records of
5
+ * #4551 around the ones that change state on their own.
6
+ *
7
+ * Each operation runs a fixed argument list. A caller names the root, the
8
+ * binary and what the operation acts on (a lock ID, a state file, a key
9
+ * suffix's backend settings), never extra arguments, so a product cannot
10
+ * turn an unlock into some other command.
11
+ *
12
+ * - `forceUnlockState` releases one lock by its ID with `force-unlock
13
+ * -force`. It changes state on its own, so it runs under a gated request:
14
+ * `gatedStateOp` asks for the request (`requestGate`), spends the approval
15
+ * (`spendGatedRequest`, pushed before anything runs) and records how it
16
+ * ended (`finishGatedRequest`, with the product's flat facts in `detail`).
17
+ * - `pushStateFile` writes one state file with `state push`, and
18
+ * `planStateCheck` plans a root against its state (`-lock=false` while the
19
+ * caller holds the lock itself) and reads the plan's JSON. A standalone
20
+ * migration's writes run under one gated request whose attachment is the
21
+ * proof, so the digest binds it. A migration inside a wave keeps the
22
+ * wave's hold hook, which chant decides already.
23
+ * - `planCopy` initialises a root under the backend settings of its copy
24
+ * (`init -reconfigure -backend-config=<k>=<v>`), plans it, a destroy too,
25
+ * and reads the plan as a change-set part; `applyPlanFile` applies a saved
26
+ * plan. A copy waits at chant's `pr-env` gate, which
27
+ * `components/pr-env-run` decides and records (#4551 gap 4), so it takes
28
+ * no request of its own.
29
+ *
30
+ * The capabilities at the end (`terraform-state-unlock`,
31
+ * `terraform-state-push`, `terraform-copy`) put the same operations in the
32
+ * plugin's registry, so a step names them by kind.
33
+ *
34
+ * The exec is injectable (`./state/exec.ts`), and so is the gated-request
35
+ * ledger, so a test runs no binary and writes no ledger.
36
+ */
37
+ import { createHash } from "node:crypto";
38
+ import { join } from "node:path";
39
+ import { CHANT_EXIT } from "@intentius/chant/exit-codes";
40
+ import { finishGatedRequest, gatedRequestDigest, readGatedRequests, requestGate, spendGatedRequest, } from "@intentius/chant/lifecycle/gated-request";
41
+ import { plannerForBinary, terraformChangeSetPart } from "./change-set.js";
42
+ import { DEFAULT_LOCK_TIMEOUT, lockTimeoutArgs } from "./lock-timeout.js";
43
+ import { lastLines, runBinary } from "./state/exec.js";
44
+ /** The ops the gated requests of this module wait at, one per kind, as terragucci named them. */
45
+ export const STATE_OPS = {
46
+ unlock: "tf-unlock",
47
+ migrate: "tf-migrate",
48
+ export: "tf-state-export",
49
+ };
50
+ /** The request kinds of #4551's design. */
51
+ export const STATE_OP_KINDS = {
52
+ unlock: "unlock",
53
+ migrate: "migrate",
54
+ export: "state-export",
55
+ };
56
+ /** A binary run that exited non-zero, with the tail of its output. */
57
+ export class StateOpError extends Error {
58
+ constructor(root, command, code, tail) {
59
+ super(`${root}: ${command} failed (exit ${code})${tail ? `:\n${tail}` : ""}`);
60
+ this.root = root;
61
+ this.command = command;
62
+ this.code = code;
63
+ this.tail = tail;
64
+ this.name = "StateOpError";
65
+ }
66
+ }
67
+ /** A gated operation stopped for a person: its request waits for an approval. The command that ran it exits 3. */
68
+ export class StateOpWaitingError extends Error {
69
+ constructor(op, subject, digest, command) {
70
+ super(`${op} ${subject} waits for an approval of ${digest}: ${command}`);
71
+ this.op = op;
72
+ this.subject = subject;
73
+ this.digest = digest;
74
+ this.command = command;
75
+ this.exitCode = CHANT_EXIT.waiting;
76
+ this.name = "StateOpWaitingError";
77
+ }
78
+ }
79
+ const ran = async (r, args, label) => {
80
+ const exec = r.exec ?? runBinary;
81
+ const done = await exec(r.binary, args, r.dir, r.env ?? process.env);
82
+ if (done.code !== 0)
83
+ throw new StateOpError(r.root, `${r.binary} ${label}`, done.code, lastLines(done.out, 10));
84
+ return done;
85
+ };
86
+ // ── the binary runs ─────────────────────────────────────────────────────────
87
+ /** `init -input=false -no-color`, with `-reconfigure` and `-backend-config` pairs when given. */
88
+ export async function initRoot(r) {
89
+ const configs = Object.entries(r.backendConfig ?? {}).map(([k, v]) => `-backend-config=${k}=${v}`);
90
+ await ran(r, ["init", "-input=false", "-no-color", ...(r.reconfigure || configs.length > 0 ? ["-reconfigure"] : []), ...configs], "init");
91
+ }
92
+ /**
93
+ * Release the state lock with this ID: `force-unlock -force -no-color <id>`.
94
+ * Run it under {@link gatedStateOp}; the binary releases whichever lock has
95
+ * the ID, so the approval binds the ID and the lock's location.
96
+ */
97
+ export async function forceUnlockState(r) {
98
+ if (!r.id || r.id.startsWith("-"))
99
+ throw new Error(`${r.root}: "${r.id}" is not a lock ID`);
100
+ await ran(r, ["force-unlock", "-force", "-no-color", r.id], `force-unlock ${r.id}`);
101
+ }
102
+ /**
103
+ * Write a state file with `state push`. `lock: false` passes `-lock=false`,
104
+ * for a caller that holds the state's lock itself; `force` passes `-force`,
105
+ * for a push over an empty state of another lineage the caller checked.
106
+ */
107
+ export async function pushStateFile(r) {
108
+ if (r.file.startsWith("-"))
109
+ throw new Error(`${r.root}: "${r.file}" is not a state file`);
110
+ await ran(r, ["state", "push", ...(r.lock === false ? ["-lock=false"] : []), ...(r.force ? ["-force"] : []), r.file], "state push");
111
+ }
112
+ async function planAndShow(r, planArgs, planFile) {
113
+ const plan = await ran(r, ["plan", "-input=false", "-no-color", ...planArgs, `-out=${planFile}`], "plan");
114
+ const show = await ran(r, ["show", "-json", planFile], "show -json");
115
+ let json;
116
+ try {
117
+ json = JSON.parse(show.stdout);
118
+ }
119
+ catch {
120
+ throw new StateOpError(r.root, `${r.binary} show -json`, 0, `printed no plan: ${lastLines(show.out, 10)}`);
121
+ }
122
+ return { planFile, json, summary: plan.out.match(/Plan: .*|No changes\..*/)?.[0] ?? "planned" };
123
+ }
124
+ /**
125
+ * Plan a root against its state and read the plan: the check a migration
126
+ * makes before and after it writes. `lock: false` passes `-lock=false`, for a
127
+ * caller that holds the lock itself.
128
+ */
129
+ export function planStateCheck(r) {
130
+ return planAndShow(r, r.lock === false ? ["-lock=false"] : [], r.planFile);
131
+ }
132
+ /**
133
+ * Initialise a root under its copy's backend settings and plan it, a destroy
134
+ * with `destroy`. `backendConfig` is what makes it the copy (a state key with
135
+ * the copy's suffix), so it is required and never empty: without it the plan
136
+ * would be of the root's own state. Pass `init: false` for a root another
137
+ * tool initialised (a Terragrunt unit prepared with the suffix set).
138
+ */
139
+ export async function planCopy(r) {
140
+ if (r.init !== false) {
141
+ if (Object.keys(r.backendConfig).length === 0)
142
+ throw new Error(`${r.root}: a copy needs the backend settings of its own state`);
143
+ await initRoot({ ...r, reconfigure: true });
144
+ }
145
+ const read = await planAndShow(r, [...lockTimeoutArgs("plan", r.lockTimeout ?? DEFAULT_LOCK_TIMEOUT, r.env ?? process.env), ...(r.destroy ? ["-destroy"] : [])], r.planFile);
146
+ const part = terraformChangeSetPart({ member: r.root, plan: read.json, planner: plannerForBinary(r.binary) });
147
+ return { ...read, part, planDigest: part.member.planDigest ?? "" };
148
+ }
149
+ /** Apply a saved plan, and nothing else: `apply -input=false -no-color <plan>`. */
150
+ export async function applyPlanFile(r) {
151
+ await ran(r, ["apply", "-input=false", "-no-color", ...lockTimeoutArgs("apply", r.lockTimeout ?? DEFAULT_LOCK_TIMEOUT, r.env ?? process.env), r.planFile], "apply");
152
+ }
153
+ const chantLedger = { requestGate, spendGatedRequest, finishGatedRequest, readGatedRequests };
154
+ /**
155
+ * The time a request was first asked, so asking again binds the same
156
+ * digest: chant's digest covers `at`, and a run that asked anew each time
157
+ * would never meet the approval of the last one. The newest standing,
158
+ * unspent request with the same kind, subject, requester and fields gives
159
+ * its `at`; with none, `now`.
160
+ */
161
+ export async function requestedAt(op, request, options = {}) {
162
+ const now = options.now ?? new Date().toISOString();
163
+ const read = await (options.ledger ?? chantLedger).readGatedRequests(op, options.cwd ? { cwd: options.cwd } : undefined).catch(() => []);
164
+ const same = JSON.stringify(Object.entries(request.fields).sort());
165
+ const standing = read
166
+ .filter((g) => !g.applied && g.request.kind === request.kind && g.request.subject === request.subject && g.request.by === request.by)
167
+ .filter((g) => JSON.stringify(Object.entries(g.request.fields).sort()) === same)
168
+ .filter((g) => !g.pending.expiresAt || g.pending.expiresAt > now)
169
+ .at(-1);
170
+ return standing?.request.at ?? now;
171
+ }
172
+ /** The digest `requestGate` puts in `fields.proof` for an attachment. */
173
+ export const attachmentDigest = (attachment) => `sha256:${createHash("sha256").update(attachment).digest("hex")}`;
174
+ /**
175
+ * Run `act` once its request is approved: ask (or read) the request, spend
176
+ * the approval, act, and record how it ended. `act` returns its output and
177
+ * the flat facts that go on the finished line. A spend that cannot be pushed
178
+ * throws before `act` runs, so no approval acts twice. A finished line that
179
+ * cannot be written is reported as `recorded: false`; the act already ran.
180
+ */
181
+ export async function gatedStateOp(input, act) {
182
+ const ledger = input.ledger ?? chantLedger;
183
+ // The proof's digest is a field of the stored request, so the standing request is matched with it.
184
+ const fields = input.attachment !== undefined ? { ...input.request.fields, proof: attachmentDigest(input.attachment) } : input.request.fields;
185
+ const at = input.request.at ?? (await requestedAt(input.op, { ...input.request, fields }, { ...(input.now ? { now: input.now } : {}), ...(input.cwd ? { cwd: input.cwd } : {}), ledger }));
186
+ const request = { kind: input.request.kind, subject: input.request.subject, by: input.request.by, at, fields };
187
+ const asked = await ledger.requestGate({
188
+ op: input.op,
189
+ request,
190
+ rules: input.rules,
191
+ ...(input.description ? { description: input.description } : {}),
192
+ ...(input.expiry ? { expiry: input.expiry } : {}),
193
+ ...(input.base ? { base: input.base } : {}),
194
+ ...(input.attachment !== undefined ? { attachment: input.attachment } : {}),
195
+ ...(input.cwd ? { cwd: input.cwd } : {}),
196
+ ...(input.now ? { now: input.now } : {}),
197
+ ...(input.gates ? { gates: input.gates } : {}),
198
+ });
199
+ if (asked.status !== "approved")
200
+ return asked;
201
+ const { digest } = asked;
202
+ const approvedBy = asked.approval.resolvedBy;
203
+ const held = await input.beforeSpend?.();
204
+ if (held)
205
+ return { status: "held", digest, request: asked.request, reason: held };
206
+ const spent = await ledger.spendGatedRequest({
207
+ op: input.op,
208
+ gate: request.subject,
209
+ digest,
210
+ approval: asked.approval,
211
+ ...(input.runId ? { runId: input.runId } : {}),
212
+ ...(input.commit ? { commit: input.commit } : {}),
213
+ ...(input.cwd ? { cwd: input.cwd } : {}),
214
+ ...(input.now ? { now: input.now } : {}),
215
+ });
216
+ const finish = async (result, detail) => {
217
+ try {
218
+ const f = await ledger.finishGatedRequest({ op: input.op, gate: request.subject, digest, applied: spent.timestamp, result, ...(detail ? { detail } : {}), ...(input.cwd ? { cwd: input.cwd } : {}) });
219
+ return f.pushed;
220
+ }
221
+ catch {
222
+ return false;
223
+ }
224
+ };
225
+ try {
226
+ const { output, detail } = await act({ digest, request: asked.request, approvedBy });
227
+ return { status: "done", digest, request: asked.request, approvedBy, output, recorded: await finish("applied", detail) };
228
+ }
229
+ catch (e) {
230
+ const error = e instanceof Error ? e : new Error(String(e));
231
+ return { status: "failed", digest, request: asked.request, approvedBy, error, recorded: await finish("failed", { error: error.message.slice(0, 400) }) };
232
+ }
233
+ }
234
+ /** The digest a request binds, for a caller that prints it before it asks. */
235
+ export const stateOpDigest = (op, request) => gatedRequestDigest(op, request);
236
+ const actorOf = (env) => env.GITHUB_ACTOR || env.GITLAB_USER_LOGIN || env.USER || env.USERNAME || "unknown";
237
+ const dirOf = (cwd, input) => input.dir ?? join(cwd ?? process.cwd(), input.root);
238
+ async function gatedRun(op, input, kind, fields, act, attachment) {
239
+ const cwd = input.cwd ?? process.cwd();
240
+ const result = await gatedStateOp({ op, request: { kind, subject: input.root, by: input.by ?? actorOf(process.env), fields }, rules: { mode: input.approval ?? "ledger" }, cwd, ...(attachment !== undefined ? { attachment } : {}) }, act);
241
+ if (result.status === "done")
242
+ return result.output;
243
+ if (result.status === "failed")
244
+ throw result.error;
245
+ if (result.status === "spent")
246
+ throw new Error(`${op} ${input.root}: the request ${result.digest} applied already, and a request applies once`);
247
+ if (result.status === "held")
248
+ throw new Error(`${op} ${input.root}: ${result.reason}`);
249
+ throw new StateOpWaitingError(op, input.root, result.digest, result.command);
250
+ }
251
+ /** The plan a gated capability answers: the request's digest is computed when it is asked, so the plan binds the step's facts alone. */
252
+ const factsPlan = (member, facts) => ({ member, planDigest: stateOpDigest("plan", { kind: "facts", subject: member, by: "", at: "", fields: facts }) });
253
+ export const terraformStateUnlockCapability = {
254
+ kind: "terraform-state-unlock",
255
+ rollbackPolicy: "none-by-design",
256
+ targets: { refuse: "a lock release acts on one lock by its ID" },
257
+ async plan(_ctx, input) {
258
+ return factsPlan(input.root, { id: input.id, location: input.location });
259
+ },
260
+ async run(_ctx, input) {
261
+ const dir = dirOf(input.cwd, input);
262
+ const binary = input.binary ?? "terraform";
263
+ return gatedRun(STATE_OPS.unlock, input, STATE_OP_KINDS.unlock, { location: input.location, id: input.id }, async () => {
264
+ await initRoot({ root: input.root, binary, dir });
265
+ await forceUnlockState({ root: input.root, binary, dir, id: input.id });
266
+ return { output: { root: input.root, id: input.id }, detail: { lock: input.id, location: input.location } };
267
+ });
268
+ },
269
+ };
270
+ export const terraformStatePushCapability = {
271
+ kind: "terraform-state-push",
272
+ rollbackPolicy: "needs-opt-out",
273
+ targets: { refuse: "a state push writes whole states" },
274
+ async plan(_ctx, input) {
275
+ return factsPlan(input.root, { roots: input.files.map((f) => f.root).join(",") });
276
+ },
277
+ async run(_ctx, input) {
278
+ const binary = input.binary ?? "terraform";
279
+ return gatedRun(STATE_OPS.migrate, input, STATE_OP_KINDS.migrate, { roots: input.files.map((f) => f.root).join(",") }, async () => {
280
+ for (const f of input.files)
281
+ await pushStateFile({ root: f.root, binary, dir: dirOf(input.cwd, f), file: f.file, ...(f.lock !== undefined ? { lock: f.lock } : {}), ...(f.force ? { force: true } : {}) });
282
+ return { output: { roots: input.files.map((f) => f.root) }, detail: { roots: input.files.length } };
283
+ }, input.proof);
284
+ },
285
+ };
286
+ export const terraformCopyCapability = {
287
+ kind: "terraform-copy",
288
+ rollbackPolicy: "needs-opt-out",
289
+ targets: { refuse: "a copy plans the whole root" },
290
+ async plan(_ctx, input) {
291
+ const dir = dirOf(input.cwd, input);
292
+ const planFile = join(dir, input.destroy ? ".chant-copy-destroy.tfplan" : ".chant-copy.tfplan");
293
+ const read = await planCopy({ root: input.root, binary: input.binary ?? "terraform", dir, backendConfig: input.backendConfig, planFile, ...(input.destroy ? { destroy: true } : {}), ...(input.lockTimeout !== undefined ? { lockTimeout: input.lockTimeout } : {}) });
294
+ const artifact = { planFile, planDigest: read.planDigest };
295
+ return { member: input.root, planDigest: read.planDigest, artifact, changeSet: read.part };
296
+ },
297
+ async run(ctx, input) {
298
+ const kept = ctx.plans?.[input.root];
299
+ const planned = kept && typeof kept.planFile === "string" ? kept : await terraformCopyCapability.plan(ctx, input).then((p) => p.artifact);
300
+ await applyPlanFile({ root: input.root, binary: input.binary ?? "terraform", dir: dirOf(input.cwd, input), planFile: planned.planFile, ...(input.lockTimeout !== undefined ? { lockTimeout: input.lockTimeout } : {}) });
301
+ return { root: input.root, planDigest: planned.planDigest };
302
+ },
303
+ };
304
+ /** The state operations' capabilities, for the plugin's registry. */
305
+ export const terraformStateOpCapabilities = [terraformStateUnlockCapability, terraformStatePushCapability, terraformCopyCapability];
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Variables read from another root's state (#4545, Atmos reads moved from
3
+ * terragucci's `atmos.ts`): an Atmos stack that sets a var with
4
+ * `!terraform.state <component> [<stack>] <output>` plans on the upstream
5
+ * instance's output, which only the job that holds a credential can read.
6
+ *
7
+ * In the `terraform-apply` step a read is `{ var, root, output }`: the var it
8
+ * sets, the `terraform.roots` entry whose state holds the value (its
9
+ * directory and workspace come from that entry), and the output followed by
10
+ * the keys into its value (`.subnets.private` is `["subnets", "private"]`).
11
+ * The step reads each upstream's `output -json` once and passes the values
12
+ * as `-var`, under the step's own `vars`, which win. A read whose upstream
13
+ * has no state, or no such output yet, waits: the root is not planned on a
14
+ * stand-in, and the wave says which upstream to apply first.
15
+ */
16
+ /** One var a root reads from another root's state. */
17
+ export interface TerraformStateRead {
18
+ /** The variable it sets. */
19
+ var: string;
20
+ /** The `terraform.roots` entry whose state holds the value. */
21
+ root: string;
22
+ /** The output, then the keys into its value. */
23
+ output: string[];
24
+ }
25
+ /** What filling a root's reads came to. */
26
+ export interface FilledStateReads {
27
+ /** The values, by var. Complete only when `waiting` and `errors` are empty. */
28
+ vars: Record<string, unknown>;
29
+ /** Reads whose upstream has no such value yet: the root waits for these upstreams to apply. */
30
+ waiting: Array<{
31
+ read: TerraformStateRead;
32
+ why: string;
33
+ }>;
34
+ /** Upstreams whose state could not be read at all. */
35
+ errors: string[];
36
+ }
37
+ /** What is wrong with a step's `reads`, empty when nothing is. */
38
+ export declare function stateReadsProblems(reads: unknown): string[];
39
+ /** The value a read names in its upstream's outputs, or undefined when the outputs do not have it. */
40
+ export declare function readOutputValue(outputs: Record<string, unknown>, output: readonly string[]): {
41
+ value: unknown;
42
+ } | undefined;
43
+ /**
44
+ * Fill `reads` from each upstream's outputs, read once per upstream through
45
+ * `outputsOf`, which throws when the state cannot be read.
46
+ */
47
+ export declare function fillStateReads(reads: readonly TerraformStateRead[], outputsOf: (root: string) => Promise<Record<string, unknown>>): Promise<FilledStateReads>;
48
+ /** Why a root with waiting reads was not planned, naming what to apply first. */
49
+ export declare function waitingReadsReason(waiting: FilledStateReads["waiting"]): string;
50
+ /**
51
+ * The reads an Atmos instance's edges file lists (`{ reads: [{ var,
52
+ * upstream, output }] }`, as terragucci's `atmos write` leaves beside each
53
+ * instance), with each upstream mapped to its `terraform.roots` entry by
54
+ * `rootOf` (by default the upstream's own path).
55
+ */
56
+ export declare function atmosStateReads(edges: unknown, rootOf?: (upstream: string) => string): TerraformStateRead[];
57
+ //# sourceMappingURL=state-reads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-reads.d.ts","sourceRoot":"","sources":["../src/state-reads.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,+FAA+F;IAC/F,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,sDAAsD;IACtD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAkB3D;AAED,sGAAsG;AACtG,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAS3H;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoBnK;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,GAAG,MAAM,CAG/E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAiB,GAAG,kBAAkB,EAAE,CAQrH"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Variables read from another root's state (#4545, Atmos reads moved from
3
+ * terragucci's `atmos.ts`): an Atmos stack that sets a var with
4
+ * `!terraform.state <component> [<stack>] <output>` plans on the upstream
5
+ * instance's output, which only the job that holds a credential can read.
6
+ *
7
+ * In the `terraform-apply` step a read is `{ var, root, output }`: the var it
8
+ * sets, the `terraform.roots` entry whose state holds the value (its
9
+ * directory and workspace come from that entry), and the output followed by
10
+ * the keys into its value (`.subnets.private` is `["subnets", "private"]`).
11
+ * The step reads each upstream's `output -json` once and passes the values
12
+ * as `-var`, under the step's own `vars`, which win. A read whose upstream
13
+ * has no state, or no such output yet, waits: the root is not planned on a
14
+ * stand-in, and the wave says which upstream to apply first.
15
+ */
16
+ /** What is wrong with a step's `reads`, empty when nothing is. */
17
+ export function stateReadsProblems(reads) {
18
+ if (reads === undefined)
19
+ return [];
20
+ if (!Array.isArray(reads))
21
+ return ["reads must be a list of { var, root, output }"];
22
+ const problems = [];
23
+ const vars = new Set();
24
+ for (const [i, r] of reads.entries()) {
25
+ const read = r;
26
+ if (!read || typeof read !== "object") {
27
+ problems.push(`reads[${i}] must be { var, root, output }`);
28
+ continue;
29
+ }
30
+ if (typeof read.var !== "string" || read.var === "")
31
+ problems.push(`reads[${i}].var must name a variable`);
32
+ else if (vars.has(read.var))
33
+ problems.push(`reads[${i}] sets ${read.var}, which an earlier read sets too`);
34
+ else
35
+ vars.add(read.var);
36
+ if (typeof read.root !== "string" || read.root === "")
37
+ problems.push(`reads[${i}].root must name a terraform.roots entry`);
38
+ if (!Array.isArray(read.output) || read.output.length === 0 || !read.output.every((k) => typeof k === "string" && k !== ""))
39
+ problems.push(`reads[${i}].output must be the output's name, then any keys into its value`);
40
+ }
41
+ return problems;
42
+ }
43
+ /** The value a read names in its upstream's outputs, or undefined when the outputs do not have it. */
44
+ export function readOutputValue(outputs, output) {
45
+ const [name, ...keys] = output;
46
+ if (name === undefined || !(name in outputs))
47
+ return undefined;
48
+ let v = outputs[name];
49
+ for (const k of keys) {
50
+ if (!v || typeof v !== "object" || Array.isArray(v) || !(k in v))
51
+ return undefined;
52
+ v = v[k];
53
+ }
54
+ return { value: v };
55
+ }
56
+ /**
57
+ * Fill `reads` from each upstream's outputs, read once per upstream through
58
+ * `outputsOf`, which throws when the state cannot be read.
59
+ */
60
+ export async function fillStateReads(reads, outputsOf) {
61
+ const result = { vars: {}, waiting: [], errors: [] };
62
+ const cache = new Map();
63
+ for (const read of reads) {
64
+ if (!cache.has(read.root))
65
+ cache.set(read.root, outputsOf(read.root));
66
+ let outputs;
67
+ try {
68
+ outputs = await cache.get(read.root);
69
+ }
70
+ catch (err) {
71
+ result.errors.push(`it reads ${read.var} from ${read.root}, whose state could not be read: ${err instanceof Error ? err.message : String(err)}`);
72
+ continue;
73
+ }
74
+ const got = readOutputValue(outputs, read.output);
75
+ if (!got) {
76
+ result.waiting.push({ read, why: Object.keys(outputs).length === 0 ? "has no state yet" : `has no output ${read.output.join(".")} yet` });
77
+ continue;
78
+ }
79
+ result.vars[read.var] = got.value;
80
+ }
81
+ return result;
82
+ }
83
+ /** Why a root with waiting reads was not planned, naming what to apply first. */
84
+ export function waitingReadsReason(waiting) {
85
+ const upstreams = [...new Set(waiting.map((w) => w.read.root))].sort();
86
+ return `not planned: ${waiting.map((w) => `it reads ${w.read.var} from ${w.read.root}, which ${w.why}`).join("; ")}; apply ${upstreams.join(", ")} first`;
87
+ }
88
+ /**
89
+ * The reads an Atmos instance's edges file lists (`{ reads: [{ var,
90
+ * upstream, output }] }`, as terragucci's `atmos write` leaves beside each
91
+ * instance), with each upstream mapped to its `terraform.roots` entry by
92
+ * `rootOf` (by default the upstream's own path).
93
+ */
94
+ export function atmosStateReads(edges, rootOf = (u) => u) {
95
+ const reads = edges?.reads;
96
+ if (!Array.isArray(reads))
97
+ return [];
98
+ return reads.flatMap((r) => {
99
+ const read = r;
100
+ if (!read || typeof read.var !== "string" || typeof read.upstream !== "string" || !Array.isArray(read.output) || !read.output.every((k) => typeof k === "string"))
101
+ return [];
102
+ return [{ var: read.var, root: rootOf(read.upstream), output: read.output }];
103
+ });
104
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"affected.d.ts","sourceRoot":"","sources":["../../src/terragrunt/affected.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"affected.d.ts","sourceRoot":"","sources":["../../src/terragrunt/affected.ts"],"names":[],"mappings":"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"}
@@ -190,7 +190,8 @@ export function terragruntAffected(input) {
190
190
  const moduleDirs = terragruntModuleDirs(unit);
191
191
  const called = new Map();
192
192
  for (const m of moduleDirs) {
193
- for (const d of rootWatchPaths(input.dir, { dir: m }))
193
+ // Terragrunt runs tofu when it is installed, so a module's `.tofu` files count (chant#4457).
194
+ for (const d of rootWatchPaths(input.dir, { dir: m }, "tofu"))
194
195
  if (!moduleDirs.includes(d) && !called.has(d))
195
196
  called.set(d, m);
196
197
  }
@@ -0,0 +1,54 @@
1
+ import { type Hcl2Json } from "@intentius/chant/terraform/hcl2json";
2
+ import { type SourceBinary } from "./registry/source-forms.js";
3
+ import type { RegistryProxy } from "./registry/proxies.js";
4
+ /** One module source or provider address a root uses. */
5
+ export interface UsedSource {
6
+ kind: "module" | "provider";
7
+ /** The file it is written in, relative to the project, `/`-separated. */
8
+ file: string;
9
+ /**
10
+ * The block that names it, after the module calls that reach it:
11
+ * `module.vpc`, `terraform` for a terragrunt.hcl's source,
12
+ * `required_providers.aws`, or `provider.aws` for an implied one.
13
+ */
14
+ block: string;
15
+ /** The source or address as written (`hashicorp/<name>` for an implied provider). */
16
+ source: string;
17
+ /**
18
+ * The normal form: for a module, the source without its query, normalised
19
+ * ({@link normalizeModuleSource}); for a provider, `<host>/<namespace>/<type>`
20
+ * ({@link providerAddress}), or the source as written when it is not an address.
21
+ */
22
+ normal: string;
23
+ /** For an implied provider: the block that implies it. */
24
+ implied?: string;
25
+ }
26
+ /** A local module call that could not be followed. */
27
+ export interface UnreadSource {
28
+ file: string;
29
+ block: string;
30
+ source: string;
31
+ why: string;
32
+ }
33
+ export interface UsedSourcesOptions {
34
+ /** Follow `./` and `../` module calls down the tree. Default true. */
35
+ followLocal?: boolean;
36
+ /** The project's top: file paths are relative to it, and a call that leaves it is not followed. Default the root's directory. */
37
+ project?: string;
38
+ /** Read only the files this binary reads, and default provider hosts to its registry. Default: every `.tf` and `.tofu` file, Terraform's registry. */
39
+ binary?: SourceBinary;
40
+ /** The HCL parser. Default: core's lazily loaded hcl2json. */
41
+ parser?: Hcl2Json;
42
+ /** Registry proxies (chant#4606): a source through one gets its upstream's normal form. */
43
+ proxies?: readonly RegistryProxy[];
44
+ }
45
+ /**
46
+ * Every module source and provider address the root at `dir` uses, and each
47
+ * local call that could not be followed. Throws, naming the file, when a
48
+ * file cannot be parsed, so a check fails loudly instead of checking less.
49
+ */
50
+ export declare function usedSources(dir: string, options?: UsedSourcesOptions): Promise<{
51
+ used: UsedSource[];
52
+ unread: UnreadSource[];
53
+ }>;
54
+ //# sourceMappingURL=used-sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"used-sources.d.ts","sourceRoot":"","sources":["../src/used-sources.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAElF,OAAO,EAAyE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACnI,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iIAAiI;IACjI,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sJAAsJ;IACtJ,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CACpC;AA6FD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CAkCxI"}