@geekmidas/cli 10.0.0-alpha.124 → 10.0.0-alpha.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/dist/{EndpointGenerator-B2MUa4M2.cjs → EndpointGenerator-BGxf9jWE.cjs} +8 -4
  2. package/dist/{EndpointGenerator-B2MUa4M2.cjs.map → EndpointGenerator-BGxf9jWE.cjs.map} +1 -1
  3. package/dist/{EndpointGenerator-Z_BUTocT.mjs → EndpointGenerator-errMeldx.mjs} +8 -4
  4. package/dist/{EndpointGenerator-Z_BUTocT.mjs.map → EndpointGenerator-errMeldx.mjs.map} +1 -1
  5. package/dist/{GoDaddyProvider-55x4o-4z.mjs → GoDaddyProvider-CvRVmN4W.mjs} +2 -2
  6. package/dist/{GoDaddyProvider-55x4o-4z.mjs.map → GoDaddyProvider-CvRVmN4W.mjs.map} +1 -1
  7. package/dist/{GoDaddyProvider-0z5RAN1k.cjs → GoDaddyProvider-DFfpzCOP.cjs} +2 -2
  8. package/dist/{GoDaddyProvider-0z5RAN1k.cjs.map → GoDaddyProvider-DFfpzCOP.cjs.map} +1 -1
  9. package/dist/{LegacyStateStore-DRpB-yC5.cjs → LegacyStateStore-BFrCHrFQ.cjs} +3 -3
  10. package/dist/{LegacyStateStore-DRpB-yC5.cjs.map → LegacyStateStore-BFrCHrFQ.cjs.map} +1 -1
  11. package/dist/{LegacyStateStore-C-vumKSN.mjs → LegacyStateStore-CgfENrXF.mjs} +3 -3
  12. package/dist/{LegacyStateStore-C-vumKSN.mjs.map → LegacyStateStore-CgfENrXF.mjs.map} +1 -1
  13. package/dist/{LocalStateStore-C3ummuDT.cjs → LocalStateStore-BU5z_IOE.cjs} +2 -2
  14. package/dist/{LocalStateStore-C3ummuDT.cjs.map → LocalStateStore-BU5z_IOE.cjs.map} +1 -1
  15. package/dist/{LocalStateStore-CtOjpV1w.mjs → LocalStateStore-DxoNpiBg.mjs} +2 -2
  16. package/dist/{LocalStateStore-CtOjpV1w.mjs.map → LocalStateStore-DxoNpiBg.mjs.map} +1 -1
  17. package/dist/{OpenApiTsGenerator-MtnMQL_g.mjs → OpenApiTsGenerator-W_HRXH1X.mjs} +2 -2
  18. package/dist/{OpenApiTsGenerator-MtnMQL_g.mjs.map → OpenApiTsGenerator-W_HRXH1X.mjs.map} +1 -1
  19. package/dist/{OpenApiTsGenerator-t3_E98Fi.cjs → OpenApiTsGenerator-cQgtxWQo.cjs} +2 -2
  20. package/dist/{OpenApiTsGenerator-t3_E98Fi.cjs.map → OpenApiTsGenerator-cQgtxWQo.cjs.map} +1 -1
  21. package/dist/{S3StateStore-BC4Jm3Tw.mjs → S3StateStore-CGMSDilh.mjs} +2 -2
  22. package/dist/{S3StateStore-BC4Jm3Tw.mjs.map → S3StateStore-CGMSDilh.mjs.map} +1 -1
  23. package/dist/{S3StateStore-BeArp0aF.cjs → S3StateStore-DiekMLpn.cjs} +2 -2
  24. package/dist/{S3StateStore-BeArp0aF.cjs.map → S3StateStore-DiekMLpn.cjs.map} +1 -1
  25. package/dist/{SSMStateStore-DcstR6cW.cjs → SSMStateStore-BDCOFdKq.cjs} +2 -2
  26. package/dist/{SSMStateStore-DcstR6cW.cjs.map → SSMStateStore-BDCOFdKq.cjs.map} +1 -1
  27. package/dist/{SSMStateStore-Crl76aYZ.mjs → SSMStateStore-Cq2H9MlF.mjs} +2 -2
  28. package/dist/{SSMStateStore-Crl76aYZ.mjs.map → SSMStateStore-Cq2H9MlF.mjs.map} +1 -1
  29. package/dist/{SubscriberGenerator-COAVPgM-.mjs → SubscriberGenerator-BALddfuW.mjs} +4 -62
  30. package/dist/SubscriberGenerator-BALddfuW.mjs.map +1 -0
  31. package/dist/{SubscriberGenerator-C3QTae-R.cjs → SubscriberGenerator-LgyTxZ8r.cjs} +3 -91
  32. package/dist/SubscriberGenerator-LgyTxZ8r.cjs.map +1 -0
  33. package/dist/{add-BFjb6mMq.cjs → add-BsiBYkAW.cjs} +6 -6
  34. package/dist/{add-BFjb6mMq.cjs.map → add-BsiBYkAW.cjs.map} +1 -1
  35. package/dist/{add-CIjmgzkb.mjs → add-CamA9Uqv.mjs} +6 -6
  36. package/dist/{add-CIjmgzkb.mjs.map → add-CamA9Uqv.mjs.map} +1 -1
  37. package/dist/{bundler-D6KFNpQk.mjs → bundler-2V2PR_E-.mjs} +5 -5
  38. package/dist/{bundler-D6KFNpQk.mjs.map → bundler-2V2PR_E-.mjs.map} +1 -1
  39. package/dist/{bundler-CiUoIsku.cjs → bundler-CijtdIZ2.cjs} +5 -5
  40. package/dist/{bundler-CiUoIsku.cjs.map → bundler-CijtdIZ2.cjs.map} +1 -1
  41. package/dist/{cli-r4eUr98C.cjs → cli-7gc1QG8X.cjs} +3 -3
  42. package/dist/{cli-r4eUr98C.cjs.map → cli-7gc1QG8X.cjs.map} +1 -1
  43. package/dist/{cli-DNtSTtMc.mjs → cli-PiyYqHGx.mjs} +3 -3
  44. package/dist/{cli-DNtSTtMc.mjs.map → cli-PiyYqHGx.mjs.map} +1 -1
  45. package/dist/{compose-BfXXWJSp.cjs → compose-8e2xJ61E.cjs} +236 -39
  46. package/dist/compose-8e2xJ61E.cjs.map +1 -0
  47. package/dist/{compose-DJvvmF3X.mjs → compose-CvHIjMDd.mjs} +235 -38
  48. package/dist/compose-CvHIjMDd.mjs.map +1 -0
  49. package/dist/{config-IgK6YaGp.d.cts → config-CdytFgSR.d.cts} +3 -3
  50. package/dist/{config-IgK6YaGp.d.cts.map → config-CdytFgSR.d.cts.map} +1 -1
  51. package/dist/{config-kE-p5hxq.d.mts → config-_y1FGBWR.d.mts} +3 -3
  52. package/dist/{config-kE-p5hxq.d.mts.map → config-_y1FGBWR.d.mts.map} +1 -1
  53. package/dist/config.cjs +2 -2
  54. package/dist/config.d.cts +3 -3
  55. package/dist/config.d.mts +3 -3
  56. package/dist/config.mjs +2 -2
  57. package/dist/{credentialSchemas-AhIBuQxQ.cjs → credentialSchemas-DFxvGEwa.cjs} +2 -2
  58. package/dist/{credentialSchemas-AhIBuQxQ.cjs.map → credentialSchemas-DFxvGEwa.cjs.map} +1 -1
  59. package/dist/{credentialSchemas-DLKbxYBy.mjs → credentialSchemas-DaMpt-Dx.mjs} +2 -2
  60. package/dist/{credentialSchemas-DLKbxYBy.mjs.map → credentialSchemas-DaMpt-Dx.mjs.map} +1 -1
  61. package/dist/{databases-BPOgTn1u.mjs → databases-6GD0tI2F.mjs} +65 -3
  62. package/dist/databases-6GD0tI2F.mjs.map +1 -0
  63. package/dist/{databases-fOaoBInm.cjs → databases-CuVGf7-M.cjs} +75 -1
  64. package/dist/databases-CuVGf7-M.cjs.map +1 -0
  65. package/dist/deploy/public.cjs +8 -8
  66. package/dist/deploy/public.d.cts +3 -3
  67. package/dist/deploy/public.d.cts.map +1 -1
  68. package/dist/deploy/public.d.mts +3 -3
  69. package/dist/deploy/public.d.mts.map +1 -1
  70. package/dist/deploy/public.mjs +8 -8
  71. package/dist/{deploy-CiRYwFmr.mjs → deploy-CIPwTJ47.mjs} +797 -25
  72. package/dist/deploy-CIPwTJ47.mjs.map +1 -0
  73. package/dist/{deploy-BbI1UMh3.cjs → deploy-wSlIRPn5.cjs} +796 -24
  74. package/dist/deploy-wSlIRPn5.cjs.map +1 -0
  75. package/dist/{discover-BvJOVsYG.mjs → discover-CzGM5P3p.mjs} +71 -1
  76. package/dist/discover-CzGM5P3p.mjs.map +1 -0
  77. package/dist/{discover-ojkcbxHw.cjs → discover-DL6h-J97.cjs} +71 -1
  78. package/dist/discover-DL6h-J97.cjs.map +1 -0
  79. package/dist/{dokploy-C0aQrCgs.cjs → dokploy-BKbUrz05.cjs} +2 -2
  80. package/dist/{dokploy-C0aQrCgs.cjs.map → dokploy-BKbUrz05.cjs.map} +1 -1
  81. package/dist/{dokploy-MM7c3IE0.mjs → dokploy-BZf1AHd0.mjs} +2 -2
  82. package/dist/{dokploy-MM7c3IE0.mjs.map → dokploy-BZf1AHd0.mjs.map} +1 -1
  83. package/dist/{drivers-CQ32PB5w.cjs → drivers-C47nm-wB.cjs} +91 -4
  84. package/dist/drivers-C47nm-wB.cjs.map +1 -0
  85. package/dist/{drivers-Chb5Akov.mjs → drivers-CDjpjakg.mjs} +60 -3
  86. package/dist/drivers-CDjpjakg.mjs.map +1 -0
  87. package/dist/{eas-1Ee6kql0.mjs → eas-CxX2RCE_.mjs} +2 -2
  88. package/dist/{eas-1Ee6kql0.mjs.map → eas-CxX2RCE_.mjs.map} +1 -1
  89. package/dist/{eas-CJoys9yh.cjs → eas-DzDMGzfc.cjs} +2 -2
  90. package/dist/{eas-CJoys9yh.cjs.map → eas-DzDMGzfc.cjs.map} +1 -1
  91. package/dist/{emit-qvHxMV9b.cjs → emit-CYloptRS.cjs} +18 -1
  92. package/dist/emit-CYloptRS.cjs.map +1 -0
  93. package/dist/{emit-CNpuV_6Q.mjs → emit-CiJGdy_f.mjs} +18 -1
  94. package/dist/emit-CiJGdy_f.mjs.map +1 -0
  95. package/dist/{encryption-B8Bk1Mvu.mjs → encryption-BFSrt89F.mjs} +3 -3
  96. package/dist/{encryption-B8Bk1Mvu.mjs.map → encryption-BFSrt89F.mjs.map} +1 -1
  97. package/dist/{encryption-Bo9VlRnl.cjs → encryption-RNcBnG4Z.cjs} +3 -3
  98. package/dist/{encryption-Bo9VlRnl.cjs.map → encryption-RNcBnG4Z.cjs.map} +1 -1
  99. package/dist/{engine-esxTxcIx.cjs → engine-Dqe9KQCm.cjs} +142 -15
  100. package/dist/engine-Dqe9KQCm.cjs.map +1 -0
  101. package/dist/{engine-BuinpJfS.mjs → engine-_0pjyCd_.mjs} +142 -15
  102. package/dist/engine-_0pjyCd_.mjs.map +1 -0
  103. package/dist/{github-BEA4K3_X.cjs → github-Csev5EFf.cjs} +41 -6
  104. package/dist/github-Csev5EFf.cjs.map +1 -0
  105. package/dist/{github-BUlKJfOV.mjs → github-Dck0nLW9.mjs} +41 -6
  106. package/dist/github-Dck0nLW9.mjs.map +1 -0
  107. package/dist/{googlePlay-CiqAS2ma.cjs → googlePlay-DBtDAGBk.cjs} +3 -3
  108. package/dist/{googlePlay-CiqAS2ma.cjs.map → googlePlay-DBtDAGBk.cjs.map} +1 -1
  109. package/dist/{googlePlay-CK05QiTq.mjs → googlePlay-DTuvDHi5.mjs} +3 -3
  110. package/dist/{googlePlay-CK05QiTq.mjs.map → googlePlay-DTuvDHi5.mjs.map} +1 -1
  111. package/dist/{index-DhUf0B0m.d.mts → index-DrkV7N5w.d.mts} +2 -2
  112. package/dist/{index-4CO0HD27.d.cts.map → index-DrkV7N5w.d.mts.map} +1 -1
  113. package/dist/{index-4CO0HD27.d.cts → index-yaXZ9m-J.d.cts} +2 -2
  114. package/dist/{index-DhUf0B0m.d.mts.map → index-yaXZ9m-J.d.cts.map} +1 -1
  115. package/dist/index.cjs +150 -67
  116. package/dist/index.cjs.map +1 -1
  117. package/dist/index.mjs +149 -66
  118. package/dist/index.mjs.map +1 -1
  119. package/dist/{migrate-C-hmbjpG.cjs → migrate-3ZEoqx5q.cjs} +3 -3
  120. package/dist/{migrate-C-hmbjpG.cjs.map → migrate-3ZEoqx5q.cjs.map} +1 -1
  121. package/dist/{migrate-BzCHT9qs.mjs → migrate-BABIuzQj.mjs} +3 -3
  122. package/dist/{migrate-BzCHT9qs.mjs.map → migrate-BABIuzQj.mjs.map} +1 -1
  123. package/dist/{migrate-CnbvrVag.mjs → migrate-DZeNpuX2.mjs} +8 -6
  124. package/dist/migrate-DZeNpuX2.mjs.map +1 -0
  125. package/dist/{migrate-DeQJBexh.cjs → migrate-pGiUqvBi.cjs} +8 -6
  126. package/dist/migrate-pGiUqvBi.cjs.map +1 -0
  127. package/dist/openapi.cjs +3 -3
  128. package/dist/openapi.d.cts +1 -1
  129. package/dist/openapi.d.mts +1 -1
  130. package/dist/openapi.mjs +3 -3
  131. package/dist/{publish-BISBrrqR.mjs → publish-BsnDeOVL.mjs} +2 -2
  132. package/dist/{publish-BISBrrqR.mjs.map → publish-BsnDeOVL.mjs.map} +1 -1
  133. package/dist/{publish-DtSIB-hZ.cjs → publish-CS6xDvGT.cjs} +2 -2
  134. package/dist/{publish-DtSIB-hZ.cjs.map → publish-CS6xDvGT.cjs.map} +1 -1
  135. package/dist/{ready-IVGu-q18.cjs → ready-CxPJm0Hc.cjs} +6 -6
  136. package/dist/{ready-IVGu-q18.cjs.map → ready-CxPJm0Hc.cjs.map} +1 -1
  137. package/dist/{ready-DqsyadOs.mjs → ready-DrvaAwKv.mjs} +6 -6
  138. package/dist/{ready-DqsyadOs.mjs.map → ready-DrvaAwKv.mjs.map} +1 -1
  139. package/dist/reconcile/public.cjs +2 -2
  140. package/dist/reconcile/public.d.cts +1 -1
  141. package/dist/reconcile/public.d.cts.map +1 -1
  142. package/dist/reconcile/public.d.mts +1 -1
  143. package/dist/reconcile/public.d.mts.map +1 -1
  144. package/dist/reconcile/public.mjs +2 -2
  145. package/dist/{resolve-BT7fkPN5.mjs → resolve-fCGJmM-R.mjs} +3 -3
  146. package/dist/{resolve-BT7fkPN5.mjs.map → resolve-fCGJmM-R.mjs.map} +1 -1
  147. package/dist/{resolve-C7GKQcE4.cjs → resolve-zqCMFio0.cjs} +3 -3
  148. package/dist/{resolve-C7GKQcE4.cjs.map → resolve-zqCMFio0.cjs.map} +1 -1
  149. package/dist/{rollback-DbP0KuDw.mjs → rollback-BkhVrtAf.mjs} +5 -5
  150. package/dist/{rollback-DbP0KuDw.mjs.map → rollback-BkhVrtAf.mjs.map} +1 -1
  151. package/dist/{rollback-BEiB-Pje.cjs → rollback-qc79mj6L.cjs} +5 -5
  152. package/dist/{rollback-BEiB-Pje.cjs.map → rollback-qc79mj6L.cjs.map} +1 -1
  153. package/dist/{runtime-BFJQNqwd.d.mts → runtime-DCkfI2E7.d.mts} +2 -2
  154. package/dist/{runtime-BFJQNqwd.d.mts.map → runtime-DCkfI2E7.d.mts.map} +1 -1
  155. package/dist/{runtime-BJO-FFef.d.cts → runtime-Ie4znWIB.d.cts} +2 -2
  156. package/dist/{runtime-BJO-FFef.d.cts.map → runtime-Ie4znWIB.d.cts.map} +1 -1
  157. package/dist/{s3-B4FTQQkV.mjs → s3-BZzSnker.mjs} +2 -2
  158. package/dist/{s3-B4FTQQkV.mjs.map → s3-BZzSnker.mjs.map} +1 -1
  159. package/dist/{s3-DwKLXwUT.cjs → s3-pqgmCTOq.cjs} +2 -2
  160. package/dist/{s3-DwKLXwUT.cjs.map → s3-pqgmCTOq.cjs.map} +1 -1
  161. package/dist/sandbox/credentials-worker.cjs +2 -2
  162. package/dist/sandbox/credentials-worker.mjs +2 -2
  163. package/dist/sandbox/discover-worker.cjs +1 -1
  164. package/dist/sandbox/discover-worker.mjs +1 -1
  165. package/dist/sandbox/migrate-worker.cjs +5 -4
  166. package/dist/sandbox/migrate-worker.cjs.map +1 -1
  167. package/dist/sandbox/migrate-worker.mjs +5 -4
  168. package/dist/sandbox/migrate-worker.mjs.map +1 -1
  169. package/dist/{seeds-DOfxmDRO.cjs → seeds-3awh33Wz.cjs} +607 -45
  170. package/dist/seeds-3awh33Wz.cjs.map +1 -0
  171. package/dist/{seeds-rG-Evfz9.mjs → seeds-Cfejy8wj.mjs} +517 -39
  172. package/dist/seeds-Cfejy8wj.mjs.map +1 -0
  173. package/dist/{serverSetup-CWWVcU6Y.cjs → serverSetup-BFQuwUeL.cjs} +6 -6
  174. package/dist/{serverSetup-CWWVcU6Y.cjs.map → serverSetup-BFQuwUeL.cjs.map} +1 -1
  175. package/dist/{serverSetup-xGw1fxuZ.mjs → serverSetup-C8ZbHTm_.mjs} +6 -6
  176. package/dist/{serverSetup-xGw1fxuZ.mjs.map → serverSetup-C8ZbHTm_.mjs.map} +1 -1
  177. package/dist/{sniffer-DVPgfyHr.mjs → sniffer-CCkdzjiU.mjs} +8 -8
  178. package/dist/{sniffer-DVPgfyHr.mjs.map → sniffer-CCkdzjiU.mjs.map} +1 -1
  179. package/dist/{sniffer-C7O9Pna_.cjs → sniffer-Cq1nhxIB.cjs} +8 -8
  180. package/dist/{sniffer-C7O9Pna_.cjs.map → sniffer-Cq1nhxIB.cjs.map} +1 -1
  181. package/dist/{snsSubscriptions-CSkteK2J.cjs → snsSubscriptions-DYyYP0Xf.cjs} +15 -3
  182. package/dist/snsSubscriptions-DYyYP0Xf.cjs.map +1 -0
  183. package/dist/{snsSubscriptions-CvBIGGp0.mjs → snsSubscriptions-R_AKBZYK.mjs} +4 -4
  184. package/dist/snsSubscriptions-R_AKBZYK.mjs.map +1 -0
  185. package/dist/{stage-fRfFtLwj.cjs → stage-BkgbVJ9Z.cjs} +6 -6
  186. package/dist/{stage-fRfFtLwj.cjs.map → stage-BkgbVJ9Z.cjs.map} +1 -1
  187. package/dist/{stage-2EKpzPQ1.mjs → stage-DCaxqm-G.mjs} +6 -6
  188. package/dist/{stage-2EKpzPQ1.mjs.map → stage-DCaxqm-G.mjs.map} +1 -1
  189. package/dist/{stages-B7mCWI_R.cjs → stages-3yUZaZeA.cjs} +2 -2
  190. package/dist/{stages-B7mCWI_R.cjs.map → stages-3yUZaZeA.cjs.map} +1 -1
  191. package/dist/{stages-DSltTW2d.mjs → stages-DTTv0NZW.mjs} +2 -2
  192. package/dist/{stages-DSltTW2d.mjs.map → stages-DTTv0NZW.mjs.map} +1 -1
  193. package/dist/target/public.cjs +1 -1
  194. package/dist/target/public.d.cts +2 -2
  195. package/dist/target/public.d.mts +2 -2
  196. package/dist/target/public.mjs +1 -1
  197. package/dist/{terminal-D1aeTkgv.cjs → terminal-PKhPAajN.cjs} +2 -2
  198. package/dist/{terminal-D1aeTkgv.cjs.map → terminal-PKhPAajN.cjs.map} +1 -1
  199. package/dist/{terminal-BAVrDhhN.mjs → terminal-bqY33lpN.mjs} +2 -2
  200. package/dist/{terminal-BAVrDhhN.mjs.map → terminal-bqY33lpN.mjs.map} +1 -1
  201. package/dist/{types-CFU2uvrz.d.cts → types-Bmjs4jZV.d.mts} +8 -2
  202. package/dist/{types-D3BeGucy.d.mts.map → types-Bmjs4jZV.d.mts.map} +1 -1
  203. package/dist/{types-D3BeGucy.d.mts → types-D0IsQxES.d.cts} +9 -1
  204. package/dist/{types-CFU2uvrz.d.cts.map → types-D0IsQxES.d.cts.map} +1 -1
  205. package/dist/vitest.cjs +1 -1
  206. package/dist/vitest.mjs +1 -1
  207. package/dist/workspace/index.cjs +1 -1
  208. package/dist/workspace/index.d.cts +2 -2
  209. package/dist/workspace/index.d.mts +2 -2
  210. package/dist/workspace/index.mjs +1 -1
  211. package/dist/{workspace-DUnnVjqC.mjs → workspace-DBHF9Gba.mjs} +5 -3
  212. package/dist/workspace-DBHF9Gba.mjs.map +1 -0
  213. package/dist/{workspace-C82GLPnf.cjs → workspace-Du4Afb03.cjs} +5 -3
  214. package/dist/workspace-Du4Afb03.cjs.map +1 -0
  215. package/package.json +17 -15
  216. package/dist/SubscriberGenerator-C3QTae-R.cjs.map +0 -1
  217. package/dist/SubscriberGenerator-COAVPgM-.mjs.map +0 -1
  218. package/dist/compose-BfXXWJSp.cjs.map +0 -1
  219. package/dist/compose-DJvvmF3X.mjs.map +0 -1
  220. package/dist/databases-BPOgTn1u.mjs.map +0 -1
  221. package/dist/databases-fOaoBInm.cjs.map +0 -1
  222. package/dist/deploy-BbI1UMh3.cjs.map +0 -1
  223. package/dist/deploy-CiRYwFmr.mjs.map +0 -1
  224. package/dist/discover-BvJOVsYG.mjs.map +0 -1
  225. package/dist/discover-ojkcbxHw.cjs.map +0 -1
  226. package/dist/drivers-CQ32PB5w.cjs.map +0 -1
  227. package/dist/drivers-Chb5Akov.mjs.map +0 -1
  228. package/dist/emit-CNpuV_6Q.mjs.map +0 -1
  229. package/dist/emit-qvHxMV9b.cjs.map +0 -1
  230. package/dist/engine-BuinpJfS.mjs.map +0 -1
  231. package/dist/engine-esxTxcIx.cjs.map +0 -1
  232. package/dist/github-BEA4K3_X.cjs.map +0 -1
  233. package/dist/github-BUlKJfOV.mjs.map +0 -1
  234. package/dist/migrate-CnbvrVag.mjs.map +0 -1
  235. package/dist/migrate-DeQJBexh.cjs.map +0 -1
  236. package/dist/seeds-DOfxmDRO.cjs.map +0 -1
  237. package/dist/seeds-rG-Evfz9.mjs.map +0 -1
  238. package/dist/snsSubscriptions-CSkteK2J.cjs.map +0 -1
  239. package/dist/snsSubscriptions-CvBIGGp0.mjs.map +0 -1
  240. package/dist/workspace-C82GLPnf.cjs.map +0 -1
  241. package/dist/workspace-DUnnVjqC.mjs.map +0 -1
