@intentius/chant-lexicon-terraform 0.124.54 → 0.124.56

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 (351) hide show
  1. package/README.md +7 -4
  2. package/dist/ci-setup.d.ts +11 -0
  3. package/dist/ci-setup.d.ts.map +1 -0
  4. package/dist/ci-setup.js +41 -0
  5. package/dist/components/capability-plugin.d.ts +40 -6
  6. package/dist/components/capability-plugin.d.ts.map +1 -1
  7. package/dist/components/capability-plugin.js +174 -30
  8. package/dist/components/compose-group.d.ts +1 -1
  9. package/dist/components/compose-group.d.ts.map +1 -1
  10. package/dist/components/compose-group.js +1 -1
  11. package/dist/components/release-inputs.d.ts +29 -0
  12. package/dist/components/release-inputs.d.ts.map +1 -0
  13. package/dist/components/release-inputs.js +57 -0
  14. package/dist/components/trace-facts.d.ts +16 -0
  15. package/dist/components/trace-facts.d.ts.map +1 -0
  16. package/dist/components/trace-facts.js +19 -0
  17. package/dist/cone.d.ts +53 -0
  18. package/dist/cone.d.ts.map +1 -0
  19. package/dist/cone.js +119 -0
  20. package/dist/cost-hold.d.ts +27 -0
  21. package/dist/cost-hold.d.ts.map +1 -0
  22. package/dist/cost-hold.js +21 -0
  23. package/dist/drift-rows.d.ts +61 -0
  24. package/dist/drift-rows.d.ts.map +1 -0
  25. package/dist/drift-rows.js +108 -0
  26. package/dist/exit-codes.d.ts +55 -0
  27. package/dist/exit-codes.d.ts.map +1 -0
  28. package/dist/exit-codes.js +48 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -0
  32. package/dist/integrity.json +7 -4
  33. package/dist/lint/audit-catalog.d.ts.map +1 -1
  34. package/dist/lint/audit-catalog.js +27 -3
  35. package/dist/lint/audit-lineage.d.ts +14 -2
  36. package/dist/lint/audit-lineage.d.ts.map +1 -1
  37. package/dist/lint/post-synth/index.d.ts.map +1 -1
  38. package/dist/lint/post-synth/index.js +4 -0
  39. package/dist/lint/post-synth/record-store.d.ts +54 -0
  40. package/dist/lint/post-synth/record-store.d.ts.map +1 -0
  41. package/dist/lint/post-synth/record-store.js +104 -0
  42. package/dist/lint/post-synth/tf001.d.ts +2 -2
  43. package/dist/lint/post-synth/tf001.js +2 -2
  44. package/dist/lint/post-synth/tf024.d.ts +35 -11
  45. package/dist/lint/post-synth/tf024.d.ts.map +1 -1
  46. package/dist/lint/post-synth/tf024.js +92 -20
  47. package/dist/lint/post-synth/tf046.d.ts +64 -0
  48. package/dist/lint/post-synth/tf046.d.ts.map +1 -0
  49. package/dist/lint/post-synth/tf046.js +175 -0
  50. package/dist/lint/post-synth/tf047.d.ts +36 -0
  51. package/dist/lint/post-synth/tf047.d.ts.map +1 -0
  52. package/dist/lint/post-synth/tf047.js +94 -0
  53. package/dist/lock-rows.d.ts +36 -0
  54. package/dist/lock-rows.d.ts.map +1 -0
  55. package/dist/lock-rows.js +60 -0
  56. package/dist/lock-timeout.d.ts +22 -0
  57. package/dist/lock-timeout.d.ts.map +1 -0
  58. package/dist/lock-timeout.js +32 -0
  59. package/dist/manifest.json +1 -1
  60. package/dist/module-catalog/index.d.ts +69 -0
  61. package/dist/module-catalog/index.d.ts.map +1 -0
  62. package/dist/module-catalog/index.js +110 -0
  63. package/dist/module-catalog/refresh-cli.d.ts +4 -0
  64. package/dist/module-catalog/refresh-cli.d.ts.map +1 -0
  65. package/dist/module-catalog/refresh-cli.js +64 -0
  66. package/dist/module-catalog/static-tier.d.ts +6 -0
  67. package/dist/module-catalog/static-tier.d.ts.map +1 -0
  68. package/dist/module-catalog/static-tier.js +1650 -0
  69. package/dist/module-catalog/types.d.ts +65 -0
  70. package/dist/module-catalog/types.d.ts.map +1 -0
  71. package/dist/module-catalog/types.js +33 -0
  72. package/dist/okf/index.md +3 -1
  73. package/dist/okf/rules/TF024.md +2 -2
  74. package/dist/okf/rules/TF046.md +11 -0
  75. package/dist/okf/rules/TF047.md +11 -0
  76. package/dist/op/activities/terraform.d.ts +29 -0
  77. package/dist/op/activities/terraform.d.ts.map +1 -1
  78. package/dist/op/activities/terraform.js +19 -4
  79. package/dist/pin/consumers.d.ts +35 -0
  80. package/dist/pin/consumers.d.ts.map +1 -0
  81. package/dist/pin/consumers.js +70 -0
  82. package/dist/plugin.d.ts.map +1 -1
  83. package/dist/plugin.js +5 -0
  84. package/dist/registry/address.d.ts +63 -0
  85. package/dist/registry/address.d.ts.map +1 -0
  86. package/dist/registry/address.js +65 -0
  87. package/dist/registry/catalog-read.d.ts +14 -0
  88. package/dist/registry/catalog-read.d.ts.map +1 -0
  89. package/dist/registry/catalog-read.js +58 -0
  90. package/dist/registry/deprecated.d.ts +37 -0
  91. package/dist/registry/deprecated.d.ts.map +1 -0
  92. package/dist/registry/deprecated.js +43 -0
  93. package/dist/registry/docs.d.ts +96 -0
  94. package/dist/registry/docs.d.ts.map +1 -0
  95. package/dist/registry/docs.js +210 -0
  96. package/dist/registry/edge/edge.d.ts +46 -0
  97. package/dist/registry/edge/edge.d.ts.map +1 -0
  98. package/dist/registry/edge/edge.js +194 -0
  99. package/dist/registry/edge/index.d.ts +11 -0
  100. package/dist/registry/edge/index.d.ts.map +1 -0
  101. package/dist/registry/edge/index.js +10 -0
  102. package/dist/registry/edge/lambda-edge.d.ts +76 -0
  103. package/dist/registry/edge/lambda-edge.d.ts.map +1 -0
  104. package/dist/registry/edge/lambda-edge.js +95 -0
  105. package/dist/registry/edge/sigv4-web.d.ts +33 -0
  106. package/dist/registry/edge/sigv4-web.d.ts.map +1 -0
  107. package/dist/registry/edge/sigv4-web.js +56 -0
  108. package/dist/registry/edge/token-source.d.ts +73 -0
  109. package/dist/registry/edge/token-source.d.ts.map +1 -0
  110. package/dist/registry/edge/token-source.js +115 -0
  111. package/dist/registry/edge/worker.d.ts +45 -0
  112. package/dist/registry/edge/worker.d.ts.map +1 -0
  113. package/dist/registry/edge/worker.js +26 -0
  114. package/dist/registry/handler.d.ts +25 -0
  115. package/dist/registry/handler.d.ts.map +1 -0
  116. package/dist/registry/handler.js +75 -0
  117. package/dist/registry/headers-file.d.ts +21 -0
  118. package/dist/registry/headers-file.d.ts.map +1 -0
  119. package/dist/registry/headers-file.js +57 -0
  120. package/dist/registry/index.d.ts +31 -0
  121. package/dist/registry/index.d.ts.map +1 -0
  122. package/dist/registry/index.js +30 -0
  123. package/dist/registry/mirror-paths.d.ts +9 -0
  124. package/dist/registry/mirror-paths.d.ts.map +1 -0
  125. package/dist/registry/mirror-paths.js +8 -0
  126. package/dist/registry/mirror.d.ts +130 -0
  127. package/dist/registry/mirror.d.ts.map +1 -0
  128. package/dist/registry/mirror.js +319 -0
  129. package/dist/registry/proxies.d.ts +73 -0
  130. package/dist/registry/proxies.d.ts.map +1 -0
  131. package/dist/registry/proxies.js +111 -0
  132. package/dist/registry/reader.d.ts +57 -0
  133. package/dist/registry/reader.d.ts.map +1 -0
  134. package/dist/registry/reader.js +198 -0
  135. package/dist/registry/semver.d.ts +16 -0
  136. package/dist/registry/semver.d.ts.map +1 -0
  137. package/dist/registry/semver.js +24 -0
  138. package/dist/registry/serve.d.ts +24 -0
  139. package/dist/registry/serve.d.ts.map +1 -0
  140. package/dist/registry/serve.js +64 -0
  141. package/dist/registry/source-forms.d.ts +79 -0
  142. package/dist/registry/source-forms.d.ts.map +1 -0
  143. package/dist/registry/source-forms.js +202 -0
  144. package/dist/registry/targets/artifactory.d.ts +28 -0
  145. package/dist/registry/targets/artifactory.d.ts.map +1 -0
  146. package/dist/registry/targets/artifactory.js +206 -0
  147. package/dist/registry/targets/fake-artifactory.d.ts +30 -0
  148. package/dist/registry/targets/fake-artifactory.d.ts.map +1 -0
  149. package/dist/registry/targets/fake-artifactory.js +142 -0
  150. package/dist/registry/targets/fake-gitlab.d.ts +39 -0
  151. package/dist/registry/targets/fake-gitlab.d.ts.map +1 -0
  152. package/dist/registry/targets/fake-gitlab.js +136 -0
  153. package/dist/registry/targets/fake-hcp.d.ts +50 -0
  154. package/dist/registry/targets/fake-hcp.d.ts.map +1 -0
  155. package/dist/registry/targets/fake-hcp.js +202 -0
  156. package/dist/registry/targets/fake-http.d.ts +31 -0
  157. package/dist/registry/targets/fake-http.d.ts.map +1 -0
  158. package/dist/registry/targets/fake-http.js +87 -0
  159. package/dist/registry/targets/fake-nexus.d.ts +27 -0
  160. package/dist/registry/targets/fake-nexus.d.ts.map +1 -0
  161. package/dist/registry/targets/fake-nexus.js +137 -0
  162. package/dist/registry/targets/gitlab.d.ts +53 -0
  163. package/dist/registry/targets/gitlab.d.ts.map +1 -0
  164. package/dist/registry/targets/gitlab.js +187 -0
  165. package/dist/registry/targets/hcp.d.ts +29 -0
  166. package/dist/registry/targets/hcp.d.ts.map +1 -0
  167. package/dist/registry/targets/hcp.js +310 -0
  168. package/dist/registry/targets/hosted.d.ts +62 -0
  169. package/dist/registry/targets/hosted.d.ts.map +1 -0
  170. package/dist/registry/targets/hosted.js +74 -0
  171. package/dist/registry/targets/index.d.ts +18 -0
  172. package/dist/registry/targets/index.d.ts.map +1 -0
  173. package/dist/registry/targets/index.js +17 -0
  174. package/dist/registry/targets/module-target.d.ts +68 -0
  175. package/dist/registry/targets/module-target.d.ts.map +1 -0
  176. package/dist/registry/targets/module-target.js +63 -0
  177. package/dist/registry/targets/nexus.d.ts +43 -0
  178. package/dist/registry/targets/nexus.d.ts.map +1 -0
  179. package/dist/registry/targets/nexus.js +250 -0
  180. package/dist/registry/targets/zip.d.ts +55 -0
  181. package/dist/registry/targets/zip.d.ts.map +1 -0
  182. package/dist/registry/targets/zip.js +278 -0
  183. package/dist/registry/writer.d.ts +101 -0
  184. package/dist/registry/writer.d.ts.map +1 -0
  185. package/dist/registry/writer.js +109 -0
  186. package/dist/rules/record-store.ts +122 -0
  187. package/dist/rules/tf001.ts +2 -2
  188. package/dist/rules/tf024.ts +105 -22
  189. package/dist/rules/tf046.ts +204 -0
  190. package/dist/rules/tf047.ts +114 -0
  191. package/dist/state/azure-blob.d.ts +8 -67
  192. package/dist/state/azure-blob.d.ts.map +1 -1
  193. package/dist/state/azure-blob.js +6 -199
  194. package/dist/state/gcs.d.ts +7 -61
  195. package/dist/state/gcs.d.ts.map +1 -1
  196. package/dist/state/gcs.js +5 -222
  197. package/dist/state/object-store.d.ts +4 -33
  198. package/dist/state/object-store.d.ts.map +1 -1
  199. package/dist/state/object-store.js +4 -17
  200. package/dist/state/s3.d.ts +11 -58
  201. package/dist/state/s3.d.ts.map +1 -1
  202. package/dist/state/s3.js +10 -161
  203. package/dist/state/store.js +2 -2
  204. package/dist/state-ops.d.ts +255 -0
  205. package/dist/state-ops.d.ts.map +1 -0
  206. package/dist/state-ops.js +305 -0
  207. package/dist/state-reads.d.ts +57 -0
  208. package/dist/state-reads.d.ts.map +1 -0
  209. package/dist/state-reads.js +104 -0
  210. package/dist/used-sources.d.ts +54 -0
  211. package/dist/used-sources.d.ts.map +1 -0
  212. package/dist/used-sources.js +157 -0
  213. package/package.json +19 -3
  214. package/src/__fixtures__/drift-record/README.md +5 -0
  215. package/src/__fixtures__/drift-rows/live-root-plan.json +70 -0
  216. package/src/__fixtures__/drift-rows/refresh-plan.json +61 -0
  217. package/src/__fixtures__/used-sources/root/extra.tofu +1 -0
  218. package/src/__fixtures__/used-sources/root/main.tf +31 -0
  219. package/src/__fixtures__/used-sources/root/modules/net/main.tf +14 -0
  220. package/src/__fixtures__/used-sources/root/modules/net/versions.tf.json +7 -0
  221. package/src/__fixtures__/used-sources/unit/terragrunt.hcl +3 -0
  222. package/src/ci-setup.ts +42 -0
  223. package/src/components/capability-plugin.test.ts +26 -14
  224. package/src/components/capability-plugin.ts +185 -31
  225. package/src/components/compose-group.ts +1 -1
  226. package/src/components/pr-loop-compose.tofu.e2e.test.ts +1 -1
  227. package/src/components/pr-loop.tofu.test.ts +1 -1
  228. package/src/components/release-inputs.ts +69 -0
  229. package/src/components/trace-facts.test.ts +21 -0
  230. package/src/components/trace-facts.ts +27 -0
  231. package/src/cone.ts +138 -0
  232. package/src/cost-hold.ts +29 -0
  233. package/src/describe-resources.engine-facts.test.ts +2 -3
  234. package/src/drift-rows.test.ts +135 -0
  235. package/src/drift-rows.ts +137 -0
  236. package/src/exit-codes.test.ts +23 -0
  237. package/src/exit-codes.ts +59 -0
  238. package/src/index.ts +3 -0
  239. package/src/lint/audit-catalog.ts +29 -3
  240. package/src/lint/audit-lineage.ts +14 -2
  241. package/src/lint/post-synth/fixtures/TF024/live-with-record-store/main.tf +18 -0
  242. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/estate.chdf.hcl +1 -0
  243. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/main.tf +10 -0
  244. package/src/lint/post-synth/fixtures/TF046/azurerm-no-resource-group/main.tf +15 -0
  245. package/src/lint/post-synth/fixtures/TF046/backend-config-only/main.tf +14 -0
  246. package/src/lint/post-synth/fixtures/TF046/derived-s3/backend.tf +7 -0
  247. package/src/lint/post-synth/fixtures/TF046/derived-s3/main.tf +9 -0
  248. package/src/lint/post-synth/fixtures/TF046/explicit-local/main.tf +16 -0
  249. package/src/lint/post-synth/fixtures/TF046/explicit-s3-beside-local-backend/main.tf +15 -0
  250. package/src/lint/post-synth/fixtures/TF046/implied-local/main.tf +9 -0
  251. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/estate.chdf.hcl +1 -0
  252. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/main.tf +5 -0
  253. package/src/lint/post-synth/fixtures/TF047/clear/main.tf +12 -0
  254. package/src/lint/post-synth/fixtures/TF047/refused/main.tf +12 -0
  255. package/src/lint/post-synth/fixtures/TF047/unknown-module/main.tf +12 -0
  256. package/src/lint/post-synth/fixtures/TF047/unknown-version/main.tf +12 -0
  257. package/src/lint/post-synth/index.ts +4 -0
  258. package/src/lint/post-synth/record-store.ts +122 -0
  259. package/src/lint/post-synth/tf001.ts +2 -2
  260. package/src/lint/post-synth/tf024.test.ts +26 -5
  261. package/src/lint/post-synth/tf024.ts +105 -22
  262. package/src/lint/post-synth/tf046.test.ts +137 -0
  263. package/src/lint/post-synth/tf046.ts +204 -0
  264. package/src/lint/post-synth/tf047.test.ts +56 -0
  265. package/src/lint/post-synth/tf047.ts +114 -0
  266. package/src/lock-rows.test.ts +70 -0
  267. package/src/lock-rows.ts +82 -0
  268. package/src/lock-timeout.ts +34 -0
  269. package/src/module-catalog/index.test.ts +93 -0
  270. package/src/module-catalog/index.ts +159 -0
  271. package/src/module-catalog/refresh-cli.ts +68 -0
  272. package/src/module-catalog/static-tier.ts +1659 -0
  273. package/src/module-catalog/types.ts +88 -0
  274. package/src/op/activities/terraform.ts +46 -5
  275. package/src/op-wave-step.test.ts +109 -0
  276. package/src/pin/__fixtures__/consumers/live/dev/main.tf +4 -0
  277. package/src/pin/__fixtures__/consumers/live/prod/main.tf +21 -0
  278. package/src/pin/__fixtures__/consumers/units/vpc/terragrunt.hcl +7 -0
  279. package/src/pin/consumers.test.ts +57 -0
  280. package/src/pin/consumers.ts +95 -0
  281. package/src/plugin.ts +6 -0
  282. package/src/registry/__fixtures__/docs/documented/.terraform-docs.yml +3 -0
  283. package/src/registry/__fixtures__/docs/documented/README.md +1 -0
  284. package/src/registry/__fixtures__/docs/documented/main.tf +8 -0
  285. package/src/registry/__fixtures__/docs/json/main.tf.json +14 -0
  286. package/src/registry/__fixtures__/docs/vpc/README.md +3 -0
  287. package/src/registry/__fixtures__/docs/vpc/examples/complete/main.tf +5 -0
  288. package/src/registry/__fixtures__/docs/vpc/examples/simple/README.md +1 -0
  289. package/src/registry/__fixtures__/docs/vpc/examples/simple/main.tf +4 -0
  290. package/src/registry/__fixtures__/docs/vpc/main.tf +14 -0
  291. package/src/registry/__fixtures__/docs/vpc/outputs.tf +9 -0
  292. package/src/registry/__fixtures__/docs/vpc/variables.tf +16 -0
  293. package/src/registry/__fixtures__/proxied-root/main.tf +12 -0
  294. package/src/registry/address.ts +100 -0
  295. package/src/registry/catalog-read.ts +56 -0
  296. package/src/registry/deprecated.test.ts +139 -0
  297. package/src/registry/deprecated.ts +76 -0
  298. package/src/registry/docs.test.ts +140 -0
  299. package/src/registry/docs.ts +299 -0
  300. package/src/registry/edge/bundle.test.ts +50 -0
  301. package/src/registry/edge/edge.test.ts +176 -0
  302. package/src/registry/edge/edge.ts +211 -0
  303. package/src/registry/edge/index.ts +10 -0
  304. package/src/registry/edge/lambda-edge.ts +127 -0
  305. package/src/registry/edge/sigv4-web.ts +79 -0
  306. package/src/registry/edge/token-source.test.ts +258 -0
  307. package/src/registry/edge/token-source.ts +169 -0
  308. package/src/registry/edge/worker.ts +61 -0
  309. package/src/registry/handler.ts +89 -0
  310. package/src/registry/headers-file.ts +61 -0
  311. package/src/registry/index.ts +31 -0
  312. package/src/registry/mirror-paths.ts +10 -0
  313. package/src/registry/mirror.test.ts +198 -0
  314. package/src/registry/mirror.ts +395 -0
  315. package/src/registry/proxies.test.ts +153 -0
  316. package/src/registry/proxies.ts +132 -0
  317. package/src/registry/reader.ts +225 -0
  318. package/src/registry/registry.test.ts +262 -0
  319. package/src/registry/semver.ts +34 -0
  320. package/src/registry/serve.ts +82 -0
  321. package/src/registry/source-forms.test.ts +87 -0
  322. package/src/registry/source-forms.ts +216 -0
  323. package/src/registry/targets/artifactory.test.ts +248 -0
  324. package/src/registry/targets/artifactory.ts +257 -0
  325. package/src/registry/targets/fake-artifactory.ts +158 -0
  326. package/src/registry/targets/fake-gitlab.ts +161 -0
  327. package/src/registry/targets/fake-hcp.ts +233 -0
  328. package/src/registry/targets/fake-http.ts +97 -0
  329. package/src/registry/targets/fake-nexus.ts +152 -0
  330. package/src/registry/targets/gitlab.test.ts +208 -0
  331. package/src/registry/targets/gitlab.ts +223 -0
  332. package/src/registry/targets/hcp.test.ts +230 -0
  333. package/src/registry/targets/hcp.ts +360 -0
  334. package/src/registry/targets/hosted.ts +117 -0
  335. package/src/registry/targets/index.ts +17 -0
  336. package/src/registry/targets/module-target.ts +131 -0
  337. package/src/registry/targets/nexus.test.ts +220 -0
  338. package/src/registry/targets/nexus.ts +314 -0
  339. package/src/registry/targets/zip.test.ts +65 -0
  340. package/src/registry/targets/zip.ts +287 -0
  341. package/src/registry/writer.ts +155 -0
  342. package/src/state/azure-blob.ts +6 -221
  343. package/src/state/gcs.ts +5 -252
  344. package/src/state/object-store.ts +4 -32
  345. package/src/state/s3.ts +10 -182
  346. package/src/state/store.ts +2 -2
  347. package/src/state-ops.test.ts +182 -0
  348. package/src/state-ops.ts +462 -0
  349. package/src/state-reads.ts +116 -0
  350. package/src/used-sources.test.ts +75 -0
  351. package/src/used-sources.ts +204 -0
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Where the Lambda@Edge function gets its accepted tokens (chant#4590).
3
+ * Lambda@Edge has no environment of its own, so by default the tokens are
4
+ * built into the zip (`source: { kind: "zip" }`, terragucci#1287's
5
+ * registry-edge.json). The function can instead read them from SSM Parameter
6
+ * Store or Secrets Manager: the read starts when the handler is made (the
7
+ * cold start), its answer is kept for `cacheSeconds`, and a rotation in the
8
+ * store reaches every replica within that time with no redeploy.
9
+ *
10
+ * The read fails closed: while the store cannot be read, or holds no token,
11
+ * every request gets a 503 and none reaches the bucket.
12
+ *
13
+ * The reads are plain fetch calls signed with ./sigv4-web.ts (Web Crypto),
14
+ * so registry/edge stays free of Node built-ins (chant#4589). Credentials
15
+ * default to the execution role's, which the Lambda runtime puts in
16
+ * AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN; the role
17
+ * needs ssm:GetParameter (and kms:Decrypt for a SecureString under a key of
18
+ * your own) or secretsmanager:GetSecretValue on that one name.
19
+ */
20
+ import { tokensFromSecret } from "./edge.js";
21
+ import { signV4Web } from "./sigv4-web.js";
22
+ export const DEFAULT_TOKEN_CACHE_SECONDS = 300;
23
+ export const MAX_TOKEN_CACHE_SECONDS = 3600;
24
+ /** After a failed read, requests are refused for this long before the next read, so a broken store is not read once per request. */
25
+ export const FAILED_READ_BACKOFF_MS = 5000;
26
+ /**
27
+ * A stored value as tokens. Either the worker's REGISTRY_TOKENS form (one per
28
+ * line or comma separated) or JSON: `{ "tokens": [...] | "a,b", "signingKey": "..." }`.
29
+ */
30
+ export function parseStoredTokens(text) {
31
+ const trimmed = text.trim();
32
+ if (trimmed.startsWith("{")) {
33
+ let doc;
34
+ try {
35
+ doc = JSON.parse(trimmed);
36
+ }
37
+ catch {
38
+ throw new Error("the stored tokens look like JSON but do not parse");
39
+ }
40
+ const tokens = Array.isArray(doc.tokens) ? doc.tokens.filter((t) => typeof t === "string").map((t) => t.trim()).filter((t) => !!t) : typeof doc.tokens === "string" ? tokensFromSecret(doc.tokens) : [];
41
+ return { tokens, ...(typeof doc.signingKey === "string" && doc.signingKey ? { signingKey: doc.signingKey } : {}) };
42
+ }
43
+ return { tokens: tokensFromSecret(trimmed) };
44
+ }
45
+ /** The execution role's credentials, read from the runtime's environment without importing node:process. */
46
+ function runtimeCredentials() {
47
+ const env = globalThis.process?.env ?? {};
48
+ const accessKeyId = env.AWS_ACCESS_KEY_ID;
49
+ const secretAccessKey = env.AWS_SECRET_ACCESS_KEY;
50
+ if (!accessKeyId || !secretAccessKey)
51
+ throw new Error("no AWS credentials in the function's runtime (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)");
52
+ return { accessKeyId, secretAccessKey, ...(env.AWS_SESSION_TOKEN ? { sessionToken: env.AWS_SESSION_TOKEN } : {}) };
53
+ }
54
+ const defaultFetch = (url, init) => fetch(url, init);
55
+ /** One read of the store: the signed JSON call, and the value it answers. */
56
+ export async function readStoredTokens(source, now = new Date()) {
57
+ const region = source.region ?? "us-east-1";
58
+ const service = source.kind === "ssm" ? "ssm" : "secretsmanager";
59
+ const url = `https://${service}.${region}.amazonaws.com/`;
60
+ const target = source.kind === "ssm" ? "AmazonSSM.GetParameter" : "secretsmanager.GetSecretValue";
61
+ const body = JSON.stringify(source.kind === "ssm" ? { Name: source.name, WithDecryption: true } : { SecretId: source.secretId });
62
+ const credentials = typeof source.credentials === "function" ? await source.credentials() : (source.credentials ?? runtimeCredentials());
63
+ const headers = await signV4Web({ method: "POST", url, headers: { "content-type": "application/x-amz-json-1.1", "x-amz-target": target }, body, region, service, credentials, now });
64
+ const res = await (source.fetch ?? defaultFetch)(url, { method: "POST", headers, body });
65
+ const text = await res.text();
66
+ const what = source.kind === "ssm" ? `SSM parameter ${source.name}` : `secret ${source.secretId}`;
67
+ if (!res.ok) {
68
+ let type = "";
69
+ try {
70
+ type = String(JSON.parse(text).__type ?? "").split("#").pop() ?? "";
71
+ }
72
+ catch { }
73
+ throw new Error(`reading ${what} in ${region} answered ${res.status}${type ? ` ${type}` : ""}`);
74
+ }
75
+ let value;
76
+ try {
77
+ const doc = JSON.parse(text);
78
+ value = source.kind === "ssm" ? doc.Parameter?.Value : doc.SecretString;
79
+ }
80
+ catch {
81
+ throw new Error(`reading ${what} answered something other than JSON`);
82
+ }
83
+ if (typeof value !== "string")
84
+ throw new Error(`${what} has no text value${source.kind === "secrets-manager" ? " (a binary secret is not read)" : ""}`);
85
+ const stored = parseStoredTokens(value);
86
+ if (stored.tokens.length === 0)
87
+ throw new Error(`${what} holds no token`);
88
+ return stored;
89
+ }
90
+ /**
91
+ * A cache over `readStoredTokens`. The first read starts at once (cold
92
+ * start). Requests that arrive during a read wait on that one read. A good
93
+ * read is kept for `cacheSeconds`; a failed one is kept for
94
+ * FAILED_READ_BACKOFF_MS, and every `get` in that time throws. The last good
95
+ * tokens are never served past their time, so the function fails closed.
96
+ */
97
+ export function storedTokenCache(source, now = Date.now) {
98
+ const cacheMs = Math.min(Math.max(source.cacheSeconds ?? DEFAULT_TOKEN_CACHE_SECONDS, 0), MAX_TOKEN_CACHE_SECONDS) * 1000;
99
+ let held;
100
+ const read = () => {
101
+ const result = readStoredTokens(source, new Date(now()));
102
+ const entry = { until: Number.POSITIVE_INFINITY, result };
103
+ held = entry;
104
+ result.then(() => {
105
+ entry.until = now() + cacheMs;
106
+ }, () => {
107
+ entry.until = now() + FAILED_READ_BACKOFF_MS;
108
+ });
109
+ return result;
110
+ };
111
+ read().catch(() => { });
112
+ return {
113
+ get: () => (held && now() < held.until ? held.result : read()),
114
+ };
115
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The registry edge function as a Cloudflare Worker (chant#4566). Bindings:
3
+ *
4
+ * REGISTRY_BUCKET an R2 bucket binding holding the registry's files, or
5
+ * REGISTRY_ORIGIN the bucket's HTTP endpoint, when the files are elsewhere
6
+ * REGISTRY_PREFIX the registry's prefix in the bucket (optional)
7
+ * REGISTRY_AUTH "token" turns read auth on; anything else, or unset, leaves it off
8
+ * REGISTRY_TOKENS a secret: the accepted tokens, one per line or comma separated
9
+ * REGISTRY_SIGNING_KEY a secret: the key tarball URLs are signed with (default: the first token)
10
+ * REGISTRY_URL_TTL seconds a signed tarball URL works (default 300)
11
+ *
12
+ * Rotating a token: add the new one to REGISTRY_TOKENS beside the old, move
13
+ * the CLIs to it, then drop the old one. Rotating the signing key breaks only
14
+ * signed URLs already handed out, which live for REGISTRY_URL_TTL seconds.
15
+ *
16
+ * No Node APIs, so it runs without the nodejs_compat flag.
17
+ */
18
+ import type { RegistryFiles } from "../handler.js";
19
+ import { type EdgeAuth } from "./edge.js";
20
+ /** The part of an R2 bucket binding the worker uses. */
21
+ export interface R2BucketLike {
22
+ get(key: string): Promise<{
23
+ arrayBuffer(): Promise<ArrayBuffer>;
24
+ } | null>;
25
+ }
26
+ export interface RegistryWorkerEnv {
27
+ REGISTRY_BUCKET?: R2BucketLike;
28
+ REGISTRY_ORIGIN?: string;
29
+ REGISTRY_PREFIX?: string;
30
+ REGISTRY_AUTH?: string;
31
+ REGISTRY_TOKENS?: string;
32
+ REGISTRY_SIGNING_KEY?: string;
33
+ REGISTRY_URL_TTL?: string;
34
+ }
35
+ /** Files read from an R2 binding. */
36
+ export declare const r2Files: (bucket: R2BucketLike) => RegistryFiles;
37
+ /** Read auth from the worker's bindings, or undefined when it is off. */
38
+ export declare function workerAuth(env: RegistryWorkerEnv): EdgeAuth | undefined;
39
+ /** Answers one request with the worker's bindings. */
40
+ export declare function registryWorkerFetch(request: Request, env: RegistryWorkerEnv): Promise<Response>;
41
+ /** The module a worker's entry file re-exports as its default. */
42
+ export declare const registryWorker: {
43
+ fetch: typeof registryWorkerFetch;
44
+ };
45
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/registry/edge/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAmE,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAExG,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,YAAY,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qCAAqC;AACrC,eAAO,MAAM,OAAO,WAAY,YAAY,KAAG,aAG9C,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,GAAG,EAAE,iBAAiB,GAAG,QAAQ,GAAG,SAAS,CAQvE;AAED,sDAAsD;AACtD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAIrG;AAED,kEAAkE;AAClE,eAAO,MAAM,cAAc;IAAK,KAAK;CAAuB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { DEFAULT_SIGNED_TTL, originFiles, registryEdge, tokensFromSecret } from "./edge.js";
2
+ /** Files read from an R2 binding. */
3
+ export const r2Files = (bucket) => async (key) => {
4
+ const o = await bucket.get(key);
5
+ return o ? { body: new Uint8Array(await o.arrayBuffer()) } : {};
6
+ };
7
+ /** Read auth from the worker's bindings, or undefined when it is off. */
8
+ export function workerAuth(env) {
9
+ if ((env.REGISTRY_AUTH ?? "").trim().toLowerCase() !== "token")
10
+ return undefined;
11
+ const ttl = Number(env.REGISTRY_URL_TTL);
12
+ return {
13
+ tokens: tokensFromSecret(env.REGISTRY_TOKENS),
14
+ ...(env.REGISTRY_SIGNING_KEY ? { signingKey: env.REGISTRY_SIGNING_KEY } : {}),
15
+ ttl: Number.isInteger(ttl) && ttl > 0 ? ttl : DEFAULT_SIGNED_TTL,
16
+ };
17
+ }
18
+ /** Answers one request with the worker's bindings. */
19
+ export async function registryWorkerFetch(request, env) {
20
+ const files = env.REGISTRY_BUCKET ? r2Files(env.REGISTRY_BUCKET) : env.REGISTRY_ORIGIN ? originFiles(env.REGISTRY_ORIGIN) : undefined;
21
+ if (!files)
22
+ return new Response("the registry worker needs a REGISTRY_BUCKET binding or REGISTRY_ORIGIN\n", { status: 500 });
23
+ return registryEdge({ files, prefix: env.REGISTRY_PREFIX, auth: workerAuth(env) })(request);
24
+ }
25
+ /** The module a worker's entry file re-exports as its default. */
26
+ export const registryWorker = { fetch: registryWorkerFetch };
@@ -0,0 +1,25 @@
1
+ import type { RegistryFetch } from "./reader.js";
2
+ /** Where the handler reads the registry's files: a key in, the bytes out (or none). */
3
+ export type RegistryFiles = (key: string) => Promise<{
4
+ body?: string | Uint8Array;
5
+ }>;
6
+ /** A registry held by a store with a text `read` (a bucket client, a test's map). Tarballs need a store that reads bytes. */
7
+ export declare const storeFiles: (store: {
8
+ read(key: string): Promise<{
9
+ body?: string | Uint8Array;
10
+ }>;
11
+ }) => RegistryFiles;
12
+ export interface RegistryHandlerOptions {
13
+ /** The registry's prefix in its store: URL path `p` reads key `<prefix>/p`. */
14
+ prefix?: string;
15
+ /** Called once per request, for a test's log: method, path and the status sent. */
16
+ log?: (line: string) => void;
17
+ }
18
+ export type RegistryHandler = (request: Request) => Promise<Response>;
19
+ /** The `content-type` a registry file is served with. */
20
+ export declare const registryContentType: (key: string) => string;
21
+ /** Answers GET and HEAD for a registry's files, adding `X-Terraform-Get` to each download answer. */
22
+ export declare function registryHandler(files: RegistryFiles, options?: RegistryHandlerOptions): RegistryHandler;
23
+ /** A fetch that answers from a handler in process, for tests that need no socket. */
24
+ export declare const handlerFetch: (handler: RegistryHandler) => RegistryFetch;
25
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/registry/handler.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,uFAAuF;AACvF,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAC,CAAC;AAErF,6HAA6H;AAC7H,eAAO,MAAM,UAAU,UAAW;IAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAC,CAAA;CAAE,KAAG,aAAyC,CAAC;AAE7I,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AActE,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,QAAS,MAAM,KAAG,MAKjD,CAAC;AAKF,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,sBAA2B,GAAG,eAAe,CA8B3G;AAED,qFAAqF;AACrF,eAAO,MAAM,YAAY,YAAa,eAAe,KAAG,aAAiJ,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Answering registry requests as the CLIs need them: each file as stored,
3
+ * except a version's `download`, which goes out as `downloadAnswer` (200, the
4
+ * JSON body, and `X-Terraform-Get` from the body's location; terragucci#1287).
5
+ *
6
+ * `registryHandler` is a web-standard `(Request) => Response` with no Node
7
+ * imports, so the same code answers in an edge function (chant#4566), in a
8
+ * test as a fetch (`handlerFetch`), and on a loopback socket through
9
+ * `serveRegistry` in ./serve, which real `terraform init` and `tofu init`
10
+ * runs point at.
11
+ */
12
+ import { keyFor } from "./address.js";
13
+ import { downloadAnswer, downloadLocation, isDownloadPath } from "./writer.js";
14
+ /** A registry held by a store with a text `read` (a bucket client, a test's map). Tarballs need a store that reads bytes. */
15
+ export const storeFiles = (store) => (key) => store.read(key);
16
+ /**
17
+ * The pages a release catalog writes beside the registry (chant#4599,
18
+ * `<prefix>/catalog/`), by extension, so a browser renders them instead of
19
+ * downloading them.
20
+ */
21
+ const PAGE_TYPES = {
22
+ ".html": "text/html; charset=utf-8",
23
+ ".css": "text/css; charset=utf-8",
24
+ ".js": "text/javascript; charset=utf-8",
25
+ ".svg": "image/svg+xml",
26
+ };
27
+ /** The `content-type` a registry file is served with. */
28
+ export const registryContentType = (key) => {
29
+ if (key.endsWith(".tar.gz") || key.endsWith(".tgz"))
30
+ return "application/gzip";
31
+ if (key.endsWith(".json") || /(^|\/)(versions|download)$/.test(key))
32
+ return "application/json";
33
+ const dot = key.lastIndexOf(".");
34
+ return (dot > key.lastIndexOf("/") && PAGE_TYPES[key.slice(dot).toLowerCase()]) || "application/octet-stream";
35
+ };
36
+ // TextEncoder and TextDecoder, not Buffer: an edge runtime (a Cloudflare Worker without nodejs_compat) has no Buffer.
37
+ const asText = (body) => (typeof body === "string" ? body : new TextDecoder().decode(body));
38
+ /** Answers GET and HEAD for a registry's files, adding `X-Terraform-Get` to each download answer. */
39
+ export function registryHandler(files, options = {}) {
40
+ return async (request) => {
41
+ const url = new URL(request.url);
42
+ const method = request.method.toUpperCase();
43
+ const done = (res) => {
44
+ options.log?.(`${method} ${url.pathname} -> ${res.status}`);
45
+ return res;
46
+ };
47
+ if (method !== "GET" && method !== "HEAD")
48
+ return done(new Response(null, { status: 405, headers: { allow: "GET, HEAD" } }));
49
+ let path;
50
+ try {
51
+ path = decodeURIComponent(url.pathname).replace(/^\/+/, "");
52
+ }
53
+ catch {
54
+ return done(new Response(null, { status: 400 }));
55
+ }
56
+ if (!path || path.split("/").includes(".."))
57
+ return done(new Response(null, { status: 404 }));
58
+ const key = keyFor(options.prefix, path);
59
+ const { body } = await files(key);
60
+ if (body === undefined)
61
+ return done(new Response(null, { status: 404 }));
62
+ if (isDownloadPath(path)) {
63
+ const location = downloadLocation(asText(body));
64
+ if (location) {
65
+ const answer = downloadAnswer(location);
66
+ return done(new Response(method === "HEAD" ? null : answer.body, { status: answer.status, headers: answer.headers }));
67
+ }
68
+ }
69
+ const bytes = typeof body === "string" ? new TextEncoder().encode(body) : body;
70
+ const headers = { "content-type": registryContentType(key), "content-length": String(bytes.byteLength) };
71
+ return done(new Response(method === "HEAD" ? null : new Uint8Array(bytes), { status: 200, headers }));
72
+ };
73
+ }
74
+ /** A fetch that answers from a handler in process, for tests that need no socket. */
75
+ export const handlerFetch = (handler) => (url, init) => handler(new Request(url, { method: init?.method ?? "GET", ...(init?.headers ? { headers: init.headers } : {}) }));
@@ -0,0 +1,21 @@
1
+ /** The file's name at the site's root. */
2
+ export declare const HEADERS_FILE = "_headers";
3
+ /** Rules Cloudflare Pages reads from `_headers`. */
4
+ export declare const PAGES_HEADER_RULES = 100;
5
+ /** One download path (from the site root, leading `/`) and the location its header names. */
6
+ export interface DownloadHeaderRule {
7
+ path: string;
8
+ location: string;
9
+ }
10
+ /** The download rules an existing `_headers` file holds; other rules are kept by `headersFile` as they are. */
11
+ export declare function readHeadersFile(text: string | undefined): {
12
+ downloads: DownloadHeaderRule[];
13
+ other: string[];
14
+ };
15
+ /**
16
+ * A `_headers` file with a rule per download, merged into `existing`: rules
17
+ * for other paths stay as written, a download rule for the same path is
18
+ * replaced, and download rules are sorted by path.
19
+ */
20
+ export declare function headersFile(rules: DownloadHeaderRule[], existing?: string): string;
21
+ //# sourceMappingURL=headers-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headers-file.d.ts","sourceRoot":"","sources":["../../src/registry/headers-file.ts"],"names":[],"mappings":"AAYA,0CAA0C;AAC1C,eAAO,MAAM,YAAY,aAAa,CAAC;AACvC,oDAAoD;AACpD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,6FAA6F;AAC7F,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,+GAA+G;AAC/G,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAqB9G;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAMlF"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The `_headers` file Cloudflare Pages and Netlify read beside a static site
3
+ * (terragucci#1287): one rule per version's download path, sending
4
+ * `X-Terraform-Get` with the location the stored body names. A host that
5
+ * reads `_headers` needs no edge function for Terraform to install; a plain
6
+ * bucket, GitHub Pages and GitLab Pages can't set a header per object and do.
7
+ *
8
+ * Cloudflare Pages reads at most 100 rules from `_headers`; a registry with
9
+ * more versions than that needs the edge function there.
10
+ */
11
+ import { DOWNLOAD_HEADER } from "./writer.js";
12
+ /** The file's name at the site's root. */
13
+ export const HEADERS_FILE = "_headers";
14
+ /** Rules Cloudflare Pages reads from `_headers`. */
15
+ export const PAGES_HEADER_RULES = 100;
16
+ const rulePath = (path) => `/${path.replace(/^\/+/, "")}`;
17
+ /** The download rules an existing `_headers` file holds; other rules are kept by `headersFile` as they are. */
18
+ export function readHeadersFile(text) {
19
+ const downloads = [];
20
+ const other = [];
21
+ let current;
22
+ const flush = () => {
23
+ if (!current)
24
+ return;
25
+ const header = current.lines.map((l) => /^\s+([^:]+):\s*(.*)$/.exec(l)).find((m) => m && m[1].trim().toLowerCase() === DOWNLOAD_HEADER.toLowerCase());
26
+ if (header && current.lines.length === 1)
27
+ downloads.push({ path: current.path, location: header[2].trim() });
28
+ else
29
+ other.push([current.path, ...current.lines].join("\n"));
30
+ current = undefined;
31
+ };
32
+ for (const line of (text ?? "").split(/\r?\n/)) {
33
+ if (!line.trim() || line.trim().startsWith("#"))
34
+ continue;
35
+ if (/^\s/.test(line))
36
+ current?.lines.push(line);
37
+ else {
38
+ flush();
39
+ current = { path: line.trim(), lines: [] };
40
+ }
41
+ }
42
+ flush();
43
+ return { downloads, other };
44
+ }
45
+ /**
46
+ * A `_headers` file with a rule per download, merged into `existing`: rules
47
+ * for other paths stay as written, a download rule for the same path is
48
+ * replaced, and download rules are sorted by path.
49
+ */
50
+ export function headersFile(rules, existing) {
51
+ const held = readHeadersFile(existing);
52
+ const byPath = new Map(held.downloads.map((r) => [r.path, r.location]));
53
+ for (const r of rules)
54
+ byPath.set(rulePath(r.path), r.location);
55
+ const downloads = [...byPath.entries()].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)).map(([path, location]) => `${path}\n ${DOWNLOAD_HEADER}: ${location}`);
56
+ return `${[...held.other, ...downloads].join("\n\n")}\n`;
57
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The Terraform module registry protocol (chant#4565): addresses, the writer
3
+ * of the protocol's files, the reader as Terraform and OpenTofu read them,
4
+ * and a handler that serves the files with the download header both CLIs
5
+ * install from. Moved from terragucci's `publish/registry.ts`; products keep
6
+ * their config keys and presets and call this. The module targets that
7
+ * publish a version to a hosted registry (GitLab first) are under ./targets
8
+ * (chant#4603). ./docs reads a module's README, inputs, outputs and
9
+ * examples for its release catalog page (chant#4598). ./source-forms puts
10
+ * module sources and provider addresses in one normal form, and
11
+ * ../used-sources lists the ones a root uses (chant#3924); ./proxies
12
+ * reads them through Artifactory and Nexus proxies (chant#4606).
13
+ */
14
+ export * from "./address.js";
15
+ export * from "./semver.js";
16
+ export * from "./writer.js";
17
+ export * from "./reader.js";
18
+ export * from "./handler.js";
19
+ export * from "./serve.js";
20
+ export * from "./headers-file.js";
21
+ export * from "./mirror.js";
22
+ export * from "./edge/index.js";
23
+ export * from "./targets/index.js";
24
+ export * from "./docs.js";
25
+ export * from "./catalog-read.js";
26
+ export * from "./deprecated.js";
27
+ export * from "./source-forms.js";
28
+ export * from "./proxies.js";
29
+ export { moduleConsumers, isLocalSource, type ModuleConsumer } from "../pin/consumers.js";
30
+ export { usedSources, type UsedSource, type UnreadSource, type UsedSourcesOptions } from "../used-sources.js";
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The Terraform module registry protocol (chant#4565): addresses, the writer
3
+ * of the protocol's files, the reader as Terraform and OpenTofu read them,
4
+ * and a handler that serves the files with the download header both CLIs
5
+ * install from. Moved from terragucci's `publish/registry.ts`; products keep
6
+ * their config keys and presets and call this. The module targets that
7
+ * publish a version to a hosted registry (GitLab first) are under ./targets
8
+ * (chant#4603). ./docs reads a module's README, inputs, outputs and
9
+ * examples for its release catalog page (chant#4598). ./source-forms puts
10
+ * module sources and provider addresses in one normal form, and
11
+ * ../used-sources lists the ones a root uses (chant#3924); ./proxies
12
+ * reads them through Artifactory and Nexus proxies (chant#4606).
13
+ */
14
+ export * from "./address.js";
15
+ export * from "./semver.js";
16
+ export * from "./writer.js";
17
+ export * from "./reader.js";
18
+ export * from "./handler.js";
19
+ export * from "./serve.js";
20
+ export * from "./headers-file.js";
21
+ export * from "./mirror.js";
22
+ export * from "./edge/index.js";
23
+ export * from "./targets/index.js";
24
+ export * from "./docs.js";
25
+ export * from "./catalog-read.js";
26
+ export * from "./deprecated.js";
27
+ export * from "./source-forms.js";
28
+ export * from "./proxies.js";
29
+ export { moduleConsumers, isLocalSource } from "../pin/consumers.js";
30
+ export { usedSources } from "../used-sources.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Paths of the provider network mirror under a registry (chant#4564), with no
3
+ * Node imports, so the edge function can tell a mirror's version file apart.
4
+ */
5
+ /** The mirror's place under the registry's prefix. */
6
+ export declare const PROVIDER_MIRROR_PREFIX = "providers";
7
+ /** True for a mirror's `providers/<host>/<ns>/<type>/<version>.json` path, with or without a prefix in front. */
8
+ export declare const isMirrorVersionPath: (path: string) => boolean;
9
+ //# sourceMappingURL=mirror-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror-paths.d.ts","sourceRoot":"","sources":["../../src/registry/mirror-paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,sDAAsD;AACtD,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD,iHAAiH;AACjH,eAAO,MAAM,mBAAmB,SAAU,MAAM,KAAG,OAAkI,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Paths of the provider network mirror under a registry (chant#4564), with no
3
+ * Node imports, so the edge function can tell a mirror's version file apart.
4
+ */
5
+ /** The mirror's place under the registry's prefix. */
6
+ export const PROVIDER_MIRROR_PREFIX = "providers";
7
+ /** True for a mirror's `providers/<host>/<ns>/<type>/<version>.json` path, with or without a prefix in front. */
8
+ export const isMirrorVersionPath = (path) => new RegExp(`(^|/)${PROVIDER_MIRROR_PREFIX}/[^/]+/[^/]+/[^/]+/(?!index\\.json$)[^/]+\\.json$`).test(path.split("?")[0]);
@@ -0,0 +1,130 @@
1
+ import type { RegistryWriteStore } from "./writer.js";
2
+ export { PROVIDER_MIRROR_PREFIX, isMirrorVersionPath } from "./mirror-paths.js";
3
+ export declare const LOCK_FILE = ".terraform.lock.hcl";
4
+ /** The two hosts a hostless provider source resolves to. */
5
+ export declare const TERRAFORM_REGISTRY = "registry.terraform.io";
6
+ export declare const OPENTOFU_REGISTRY = "registry.opentofu.org";
7
+ /** Every provider in a lock file, by its full address, with its version. */
8
+ export declare function readLock(text: string): Map<string, string>;
9
+ /** The repo's lock files, as `/`-separated paths relative to the repo, sorted. */
10
+ export declare function lockFiles(repo: string): string[];
11
+ /** One provider one lock file pins. */
12
+ export interface LockEntry {
13
+ /** The lock file, relative to the repo. */
14
+ lock: string;
15
+ address: string;
16
+ version: string;
17
+ }
18
+ /** Every provider every lock file pins. */
19
+ export declare function lockEntries(repo: string, files?: string[]): LockEntry[];
20
+ /** Lock files that pin the same providers at the same versions, mirrored once. */
21
+ export interface MirrorGroup {
22
+ /** The lock files, relative to the repo. */
23
+ locks: string[];
24
+ /** The first lock file's text, which `providers mirror` checks downloads against. */
25
+ text: string;
26
+ /** Address to version. */
27
+ providers: Map<string, string>;
28
+ }
29
+ /** The repo's lock files grouped by what they pin; a lock file that pins nothing is left out. */
30
+ export declare function mirrorGroups(repo: string, locks?: string[]): MirrorGroup[];
31
+ /** A file a mirror build writes, relative to its directory. */
32
+ export interface MirrorModuleFile {
33
+ path: string;
34
+ content: string;
35
+ }
36
+ export interface MirrorModuleOptions {
37
+ /** Directory the modules go under. Default `mirror`. */
38
+ dir?: string;
39
+ /** Also require each provider locked on registry.terraform.io or registry.opentofu.org under the other host. Default false. */
40
+ bothHosts?: boolean;
41
+ }
42
+ /** The other default host's address for a provider locked on one of them, or undefined. */
43
+ export declare function otherHostAddress(address: string): string | undefined;
44
+ /**
45
+ * One module per group: `versions.tf` holding each provider at exactly its
46
+ * locked version, and the lock file beside it so `providers mirror` checks the
47
+ * hashes. With `bothHosts`, the other default host's address is required too;
48
+ * the lock file does not name it, so its download is checked by that
49
+ * registry's signature alone.
50
+ */
51
+ export declare function mirrorModules(groups: MirrorGroup[], options?: MirrorModuleOptions): MirrorModuleFile[];
52
+ /** A platform as the binaries name it, `linux_amd64`, from that form or Docker's `linux/amd64`. */
53
+ export declare function binaryPlatform(platform: string): string;
54
+ /** The platform this process runs on, as the binaries name it. */
55
+ export declare function hostPlatform(platform?: string, arch?: string): string;
56
+ /**
57
+ * Whether a mirror directory holds the provider at the version for the
58
+ * platform, in either layout a `filesystem_mirror` reads: packed (what
59
+ * `providers mirror` writes, a zip per platform) or unpacked (a directory per
60
+ * platform).
61
+ */
62
+ export declare function mirrorHas(mirror: string, address: string, version: string, platform: string): boolean;
63
+ /** Runs the binary; a test passes its own. */
64
+ export type MirrorRun = (bin: string, args: string[], cwd: string) => {
65
+ status: number | null;
66
+ output: string;
67
+ };
68
+ export interface BuildMirrorOptions {
69
+ /** The binary that runs `providers mirror`. Default tofu. */
70
+ binary?: string;
71
+ /** Platforms to mirror, `linux_amd64` or `linux/amd64`. Default linux_amd64. */
72
+ platforms?: string[];
73
+ /** Mirror each provider under both default hosts. Default true. */
74
+ bothHosts?: boolean;
75
+ /** The lock files to cover. Default every lock file in the repo. */
76
+ locks?: string[];
77
+ /** Where the modules are written while the binary runs. Default a new temporary directory. */
78
+ workDir?: string;
79
+ run?: MirrorRun;
80
+ }
81
+ export interface BuiltMirror {
82
+ /** The directory the mirror was written to. */
83
+ out: string;
84
+ /** The lock files covered. */
85
+ locks: string[];
86
+ /** Every provider mirrored, as `address version`, sorted. */
87
+ providers: string[];
88
+ platforms: string[];
89
+ }
90
+ export declare class MirrorBuildError extends Error {
91
+ constructor(message: string);
92
+ }
93
+ /**
94
+ * Runs `providers mirror` over every lock file's group into `out`, then
95
+ * rewrites each `index.json` from the version files present, so groups that
96
+ * mirror different versions of one provider all show.
97
+ */
98
+ export declare function buildMirror(repo: string, out: string, options?: BuildMirrorOptions): BuiltMirror;
99
+ /** The store a mirror is uploaded to: a registry's write store, with an optional existence check so archives already there are skipped. */
100
+ export type MirrorUploadStore = Pick<RegistryWriteStore, "put" | "read"> & {
101
+ has?(key: string): Promise<boolean>;
102
+ };
103
+ export interface UploadMirrorOptions {
104
+ /** The registry's prefix in its store; the mirror goes under `<prefix>/providers/`. */
105
+ prefix?: string;
106
+ }
107
+ export interface UploadedMirror {
108
+ /** Keys written. */
109
+ put: string[];
110
+ /** Archive keys left as they were, already in the store. */
111
+ kept: string[];
112
+ }
113
+ /** The key a mirror file goes to. */
114
+ export declare const mirrorKey: (prefix: string | undefined, path: string) => string;
115
+ /**
116
+ * Uploads a built mirror: archives, then each `<version>.json`, then each
117
+ * `index.json` merged with the versions the store's copy already lists, so a
118
+ * reader never sees an index naming a version whose files are not there yet.
119
+ */
120
+ export declare function uploadMirror(store: MirrorUploadStore, dir: string, options?: UploadMirrorOptions): Promise<UploadedMirror>;
121
+ /** The mirror's URL under a registry's base URL, ending in `/`. */
122
+ export declare const mirrorUrl: (registryUrl: string, prefix?: string) => string;
123
+ /**
124
+ * The CLI config block users add: the mirrored providers come only from the
125
+ * mirror, and everything else directly from its registry. `include` keeps
126
+ * the mirror from being asked for a provider it lacks, and `exclude` keeps a
127
+ * mirrored provider from going direct.
128
+ */
129
+ export declare function mirrorCliConfig(url: string, addresses: string[]): string;
130
+ //# sourceMappingURL=mirror.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror.d.ts","sourceRoot":"","sources":["../../src/registry/mirror.ts"],"names":[],"mappings":"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"}