@@ -1,23 +1,23 @@
1
1
  import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
2
2
  import { r as storedCredentials, x as gkmHome } from "./credentials-DpfnUvIR.mjs";
3
- import { $ as IamUserNotOwned, G as checkS3Config, J as BucketNameUnavailable, K as AccessKeyLimit, L as resolveStageTelemetry, N as assertDeployedStage, Q as BucketRegionUnknown, U as stageProvider, W as S3_PROVISIONING, X as BucketProbeFailed, Y as BucketOwnedByAnotherProject, Z as BucketRegionMismatch, et as ProvisionedBucketUnreachable, ht as isReservedStageKey, nt as RotationInProgress, q as BucketKeySetElsewhere, rt as S3RegionRequired, tt as RecordedBucketUnreachable, u as getAppBuildOrder } from "./workspace-DUnnVjqC.mjs";
4
- import { E as BACKUPS_URL_KEY, I as stageBackups, L as deploysWithCompose, M as backupExpiries, P as backupsPrefix, T as BACKUPS_SERVICE, _ as awsClientConfig, a as subscriptionKey, b as assertSitePasswordTarget, h as stageDnsDomains, l as dnsCredentials, o as subscriptionResource, v as awsEndpoint, y as awsProvisioningCredentials } from "./snsSubscriptions-CvBIGGp0.mjs";
3
+ import { $ as IamUserNotOwned, G as checkS3Config, J as BucketNameUnavailable, K as AccessKeyLimit, L as resolveStageTelemetry, N as assertDeployedStage, Q as BucketRegionUnknown, U as stageProvider, W as S3_PROVISIONING, X as BucketProbeFailed, Y as BucketOwnedByAnotherProject, Z as BucketRegionMismatch, et as ProvisionedBucketUnreachable, ht as isReservedStageKey, nt as RotationInProgress, q as BucketKeySetElsewhere, rt as S3RegionRequired, tt as RecordedBucketUnreachable, u as getAppBuildOrder } from "./workspace-DBHF9Gba.mjs";
4
+ import { D as BACKUPS_SERVICE, I as backupsPrefix, O as BACKUPS_URL_KEY, P as backupExpiries, R as stageBackups, S as assertSitePasswordTarget, _ as stageDnsDomains, a as subscriptionKey, b as awsEndpoint, d as recordTtl, l as dnsCredentials, m as settleStackDns, o as subscriptionResource, x as awsProvisioningCredentials, y as awsClientConfig, z as deploysWithCompose } from "./snsSubscriptions-R_AKBZYK.mjs";
5
5
  import { o as builtinTarget } from "./define-6poNqm5O.mjs";
6
- import { Bn as usesTelemetry, Bt as initStageSecrets, Lt as secretsStoreFor, N as stageProviderNotes, P as PROVIDER_KINDS, X as DevServicesNeedServerTarget, Z as ExternalServicesNotConfigured, ar as isMainFrontendApp, d as DeployJournal, et as devServicesUsed, fn as mergeLifecycle, ft as constructGlobs, ir as NoDomainForStage, it as stageServiceDeclarations, j as assertStageProvidersEnabled, nt as reportDevServices, or as resolveHost, ot as appEnvKeys, tt as externalServices, v as createComposeState, y as createEmptyState } from "./seeds-rG-Evfz9.mjs";
6
+ import { $ as ORIGIN_VERIFY_HEADER, En as mergeLifecycle, N as stageProviderNotes, P as PROVIDER_KINDS, Qt as initStageSecrets, Yt as secretsStoreFor, _t as appEnvKeys, br as resolveHost, ct as ExternalServicesNotConfigured, d as DeployJournal, dt as devServicesUsed, er as usesTelemetry, f as extractSubdomain, ft as externalServices, ht as stageServiceDeclarations, j as assertStageProvidersEnabled, m as normalizeDnsConfig, nt as originSecretKey, p as findRootDomain, pt as reportDevServices, rt as processorOriginHost, st as DevServicesNeedServerTarget, tt as newOriginSecret, v as createComposeState, vr as NoDomainForStage, wt as constructGlobs, y as createEmptyState, yr as isMainFrontendApp } from "./seeds-Cfejy8wj.mjs";
7
7
  import { n as derivedApps, t as appKey } from "./derive-B4vDpzgP.mjs";
8
- import { s as subscriberRoute } from "./SubscriberGenerator-COAVPgM-.mjs";
9
8
  import { n as deployIdentity, t as applicationName } from "./identity-CBXr4wNi.mjs";
10
- import { i as discover, m as eventsEdge, p as withOutput } from "./discover-BvJOVsYG.mjs";
9
+ import { i as discover, m as eventsEdge, p as withOutput } from "./discover-CzGM5P3p.mjs";
11
10
  import { c as withSandbox } from "./sandbox-CbVB7uOD.mjs";
12
11
  import { findWorkspaceRoot, loadWorkspaceConfig } from "./config.mjs";
13
- import { a as parseTargetOptions, o as resolveTarget } from "./resolve-BT7fkPN5.mjs";
12
+ import { s as subscriberRoute } from "./SubscriberGenerator-BALddfuW.mjs";
13
+ import { a as parseTargetOptions, o as resolveTarget } from "./resolve-fCGJmM-R.mjs";
14
14
  import { t as LocalSandbox } from "./local-B7Zv1NoA.mjs";
15
- import { E as eventError, S as createStateStore, v as assertStateOutlivesRun, y as assertStateRoom } from "./sniffer-DVPgfyHr.mjs";
15
+ import { E as eventError, S as createStateStore, v as assertStateOutlivesRun, y as assertStateRoom } from "./sniffer-CCkdzjiU.mjs";
16
16
  import { a as findProjectBucket, i as ensureProjectBucket, o as projectBucketName, r as callerAccountId, s as reconcileProjectBucketLifecycle } from "./projectBucket-C_DN4WzF.mjs";
17
- import { n as assertStageCredentials } from "./credentialSchemas-DLKbxYBy.mjs";
17
+ import { n as assertStageCredentials } from "./credentialSchemas-DaMpt-Dx.mjs";
18
18
  import { resolve } from "node:path";
19
19
  import { randomInt } from "node:crypto";
20
- import { dependentsOf, kebabCase, provideKey, providedKeyFor } from "@geekmidas/manifest";
20
+ import { bucketExpiry, dependentsOf, kebabCase, provideKey, providedKeyFor } from "@geekmidas/manifest";
21
21
  import * as s3Url from "@geekmidas/storage/s3-url";
22
22
  //#region src/target/secrets.ts
23
23
  /**
@@ -219,10 +219,13 @@ function openResource(bucket, pattern) {
219
219
  }
220
220
  /**
221
221
  * The bucket's own policy: every request refused unless it came over TLS,
222
- * and — only when a file server opens paths on it — anonymous `s3:GetObject`
223
- * on exactly those prefixes.
222
+ * and — only when a file server opens paths on it — `s3:GetObject` on
223
+ * exactly those prefixes: to anyone, or, when a CDN serves them, to
224
+ * CloudFront alone, for exactly the stage's distributions. Behind a CDN the
225
+ * bucket is never public: a key outside the open prefixes is refused to
226
+ * CloudFront too, so the edge answers it 403.
224
227
  */
225
- function bucketPolicy(bucket, open = []) {
228
+ function bucketPolicy(bucket, open = [], options = {}) {
226
229
  const statements = [{
227
230
  Sid: "GkmDenyInsecureTransport",
228
231
  Effect: "Deny",
@@ -231,12 +234,21 @@ function bucketPolicy(bucket, open = []) {
231
234
  Resource: [bucketArn(bucket), `${bucketArn(bucket)}/*`],
232
235
  Condition: { Bool: { "aws:SecureTransport": "false" } }
233
236
  }];
234
- if (open.length > 0) statements.push({
237
+ const resources = [...new Set(open.map((p) => openResource(bucket, p)))].sort();
238
+ if (open.length > 0 && options.cdn) statements.push({
239
+ Sid: "GkmCdnRead",
240
+ Effect: "Allow",
241
+ Principal: { Service: "cloudfront.amazonaws.com" },
242
+ Action: "s3:GetObject",
243
+ Resource: resources,
244
+ Condition: { StringEquals: { "AWS:SourceArn": [...new Set(options.cdn.distributionArns)].sort() } }
245
+ });
246
+ else if (open.length > 0) statements.push({
235
247
  Sid: "GkmOpenPaths",
236
248
  Effect: "Allow",
237
249
  Principal: "*",
238
250
  Action: "s3:GetObject",
239
- Resource: [...new Set(open.map((p) => openResource(bucket, p)))].sort()
251
+ Resource: resources
240
252
  });
241
253
  return {
242
254
  Version: "2012-10-17",
@@ -285,7 +297,7 @@ function canonical(value, key) {
285
297
  }
286
298
  if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((k) => {
287
299
  const v = value[k];
288
- return [k, canonical(k === "Action" || k === "Resource" || k === "AWS" ? Array.isArray(v) ? v : [v] : v, k)];
300
+ return [k, canonical(k === "Action" || k === "Resource" || k === "AWS" || k === "AWS:SourceArn" ? Array.isArray(v) ? v : [v] : v, k)];
289
301
  }));
290
302
  return value;
291
303
  }
@@ -331,7 +343,7 @@ function identityTags(ctx, id) {
331
343
  ];
332
344
  }
333
345
  /** A read whose "there is none" answer is one of `missing`. */
334
- async function readOr$2(read, missing) {
346
+ async function readOr$3(read, missing) {
335
347
  try {
336
348
  return await read();
337
349
  } catch (error) {
@@ -361,7 +373,7 @@ async function ensureIamUser(ctx, clients, input) {
361
373
  key: `iam-user:${id}`,
362
374
  type: "iam-user"
363
375
  };
364
- const found = await readOr$2(() => iam.send(new IAM.GetUserCommand({ UserName: user })), ["NoSuchEntity", "NoSuchEntityException"]);
376
+ const found = await readOr$3(() => iam.send(new IAM.GetUserCommand({ UserName: user })), ["NoSuchEntity", "NoSuchEntityException"]);
365
377
  if (found?.User) {
366
378
  const tags = await iam.send(new IAM.ListUserTagsCommand({ UserName: user }));
367
379
  const tag = (key) => tags.Tags?.find((t) => t.Key === key)?.Value;
@@ -381,7 +393,7 @@ async function ensureIamUser(ctx, clients, input) {
381
393
  await ctx.state.ready(entry, user);
382
394
  });
383
395
  const exists = Boolean(found?.User) || !ctx.dryRun;
384
- const current = exists ? await readOr$2(() => iam.send(new IAM.GetUserPolicyCommand({
396
+ const current = exists ? await readOr$3(() => iam.send(new IAM.GetUserPolicyCommand({
385
397
  UserName: user,
386
398
  PolicyName: input.policyName
387
399
  })), ["NoSuchEntity", "NoSuchEntityException"]) : void 0;
@@ -795,6 +807,738 @@ async function verifyStageBackups(input) {
795
807
  }
796
808
  }
797
809
  //#endregion
810
+ //#region src/providers/dnsWriter.ts
811
+ /**
812
+ * The DNS records a provider asks for — a certificate's validation record, a
813
+ * CDN's name — written through the stage's own DNS providers.
814
+ *
815
+ * The same machinery the deploy's DNS step uses for the stack's hosts
816
+ * (`settleStackDns`), handed a plan of CNAMEs instead of the server's
817
+ * addresses: a record holding its value is left alone, one with another value
818
+ * is replaced and printed, and what is written is read back. A host under no
819
+ * domain in `dns`, or under a `manual` one, is printed for the person to
820
+ * create and reported back, so the provider can say what it is waiting on.
821
+ */
822
+ async function writeProviderDns(records, options) {
823
+ const { log } = options;
824
+ const dns = options.workspace.dns ? normalizeDnsConfig(options.workspace.dns) : {};
825
+ const manual = [];
826
+ const domains = /* @__PURE__ */ new Map();
827
+ for (const record of records) {
828
+ const host = record.host.toLowerCase().replace(/\.$/, "");
829
+ const value = record.value.replace(/\.$/, "");
830
+ const domain = findRootDomain(host, dns);
831
+ if (!domain) {
832
+ log(` create at its DNS host: ${host} CNAME ${value}`);
833
+ manual.push(host);
834
+ continue;
835
+ }
836
+ const config = dns[domain];
837
+ const plan = domains.get(domain) ?? {
838
+ domain,
839
+ provider: typeof config.provider === "string" ? config.provider : "custom",
840
+ config,
841
+ records: []
842
+ };
843
+ const planned = {
844
+ host,
845
+ domain,
846
+ name: extractSubdomain(host, domain),
847
+ type: record.type,
848
+ value,
849
+ ttl: recordTtl(config)
850
+ };
851
+ plan.records.push(planned);
852
+ domains.set(domain, plan);
853
+ }
854
+ if (domains.size === 0) return { manual };
855
+ const plans = [...domains.values()];
856
+ const tokens = await dnsCredentials(options.stage, plans.map(({ domain, config }) => ({
857
+ domain,
858
+ config
859
+ })), options.credentials);
860
+ const applied = await settleStackDns({
861
+ stage: options.stage,
862
+ server: { ipv4: "" },
863
+ domains: plans,
864
+ uncovered: []
865
+ }, {
866
+ ...options.dryRun ? { dryRun: true } : { confirm: true },
867
+ log,
868
+ credentials: {
869
+ ...tokens.godaddy ? { credential: tokens.godaddy } : {},
870
+ log
871
+ },
872
+ ...tokens.hostinger ? { hostinger: tokens.hostinger } : {},
873
+ ...options.providerFor ? { providerFor: options.providerFor } : {}
874
+ });
875
+ for (const change of applied.changes) {
876
+ if (change.action !== "manual") continue;
877
+ const host = plans.find((p) => p.domain === change.domain)?.records.find((r) => r.name === change.name)?.host;
878
+ if (host) manual.push(host);
879
+ }
880
+ return { manual: [...new Set(manual)].sort() };
881
+ }
882
+ //#endregion
883
+ //#region src/providers/s3/cdn.ts
884
+ /** AWS's managed `CachingOptimized` cache policy: path-keyed, gzip and brotli. */
885
+ const CACHING_OPTIMIZED = "658327ea-f89d-4fab-a63d-7e88639e58f6";
886
+ /** What an immutable path is served with. */
887
+ const IMMUTABLE_CACHE_CONTROL = "public, max-age=31536000, immutable";
888
+ /** The only region CloudFront reads a certificate from. */
889
+ const CDN_REGION = "us-east-1";
890
+ /** The distribution's bucket origin. */
891
+ const ORIGIN_ID = "bucket";
892
+ /** Its processors' origin: the stack's processor unit, at a host of its own. */
893
+ const PROCESSORS_ORIGIN_ID = "processors";
894
+ /**
895
+ * AWS's managed `CachingOptimizedForUncompressedObjects`: keyed on the path
896
+ * alone, and nothing re-compressed — a derivative is an image, already
897
+ * compressed, and its width is in the path, so nothing else may fragment it.
898
+ */
899
+ const CACHING_OPTIMIZED_UNCOMPRESSED = "b2884449-e4de-46a7-ac36-70bc7f1ddd6d";
900
+ /** A CDN is a name on the stage's domain, and the stage has none. */
901
+ var FileServerCdnNeedsDomain = class extends GkmError {
902
+ server;
903
+ stage;
904
+ constructor(server, stage) {
905
+ super(`'${server}' is served through a CDN on '${stage}', which answers on <fileserver>.<domain> — and '${stage}' has no domain. Set domains.${stage} in gkm.config.ts, or set deploy.objects.${stage}.cdn to false to serve it from the bucket's own endpoint.`);
906
+ this.server = server;
907
+ this.stage = stage;
908
+ this.name = "FileServerCdnNeedsDomain";
909
+ }
910
+ };
911
+ /**
912
+ * The certificate is waiting on its validation record: one the person has to
913
+ * create, or one that has not propagated yet. Everything up to it is
914
+ * recorded, so the next deploy carries on from here.
915
+ */
916
+ var CdnCertificatePending = class extends GkmError {
917
+ server;
918
+ host;
919
+ record;
920
+ reason;
921
+ constructor(server, host, record, reason) {
922
+ super((reason === "manual" ? `The certificate for ${host} ('${server}') is validated by a DNS record no DNS provider in gkm.config.ts can write. Create it at the domain's DNS host:
923
+ ` : `The certificate for ${host} ('${server}') is not issued yet: ACM has not seen its validation record. It is written; DNS can take a while to answer with it. Check it resolves:
924
+ `) + ` ${record.name} CNAME ${record.value}\nthen deploy again — the certificate and everything before it are recorded, and the deploy carries on from there.`);
925
+ this.server = server;
926
+ this.host = host;
927
+ this.record = record;
928
+ this.reason = reason;
929
+ this.name = "CdnCertificatePending";
930
+ }
931
+ };
932
+ /** ACM gave up on the certificate. */
933
+ var CdnCertificateFailed = class extends GkmError {
934
+ server;
935
+ host;
936
+ status;
937
+ reason;
938
+ constructor(server, host, status, reason) {
939
+ super(`ACM did not issue the certificate for ${host} ('${server}'): ${status}` + (reason ? ` (${reason})` : "") + ". A CAA record on the domain that does not allow amazon.com, or a validation record removed before it was checked, are the usual causes. Fix it and deploy again: a new certificate is requested.");
940
+ this.server = server;
941
+ this.host = host;
942
+ this.status = status;
943
+ this.reason = reason;
944
+ this.name = "CdnCertificateFailed";
945
+ }
946
+ };
947
+ /** Where a file server answers: `<fileserver>.<domain>`. */
948
+ function cdnHost(serverId, domain) {
949
+ return `${appKey(serverId)}.${domain}`.toLowerCase();
950
+ }
951
+ /**
952
+ * The name the stage's CDN resources go by, within CloudFront's limits:
953
+ * letters, digits, `-` and `_`, and at most 64 characters (an origin access
954
+ * control's). Kept whole where it fits; otherwise shortened with a hash of
955
+ * the whole, so two long names never meet.
956
+ */
957
+ function cdnName(scope, stage, serverId) {
958
+ const whole = `gkm-${scope}-${stage}-${appKey(serverId)}`.replace(/[^A-Za-z0-9_-]/g, "-");
959
+ if (whole.length <= 56) return whole;
960
+ return `${whole.slice(0, 47)}-${hash(whole)}`;
961
+ }
962
+ function hash(value) {
963
+ let h = 2166136261;
964
+ for (let i = 0; i < value.length; i++) {
965
+ h ^= value.charCodeAt(i);
966
+ h = Math.imul(h, 16777619);
967
+ }
968
+ return (h >>> 0).toString(36).padStart(8, "0").slice(0, 8);
969
+ }
970
+ /**
971
+ * An open or immutable glob as a CloudFront path pattern. CloudFront's `*`
972
+ * crosses `/`, so a single star is as wide as a double one — the bucket
973
+ * policy reads it the same way, and the construct's own check is the
974
+ * stricter of the three.
975
+ */
976
+ function pathPattern(glob) {
977
+ return glob.replace(/^\/+/, "").replace(/\*\*/g, "*");
978
+ }
979
+ /** A CloudFront list: its `Quantity` and, when it has some, its `Items`. */
980
+ function list(items) {
981
+ return items.length > 0 ? {
982
+ Quantity: items.length,
983
+ Items: [...items]
984
+ } : { Quantity: 0 };
985
+ }
986
+ /** One of the stage's response headers policies. */
987
+ function headersPolicyConfig(input) {
988
+ return {
989
+ Name: input.name,
990
+ Comment: input.comment,
991
+ ...input.origins.length > 0 ? { CorsConfig: {
992
+ AccessControlAllowOrigins: list([...input.origins].sort()),
993
+ AccessControlAllowHeaders: {
994
+ Quantity: 1,
995
+ Items: ["*"]
996
+ },
997
+ AccessControlAllowMethods: {
998
+ Quantity: 3,
999
+ Items: [
1000
+ "GET",
1001
+ "HEAD",
1002
+ "OPTIONS"
1003
+ ]
1004
+ },
1005
+ AccessControlAllowCredentials: false,
1006
+ AccessControlMaxAgeSec: 86400,
1007
+ OriginOverride: false
1008
+ } } : {},
1009
+ ...input.immutable ? { CustomHeadersConfig: {
1010
+ Quantity: 1,
1011
+ Items: [{
1012
+ Header: "Cache-Control",
1013
+ Value: IMMUTABLE_CACHE_CONTROL,
1014
+ Override: true
1015
+ }]
1016
+ } } : {}
1017
+ };
1018
+ }
1019
+ /** The parts of a distribution's config this provider owns. */
1020
+ function distributionConfig(input) {
1021
+ const behaviour = (policy) => ({
1022
+ TargetOriginId: ORIGIN_ID,
1023
+ ViewerProtocolPolicy: "redirect-to-https",
1024
+ AllowedMethods: {
1025
+ Quantity: 3,
1026
+ Items: [
1027
+ "GET",
1028
+ "HEAD",
1029
+ "OPTIONS"
1030
+ ],
1031
+ CachedMethods: {
1032
+ Quantity: 2,
1033
+ Items: ["GET", "HEAD"]
1034
+ }
1035
+ },
1036
+ Compress: true,
1037
+ CachePolicyId: CACHING_OPTIMIZED,
1038
+ ...policy ? { ResponseHeadersPolicyId: policy } : {}
1039
+ });
1040
+ const patterns = [...new Set(input.immutable.map(pathPattern))].sort();
1041
+ const processors = input.processors;
1042
+ const processorPatterns = processors ? [...new Set(processors.prefixes.map((p) => `${pathPattern(p)}*`))].sort() : [];
1043
+ return {
1044
+ CallerReference: input.callerReference,
1045
+ Comment: input.comment,
1046
+ Enabled: true,
1047
+ Aliases: {
1048
+ Quantity: 1,
1049
+ Items: [input.host]
1050
+ },
1051
+ Origins: list([{
1052
+ Id: ORIGIN_ID,
1053
+ DomainName: input.bucketDomain,
1054
+ OriginPath: "",
1055
+ S3OriginConfig: { OriginAccessIdentity: "" },
1056
+ OriginAccessControlId: input.originAccessControlId
1057
+ }, ...processors ? [{
1058
+ Id: PROCESSORS_ORIGIN_ID,
1059
+ DomainName: processors.host,
1060
+ OriginPath: "",
1061
+ CustomOriginConfig: {
1062
+ HTTPPort: 80,
1063
+ HTTPSPort: 443,
1064
+ OriginProtocolPolicy: "https-only",
1065
+ OriginSslProtocols: {
1066
+ Quantity: 1,
1067
+ Items: ["TLSv1.2"]
1068
+ },
1069
+ OriginReadTimeout: 30,
1070
+ OriginKeepaliveTimeout: 5
1071
+ },
1072
+ CustomHeaders: {
1073
+ Quantity: 1,
1074
+ Items: [{
1075
+ HeaderName: ORIGIN_VERIFY_HEADER,
1076
+ HeaderValue: processors.secret
1077
+ }]
1078
+ }
1079
+ }] : []]),
1080
+ DefaultCacheBehavior: behaviour(input.corsPolicyId),
1081
+ CacheBehaviors: list([...processorPatterns.map((PathPattern) => ({
1082
+ ...behaviour(input.corsPolicyId),
1083
+ TargetOriginId: PROCESSORS_ORIGIN_ID,
1084
+ Compress: false,
1085
+ CachePolicyId: CACHING_OPTIMIZED_UNCOMPRESSED,
1086
+ PathPattern
1087
+ })), ...patterns.map((PathPattern) => ({
1088
+ ...behaviour(input.immutablePolicyId),
1089
+ PathPattern
1090
+ }))]),
1091
+ ViewerCertificate: {
1092
+ ACMCertificateArn: input.certificateArn,
1093
+ SSLSupportMethod: "sni-only",
1094
+ MinimumProtocolVersion: "TLSv1.2_2021",
1095
+ CloudFrontDefaultCertificate: false
1096
+ },
1097
+ HttpVersion: "http2and3",
1098
+ IsIPV6Enabled: true,
1099
+ DefaultRootObject: ""
1100
+ };
1101
+ }
1102
+ /**
1103
+ * Whether `current` already holds everything in `wanted`: each key `wanted`
1104
+ * names, recursively, with lists compared as sets. What else `current` holds
1105
+ * — logging, a WAF, geo restrictions set by hand — is left alone, and a
1106
+ * `CallerReference`, fixed at creation, is never compared.
1107
+ */
1108
+ function holds(current, wanted, key) {
1109
+ if (key === "CallerReference") return true;
1110
+ if (Array.isArray(wanted)) return Array.isArray(current) && current.length === wanted.length && wanted.every((w) => current.some((c) => holds(c, w)));
1111
+ if (wanted && typeof wanted === "object") {
1112
+ if (!current || typeof current !== "object") return false;
1113
+ return Object.entries(wanted).every(([k, v]) => holds(current[k], v, k));
1114
+ }
1115
+ return current === wanted;
1116
+ }
1117
+ /** Header configs a policy may hold that this provider never sets. */
1118
+ const FOREIGN_HEADER_CONFIGS = [
1119
+ "CorsConfig",
1120
+ "CustomHeadersConfig",
1121
+ "SecurityHeadersConfig",
1122
+ "RemoveHeadersConfig",
1123
+ "ServerTimingHeadersConfig"
1124
+ ];
1125
+ /** Whether a policy is exactly what is wanted: nothing missing, nothing more. */
1126
+ function sameHeadersPolicy(current, wanted) {
1127
+ if (!current || !holds(current, wanted)) return false;
1128
+ return FOREIGN_HEADER_CONFIGS.every((k) => {
1129
+ if (k in wanted) return true;
1130
+ const extra = current[k];
1131
+ return !extra || extra.Quantity === 0;
1132
+ });
1133
+ }
1134
+ const defaultCdnClients = async (credential) => {
1135
+ const CF = await import("@aws-sdk/client-cloudfront");
1136
+ const ACM = await import("@aws-sdk/client-acm");
1137
+ const config = await awsClientConfig(credential, CDN_REGION);
1138
+ const cloudfront = awsEndpoint(process.env, "CLOUDFRONT");
1139
+ const acm = awsEndpoint(process.env, "ACM");
1140
+ return {
1141
+ CF,
1142
+ ACM,
1143
+ cloudfront: new CF.CloudFrontClient({
1144
+ ...config,
1145
+ ...cloudfront ? { endpoint: cloudfront } : {}
1146
+ }),
1147
+ acm: new ACM.ACMClient({
1148
+ ...config,
1149
+ ...acm ? { endpoint: acm } : {}
1150
+ }),
1151
+ wait: {
1152
+ timeoutMs: 9e5,
1153
+ intervalMs: 1e4
1154
+ }
1155
+ };
1156
+ };
1157
+ let makeCdnClients = defaultCdnClients;
1158
+ /** What an AWS SDK error is called, whichever field carries it. */
1159
+ function errorName$2(error) {
1160
+ const e = error;
1161
+ return e?.Code ?? e?.name ?? "";
1162
+ }
1163
+ async function readOr$2(read, missing) {
1164
+ try {
1165
+ return await read();
1166
+ } catch (error) {
1167
+ if (missing.includes(errorName$2(error))) return void 0;
1168
+ throw error;
1169
+ }
1170
+ }
1171
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1172
+ /** What stands in for an id a dry run would create. */
1173
+ const PLANNED = "(created by this deploy)";
1174
+ /** Each file server over a bucket, behind its own distribution. */
1175
+ async function ensureBucketCdn(ctx, input) {
1176
+ const domain = ctx.workspace.domains?.[ctx.stage];
1177
+ if (!domain) throw new FileServerCdnNeedsDomain(input.servers[0].id, ctx.stage);
1178
+ const clients = await makeCdnClients(ctx.credential);
1179
+ const out = {
1180
+ distributionArns: [],
1181
+ urls: {}
1182
+ };
1183
+ for (const server of input.servers) {
1184
+ const { arn, url } = await ensureServerCdn(ctx, clients, {
1185
+ ...input,
1186
+ server,
1187
+ host: cdnHost(server.id, domain),
1188
+ processorHost: processorOriginHost(server.id, domain)
1189
+ });
1190
+ out.distributionArns.push(arn);
1191
+ out.urls[server.id] = url;
1192
+ }
1193
+ return out;
1194
+ }
1195
+ async function ensureServerCdn(ctx, clients, input) {
1196
+ const { server, host } = input;
1197
+ const name = cdnName(ctx.identity.scope, ctx.stage, server.id);
1198
+ const comment = `gkm ${ctx.identity.key} ${ctx.stage} ${server.id}`.slice(0, 128);
1199
+ const certificateArn = await ensureCertificate(ctx, clients, {
1200
+ id: server.id,
1201
+ host,
1202
+ name
1203
+ });
1204
+ const originAccessControlId = await ensureOriginAccessControl(ctx, clients, {
1205
+ id: server.id,
1206
+ name,
1207
+ bucket: input.bucket
1208
+ });
1209
+ const corsPolicyId = input.origins.length > 0 ? await ensureHeadersPolicy(ctx, clients, {
1210
+ id: server.id,
1211
+ kind: "cors",
1212
+ config: headersPolicyConfig({
1213
+ name: `${name}-cors`,
1214
+ comment: `${comment}: CORS`,
1215
+ origins: input.origins,
1216
+ immutable: false
1217
+ })
1218
+ }) : void 0;
1219
+ const immutablePolicyId = server.immutable.length > 0 ? await ensureHeadersPolicy(ctx, clients, {
1220
+ id: server.id,
1221
+ kind: "immutable",
1222
+ config: headersPolicyConfig({
1223
+ name: `${name}-immutable`,
1224
+ comment: `${comment}: CORS and Cache-Control immutable`,
1225
+ origins: input.origins,
1226
+ immutable: true
1227
+ })
1228
+ }) : void 0;
1229
+ const processors = server.processors?.length ? {
1230
+ prefixes: server.processors,
1231
+ host: input.processorHost,
1232
+ secret: await ensureOriginSecret(ctx, server.id)
1233
+ } : void 0;
1234
+ const distribution = await ensureDistribution(ctx, clients, {
1235
+ id: server.id,
1236
+ comment,
1237
+ config: distributionConfig({
1238
+ comment,
1239
+ callerReference: name,
1240
+ host,
1241
+ certificateArn,
1242
+ bucketDomain: `${input.bucket}.s3.${input.region}.amazonaws.com`,
1243
+ originAccessControlId,
1244
+ ...corsPolicyId ? { corsPolicyId } : {},
1245
+ ...immutablePolicyId ? { immutablePolicyId } : {},
1246
+ immutable: server.immutable,
1247
+ ...processors ? { processors } : {}
1248
+ })
1249
+ });
1250
+ if (distribution.domainName !== PLANNED) {
1251
+ if ((await ctx.writeDns([{
1252
+ host,
1253
+ type: "CNAME",
1254
+ value: distribution.domainName
1255
+ }])).manual.includes(host)) ctx.log(` ${host} answers once that record exists — ${server.id}'s URL is https://${host}`);
1256
+ }
1257
+ return {
1258
+ arn: distribution.arn,
1259
+ url: `https://${host}`
1260
+ };
1261
+ }
1262
+ /**
1263
+ * The secret the CDN sends a file server's processors: the one in the stage's
1264
+ * secrets, or a new one written there — read by the stack, whose edge checks
1265
+ * it, when it composes.
1266
+ */
1267
+ async function ensureOriginSecret(ctx, serverId) {
1268
+ const key = originSecretKey(serverId);
1269
+ const kept = ctx.secrets[key];
1270
+ if (kept) return kept;
1271
+ const secret = newOriginSecret();
1272
+ ctx.log(` ${serverId}: a new processor origin secret, kept as ${key}`);
1273
+ await ctx.writeSecrets({ [key]: secret });
1274
+ return secret;
1275
+ }
1276
+ /** The certificate for `host`: recorded, adopted, or requested — then issued. */
1277
+ async function ensureCertificate(ctx, clients, input) {
1278
+ const { ACM, acm } = clients;
1279
+ const { id, host } = input;
1280
+ const entry = {
1281
+ key: `acm-certificate:${id}`,
1282
+ type: "acm-certificate",
1283
+ data: { host }
1284
+ };
1285
+ const describe = (arn) => readOr$2(() => acm.send(new ACM.DescribeCertificateCommand({ CertificateArn: arn })), ["ResourceNotFoundException"]).then((out) => out?.Certificate);
1286
+ let arn;
1287
+ const recorded = ctx.state.record(entry.key);
1288
+ if (recorded?.id && recorded.data?.host === host) {
1289
+ const found = await describe(recorded.id);
1290
+ if (found && found.Status !== "FAILED" && found.Status !== "VALIDATION_TIMED_OUT" && found.Status !== "REVOKED" && found.Status !== "EXPIRED") arn = recorded.id;
1291
+ }
1292
+ if (!arn) {
1293
+ arn = await findCertificate(clients, host);
1294
+ if (arn) ctx.log(` adopting the certificate for ${host} — ${arn}`);
1295
+ }
1296
+ if (!arn) {
1297
+ if (ctx.dryRun) {
1298
+ await ctx.change({
1299
+ construct: id,
1300
+ resource: `certificate ${host}`,
1301
+ change: "request (ACM, us-east-1, DNS-validated)"
1302
+ }, async () => {});
1303
+ return PLANNED;
1304
+ }
1305
+ await ctx.state.pending(entry);
1306
+ arn = (await acm.send(new ACM.RequestCertificateCommand({
1307
+ DomainName: host,
1308
+ ValidationMethod: "DNS",
1309
+ IdempotencyToken: input.name.replace(/[^A-Za-z0-9]/g, "").slice(0, 32),
1310
+ Tags: identityTags(ctx, id).map((t) => ({
1311
+ Key: t.Key,
1312
+ Value: t.Value
1313
+ }))
1314
+ }))).CertificateArn;
1315
+ await ctx.change({
1316
+ construct: id,
1317
+ resource: `certificate ${host}`,
1318
+ change: "request (ACM, us-east-1, DNS-validated)"
1319
+ }, async () => {});
1320
+ }
1321
+ if (!ctx.dryRun) await ctx.state.ready(entry, arn);
1322
+ let certificate = await describe(arn);
1323
+ let record = certificate?.DomainValidationOptions?.[0]?.ResourceRecord;
1324
+ for (let i = 0; !record && i < 15; i++) {
1325
+ await sleep(Math.min(clients.wait.intervalMs, 2e3));
1326
+ certificate = await describe(arn);
1327
+ record = certificate?.DomainValidationOptions?.[0]?.ResourceRecord;
1328
+ }
1329
+ const validation = record ? {
1330
+ name: record.Name.replace(/\.$/, ""),
1331
+ value: record.Value.replace(/\.$/, "")
1332
+ } : void 0;
1333
+ const written = validation ? await ctx.writeDns([{
1334
+ host: validation.name,
1335
+ type: "CNAME",
1336
+ value: validation.value
1337
+ }]) : { manual: [] };
1338
+ if (certificate?.Status === "ISSUED" || ctx.dryRun) return arn;
1339
+ if (validation && written.manual.includes(validation.name.toLowerCase())) throw new CdnCertificatePending(id, host, validation, "manual");
1340
+ ctx.log(` waiting for ACM to issue the certificate for ${host}…`);
1341
+ const deadline = Date.now() + clients.wait.timeoutMs;
1342
+ while (certificate?.Status === "PENDING_VALIDATION" && Date.now() < deadline) {
1343
+ await sleep(clients.wait.intervalMs);
1344
+ certificate = await describe(arn);
1345
+ }
1346
+ if (certificate?.Status === "ISSUED") return arn;
1347
+ if (certificate?.Status === "PENDING_VALIDATION" || !certificate) throw new CdnCertificatePending(id, host, validation ?? {
1348
+ name: `(not published yet) ${host}`,
1349
+ value: ""
1350
+ }, "timeout");
1351
+ throw new CdnCertificateFailed(id, host, certificate.Status ?? "unknown", certificate.FailureReason);
1352
+ }
1353
+ /** An issued or pending certificate for exactly `host`, if the account has one. */
1354
+ async function findCertificate(clients, host) {
1355
+ const { ACM, acm } = clients;
1356
+ let NextToken;
1357
+ do {
1358
+ const page = await acm.send(new ACM.ListCertificatesCommand({
1359
+ CertificateStatuses: ["ISSUED", "PENDING_VALIDATION"],
1360
+ ...NextToken ? { NextToken } : {}
1361
+ }));
1362
+ const match = page.CertificateSummaryList?.find((c) => c.DomainName?.toLowerCase() === host);
1363
+ if (match?.CertificateArn) return match.CertificateArn;
1364
+ NextToken = page.NextToken;
1365
+ } while (NextToken);
1366
+ }
1367
+ /** The origin access control CloudFront signs its bucket requests with. */
1368
+ async function ensureOriginAccessControl(ctx, clients, input) {
1369
+ const { CF, cloudfront } = clients;
1370
+ const entry = {
1371
+ key: `cloudfront-oac:${input.id}`,
1372
+ type: "cloudfront-oac",
1373
+ data: { name: input.name }
1374
+ };
1375
+ const recorded = ctx.state.record(entry.key)?.id;
1376
+ if (recorded) {
1377
+ if (await readOr$2(() => cloudfront.send(new CF.GetOriginAccessControlCommand({ Id: recorded })), ["NoSuchOriginAccessControl"])) return recorded;
1378
+ }
1379
+ let Marker;
1380
+ do {
1381
+ const page = await cloudfront.send(new CF.ListOriginAccessControlsCommand({ ...Marker ? { Marker } : {} }));
1382
+ const match = page.OriginAccessControlList?.Items?.find((o) => o.Name === input.name);
1383
+ if (match?.Id) {
1384
+ if (!ctx.dryRun) await ctx.state.ready(entry, match.Id);
1385
+ return match.Id;
1386
+ }
1387
+ Marker = page.OriginAccessControlList?.NextMarker;
1388
+ } while (Marker);
1389
+ let id = PLANNED;
1390
+ await ctx.change({
1391
+ construct: input.id,
1392
+ resource: `origin access control ${input.name}`,
1393
+ change: `create (CloudFront signs its reads of ${input.bucket})`
1394
+ }, async () => {
1395
+ await ctx.state.pending(entry);
1396
+ id = (await cloudfront.send(new CF.CreateOriginAccessControlCommand({ OriginAccessControlConfig: {
1397
+ Name: input.name,
1398
+ Description: `gkm: CloudFront's reads of ${input.bucket}`,
1399
+ OriginAccessControlOriginType: "s3",
1400
+ SigningBehavior: "always",
1401
+ SigningProtocol: "sigv4"
1402
+ } }))).OriginAccessControl.Id;
1403
+ await ctx.state.ready(entry, id);
1404
+ });
1405
+ return id;
1406
+ }
1407
+ /** One response headers policy, as wanted. */
1408
+ async function ensureHeadersPolicy(ctx, clients, input) {
1409
+ const { CF, cloudfront } = clients;
1410
+ const { config } = input;
1411
+ const entry = {
1412
+ key: `cloudfront-headers:${input.id}:${input.kind}`,
1413
+ type: "cloudfront-headers",
1414
+ data: { name: config.Name }
1415
+ };
1416
+ const read = (Id) => readOr$2(() => cloudfront.send(new CF.GetResponseHeadersPolicyConfigCommand({ Id })), ["NoSuchResponseHeadersPolicy"]);
1417
+ let id = ctx.state.record(entry.key)?.id;
1418
+ let current = id ? await read(id) : void 0;
1419
+ if (!current) {
1420
+ id = void 0;
1421
+ let Marker;
1422
+ do {
1423
+ const page = await cloudfront.send(new CF.ListResponseHeadersPoliciesCommand({
1424
+ Type: "custom",
1425
+ ...Marker ? { Marker } : {}
1426
+ }));
1427
+ const match = page.ResponseHeadersPolicyList?.Items?.find((p) => p.ResponseHeadersPolicy?.ResponseHeadersPolicyConfig?.Name === config.Name);
1428
+ if (match?.ResponseHeadersPolicy?.Id) {
1429
+ id = match.ResponseHeadersPolicy.Id;
1430
+ current = await read(id);
1431
+ }
1432
+ Marker = page.ResponseHeadersPolicyList?.NextMarker;
1433
+ } while (!id && Marker);
1434
+ }
1435
+ if (id && current) {
1436
+ if (!ctx.dryRun) await ctx.state.ready(entry, id);
1437
+ if (sameHeadersPolicy(current.ResponseHeadersPolicyConfig, config)) return id;
1438
+ const existing = id;
1439
+ await ctx.change({
1440
+ construct: input.id,
1441
+ resource: `response headers policy ${config.Name}`,
1442
+ change: "put back what drifted"
1443
+ }, async () => {
1444
+ await cloudfront.send(new CF.UpdateResponseHeadersPolicyCommand({
1445
+ Id: existing,
1446
+ IfMatch: current.ETag,
1447
+ ResponseHeadersPolicyConfig: config
1448
+ }));
1449
+ });
1450
+ return existing;
1451
+ }
1452
+ let created = PLANNED;
1453
+ await ctx.change({
1454
+ construct: input.id,
1455
+ resource: `response headers policy ${config.Name}`,
1456
+ change: "create"
1457
+ }, async () => {
1458
+ await ctx.state.pending(entry);
1459
+ created = (await cloudfront.send(new CF.CreateResponseHeadersPolicyCommand({ ResponseHeadersPolicyConfig: config }))).ResponseHeadersPolicy.Id;
1460
+ await ctx.state.ready(entry, created);
1461
+ });
1462
+ return created;
1463
+ }
1464
+ /** The distribution: recorded, found by its comment, or created — as wanted. */
1465
+ async function ensureDistribution(ctx, clients, input) {
1466
+ const { CF, cloudfront } = clients;
1467
+ const entry = {
1468
+ key: `cloudfront-distribution:${input.id}`,
1469
+ type: "cloudfront-distribution"
1470
+ };
1471
+ const get = (Id) => readOr$2(() => cloudfront.send(new CF.GetDistributionCommand({ Id })), ["NoSuchDistribution"]);
1472
+ let found = ctx.state.record(entry.key)?.id ? await get(ctx.state.record(entry.key).id) : void 0;
1473
+ if (!found) {
1474
+ let Marker;
1475
+ do {
1476
+ const page = await cloudfront.send(new CF.ListDistributionsCommand({ ...Marker ? { Marker } : {} }));
1477
+ const match = page.DistributionList?.Items?.find((d) => d.Comment === input.comment);
1478
+ if (match?.Id) found = await get(match.Id);
1479
+ Marker = page.DistributionList?.NextMarker;
1480
+ } while (!found && Marker);
1481
+ }
1482
+ if (found?.Distribution) {
1483
+ const distribution = found.Distribution;
1484
+ const id = distribution.Id;
1485
+ const located = {
1486
+ arn: distribution.ARN,
1487
+ domainName: distribution.DomainName
1488
+ };
1489
+ if (!ctx.dryRun) await ctx.state.ready({
1490
+ ...entry,
1491
+ data: located
1492
+ }, id);
1493
+ const current = await cloudfront.send(new CF.GetDistributionConfigCommand({ Id: id }));
1494
+ if (holds(current.DistributionConfig, input.config)) return located;
1495
+ await ctx.change({
1496
+ construct: input.id,
1497
+ resource: `distribution ${id}`,
1498
+ change: "put back what drifted"
1499
+ }, async () => {
1500
+ await cloudfront.send(new CF.UpdateDistributionCommand({
1501
+ Id: id,
1502
+ IfMatch: current.ETag,
1503
+ DistributionConfig: {
1504
+ ...current.DistributionConfig,
1505
+ ...input.config,
1506
+ CallerReference: current.DistributionConfig.CallerReference
1507
+ }
1508
+ }));
1509
+ });
1510
+ return located;
1511
+ }
1512
+ let created = {
1513
+ arn: `arn:aws:cloudfront::${PLANNED}`,
1514
+ domainName: PLANNED
1515
+ };
1516
+ const host = input.config.Aliases?.Items?.[0] ?? input.id;
1517
+ await ctx.change({
1518
+ construct: input.id,
1519
+ resource: `distribution ${host}`,
1520
+ change: "create (CloudFront, takes minutes to reach every edge)"
1521
+ }, async () => {
1522
+ await ctx.state.pending(entry);
1523
+ const out = await cloudfront.send(new CF.CreateDistributionWithTagsCommand({ DistributionConfigWithTags: {
1524
+ DistributionConfig: input.config,
1525
+ Tags: { Items: identityTags(ctx, input.id).map((t) => ({
1526
+ Key: t.Key,
1527
+ Value: t.Value
1528
+ })) }
1529
+ } }));
1530
+ created = {
1531
+ arn: out.Distribution.ARN,
1532
+ domainName: out.Distribution.DomainName
1533
+ };
1534
+ await ctx.state.ready({
1535
+ ...entry,
1536
+ data: created
1537
+ }, out.Distribution.Id);
1538
+ });
1539
+ return created;
1540
+ }
1541
+ //#endregion
798
1542
  //#region src/providers/s3/events.ts
799
1543
  /** What S3 tells the topic about: every object written, and every removed. */
800
1544
  const BUCKET_EVENTS = ["s3:ObjectCreated:*", "s3:ObjectRemoved:*"];
@@ -1223,10 +1967,12 @@ function bucketConstructs(manifest) {
1223
1967
  return Object.entries(manifest).filter(([, d]) => d.kind === "objects").map(([id, d]) => ({
1224
1968
  id,
1225
1969
  versioned: d.versioned === true,
1226
- ...d.expire ? { expire: d.expire } : {},
1970
+ ...bucketExpiry(manifest, id) ? { expire: bucketExpiry(manifest, id) } : {},
1227
1971
  servers: Object.entries(manifest).filter(([, s]) => s.kind === "file-server" && s.of === id).map(([sid, s]) => ({
1228
1972
  id: sid,
1229
- open: s.open ?? []
1973
+ open: s.open ?? [],
1974
+ immutable: s.immutable ?? [],
1975
+ ...s.processors?.length ? { processors: [...new Set(s.processors.map((p) => p.prefix))].sort() } : {}
1230
1976
  })).sort((a, b) => a.id.localeCompare(b.id))
1231
1977
  })).sort((a, b) => a.id.localeCompare(b.id));
1232
1978
  }
@@ -1377,12 +2123,25 @@ async function ensureBucket(ctx, stageClients, construct, watchers) {
1377
2123
  clients = await makeClients(ctx.credential, located.region);
1378
2124
  ctx.log(` '${bucket}' is in ${located.region}, not ${stageClients.region}: '${id}' is reached and addressed there`);
1379
2125
  }
2126
+ const cdn = ctx.config.cdn !== false && construct.servers.length > 0 ? await ensureBucketCdn(ctx, {
2127
+ bucket,
2128
+ region: clients.region,
2129
+ servers: construct.servers,
2130
+ origins: bucketOrigins({
2131
+ workspace: ctx.workspace,
2132
+ manifest: ctx.manifest,
2133
+ runnables: ctx.runnables,
2134
+ stage: ctx.stage,
2135
+ bucket: id
2136
+ }).origins
2137
+ }) : void 0;
1380
2138
  await ensureBucketSettings(ctx, clients, {
1381
2139
  id,
1382
2140
  bucket,
1383
2141
  exists,
1384
2142
  versioning,
1385
2143
  open,
2144
+ ...cdn ? { cdn } : {},
1386
2145
  ...construct.expire ? { expire: construct.expire } : {}
1387
2146
  });
1388
2147
  const events = watchers ? await ensureBucketEvents(ctx, clients, {
@@ -1419,8 +2178,9 @@ async function ensureBucket(ctx, stageClients, construct, watchers) {
1419
2178
  watchers
1420
2179
  });
1421
2180
  }
1422
- const publicUrl = bucketPublicUrl(bucket, clients.region, clients.endpoint);
2181
+ const bucketUrl = bucketPublicUrl(bucket, clients.region, clients.endpoint);
1423
2182
  for (const server of construct.servers) {
2183
+ const publicUrl = cdn?.urls[server.id] ?? bucketUrl;
1424
2184
  const key = provideKey(server.id, "url");
1425
2185
  const entry = {
1426
2186
  key: `file-server:${server.id}`,
@@ -1578,7 +2338,7 @@ async function ensureBucketSettings(ctx, clients, input) {
1578
2338
  Value: t.Value
1579
2339
  })) }
1580
2340
  })));
1581
- const isOpen = input.open.length > 0;
2341
+ const isOpen = input.open.length > 0 && !input.cdn;
1582
2342
  const block = publicAccessBlock(isOpen);
1583
2343
  const ensureBlock = async () => {
1584
2344
  const now = (await read(() => s3.send(new S3.GetPublicAccessBlockCommand({ Bucket })), ["NoSuchPublicAccessBlockConfiguration"]))?.PublicAccessBlockConfiguration;
@@ -1587,10 +2347,10 @@ async function ensureBucketSettings(ctx, clients, input) {
1587
2347
  PublicAccessBlockConfiguration: block
1588
2348
  })));
1589
2349
  };
1590
- const policy = bucketPolicy(bucket, input.open);
2350
+ const policy = bucketPolicy(bucket, input.open, input.cdn ? { cdn: input.cdn } : {});
1591
2351
  const ensurePolicy = async () => {
1592
2352
  const current = await read(() => s3.send(new S3.GetBucketPolicyCommand({ Bucket })), ["NoSuchBucketPolicy"]);
1593
- if (!(current?.Policy !== void 0 && canonicalPolicy(JSON.parse(current.Policy)) === canonicalPolicy(policy))) await set(isOpen ? `policy: TLS only, public read on ${input.open.join(", ")}` : "policy: TLS only", () => s3.send(new S3.PutBucketPolicyCommand({
2353
+ if (!(current?.Policy !== void 0 && canonicalPolicy(JSON.parse(current.Policy)) === canonicalPolicy(policy))) await set(isOpen ? `policy: TLS only, public read on ${input.open.join(", ")}` : input.cdn && input.open.length > 0 ? `policy: TLS only, CloudFront reads ${input.open.join(", ")}` : "policy: TLS only", () => s3.send(new S3.PutBucketPolicyCommand({
1594
2354
  Bucket,
1595
2355
  Policy: JSON.stringify(policy)
1596
2356
  })));
@@ -1892,6 +2652,17 @@ async function provisionStage(options) {
1892
2652
  log(` ${dryRun ? "would " : ""}${action.change} — ${action.resource}`);
1893
2653
  },
1894
2654
  writeSecrets,
2655
+ writeDns: (records) => writeProviderDns(records, {
2656
+ workspace,
2657
+ stage,
2658
+ dryRun,
2659
+ credentials: options.credentials ?? storedCredentials({
2660
+ env,
2661
+ ...options.home ? { home: options.home } : {}
2662
+ }),
2663
+ ...options.dnsProviderFor ? { providerFor: options.dnsProviderFor } : {},
2664
+ log
2665
+ }),
1895
2666
  log
1896
2667
  });
1897
2668
  if (entry.report.actions.length === 0) log(" up to date");
@@ -2334,6 +3105,7 @@ async function provisionResources(phaseCtx, request, ctx, store, emit) {
2334
3105
  ...request.rotateKeys ? { rotateKeys: true } : {},
2335
3106
  ...request.retireOldKeys ? { retireOldKeys: true } : {},
2336
3107
  ...ctx.home ? { home: ctx.home } : {},
3108
+ credentials: ctx.credentials,
2337
3109
  log: (line) => phaseCtx.logger.info(line)
2338
3110
  });
2339
3111
  if (!ctx.dryRun) return;
@@ -2664,4 +3436,4 @@ async function load(input, sandbox) {
2664
3436
  //#endregion
2665
3437
  export { UnknownDeployApps as a, bucketName as c, TargetBuildsNothing as i, iamUserName as l, NoDeployableApps as n, backupsUserName as o, RollbackFailed as r, IAM_USER_PATH as s, deploy as t };
2666
3438
 
2667
- //# sourceMappingURL=deploy-CiRYwFmr.mjs.map
3439
+ //# sourceMappingURL=deploy-CIPwTJ47.mjs.map