@geekmidas/cli 10.0.0-alpha.12 → 10.0.0-alpha.121

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 (517) hide show
  1. package/README.md +310 -377
  2. package/bin/adjacent-tsconfig.mjs +46 -8
  3. package/bin/gkm.mjs +11 -3
  4. package/bin/owning-tsconfig-jsx-register.mjs +18 -0
  5. package/bin/owning-tsconfig-jsx.mjs +108 -0
  6. package/dist/EndpointGenerator-BDa6pPgE.cjs +1090 -0
  7. package/dist/EndpointGenerator-BDa6pPgE.cjs.map +1 -0
  8. package/dist/EndpointGenerator-CP_z_E3e.mjs +1031 -0
  9. package/dist/EndpointGenerator-CP_z_E3e.mjs.map +1 -0
  10. package/dist/GoDaddyProvider-3C8U_tVu.cjs +388 -0
  11. package/dist/GoDaddyProvider-3C8U_tVu.cjs.map +1 -0
  12. package/dist/GoDaddyProvider-D0MQoOM4.mjs +388 -0
  13. package/dist/GoDaddyProvider-D0MQoOM4.mjs.map +1 -0
  14. package/dist/{HostingerProvider-BcyFRbqV.mjs → HostingerProvider-BNpS9aRJ.mjs} +29 -25
  15. package/dist/HostingerProvider-BNpS9aRJ.mjs.map +1 -0
  16. package/dist/{HostingerProvider-BOvsgATO.cjs → HostingerProvider-DR1iws1P.cjs} +29 -25
  17. package/dist/HostingerProvider-DR1iws1P.cjs.map +1 -0
  18. package/dist/LegacyStateStore-CRi7TosX.mjs +124 -0
  19. package/dist/LegacyStateStore-CRi7TosX.mjs.map +1 -0
  20. package/dist/LegacyStateStore-DHsoQGOo.cjs +124 -0
  21. package/dist/LegacyStateStore-DHsoQGOo.cjs.map +1 -0
  22. package/dist/LocalStateStore-BQXTkeoS.cjs +178 -0
  23. package/dist/LocalStateStore-BQXTkeoS.cjs.map +1 -0
  24. package/dist/LocalStateStore-Dkth0jXX.mjs +167 -0
  25. package/dist/LocalStateStore-Dkth0jXX.mjs.map +1 -0
  26. package/dist/OpenApiTsGenerator-CsrukCE-.mjs +536 -0
  27. package/dist/OpenApiTsGenerator-CsrukCE-.mjs.map +1 -0
  28. package/dist/OpenApiTsGenerator-FNhY7Ssz.cjs +541 -0
  29. package/dist/OpenApiTsGenerator-FNhY7Ssz.cjs.map +1 -0
  30. package/dist/{Route53Provider-CH9XH7bz.cjs → Route53Provider-Bllus2NR.cjs} +21 -22
  31. package/dist/Route53Provider-Bllus2NR.cjs.map +1 -0
  32. package/dist/{Route53Provider-C0xmer8U.mjs → Route53Provider-QXxjkZO1.mjs} +13 -13
  33. package/dist/Route53Provider-QXxjkZO1.mjs.map +1 -0
  34. package/dist/S3StateStore-DGKZgyKz.cjs +222 -0
  35. package/dist/S3StateStore-DGKZgyKz.cjs.map +1 -0
  36. package/dist/S3StateStore-pZZnLLBd.mjs +223 -0
  37. package/dist/S3StateStore-pZZnLLBd.mjs.map +1 -0
  38. package/dist/SSMStateStore-CZRMERDA.mjs +205 -0
  39. package/dist/SSMStateStore-CZRMERDA.mjs.map +1 -0
  40. package/dist/SSMStateStore-DzkyjQ5D.cjs +204 -0
  41. package/dist/SSMStateStore-DzkyjQ5D.cjs.map +1 -0
  42. package/dist/SubscriberGenerator-C8CPxrCK.cjs +592 -0
  43. package/dist/SubscriberGenerator-C8CPxrCK.cjs.map +1 -0
  44. package/dist/SubscriberGenerator-y3pncae_.mjs +533 -0
  45. package/dist/SubscriberGenerator-y3pncae_.mjs.map +1 -0
  46. package/dist/add-C0kXOsWS.mjs +717 -0
  47. package/dist/add-C0kXOsWS.mjs.map +1 -0
  48. package/dist/add-Df8cmz0H.cjs +719 -0
  49. package/dist/add-Df8cmz0H.cjs.map +1 -0
  50. package/dist/appPorts-BoXMwolc.mjs +249 -0
  51. package/dist/appPorts-BoXMwolc.mjs.map +1 -0
  52. package/dist/appPorts-IW-OZmRi.cjs +296 -0
  53. package/dist/appPorts-IW-OZmRi.cjs.map +1 -0
  54. package/dist/aws-8QQ8n-t6.mjs +89 -0
  55. package/dist/aws-8QQ8n-t6.mjs.map +1 -0
  56. package/dist/aws-DY9NqQIT.cjs +100 -0
  57. package/dist/aws-DY9NqQIT.cjs.map +1 -0
  58. package/dist/awsStore-Bx5nCFnS.mjs +121 -0
  59. package/dist/awsStore-Bx5nCFnS.mjs.map +1 -0
  60. package/dist/awsStore-u3ehhMoY.cjs +138 -0
  61. package/dist/awsStore-u3ehhMoY.cjs.map +1 -0
  62. package/dist/{backup-provisioner-DXXg6FIL.mjs → backup-provisioner-C8DnCmxK.mjs} +11 -8
  63. package/dist/backup-provisioner-C8DnCmxK.mjs.map +1 -0
  64. package/dist/{backup-provisioner-cE2PuCTb.cjs → backup-provisioner-oDEsPj02.cjs} +22 -20
  65. package/dist/backup-provisioner-oDEsPj02.cjs.map +1 -0
  66. package/dist/backups/runner.cjs +519 -0
  67. package/dist/backups/runner.cjs.map +1 -0
  68. package/dist/backups/runner.d.cts +102 -0
  69. package/dist/backups/runner.d.cts.map +1 -0
  70. package/dist/backups/runner.d.mts +102 -0
  71. package/dist/backups/runner.d.mts.map +1 -0
  72. package/dist/backups/runner.mjs +506 -0
  73. package/dist/backups/runner.mjs.map +1 -0
  74. package/dist/{bundler-Bux2iF-v.mjs → bundler-B-I4Du99.mjs} +35 -16
  75. package/dist/bundler-B-I4Du99.mjs.map +1 -0
  76. package/dist/{bundler-BMekgx7a.cjs → bundler-Dx_grUmc.cjs} +37 -19
  77. package/dist/bundler-Dx_grUmc.cjs.map +1 -0
  78. package/dist/cli-Cd9exatJ.cjs +71 -0
  79. package/dist/cli-Cd9exatJ.cjs.map +1 -0
  80. package/dist/cli-DL7GxGAe.mjs +71 -0
  81. package/dist/cli-DL7GxGAe.mjs.map +1 -0
  82. package/dist/compose-C43c03WZ.mjs +3284 -0
  83. package/dist/compose-C43c03WZ.mjs.map +1 -0
  84. package/dist/compose-Mdgea4Yt.cjs +3427 -0
  85. package/dist/compose-Mdgea4Yt.cjs.map +1 -0
  86. package/dist/config-D48erO2j.d.mts +269 -0
  87. package/dist/config-D48erO2j.d.mts.map +1 -0
  88. package/dist/config-DHDtsQrB.d.cts +269 -0
  89. package/dist/config-DHDtsQrB.d.cts.map +1 -0
  90. package/dist/config.cjs +421 -11
  91. package/dist/config.cjs.map +1 -0
  92. package/dist/config.d.cts +4 -120
  93. package/dist/config.d.mts +4 -120
  94. package/dist/config.mjs +405 -4
  95. package/dist/config.mjs.map +1 -0
  96. package/dist/credentialSchemas-B67WJOOm.cjs +272 -0
  97. package/dist/credentialSchemas-B67WJOOm.cjs.map +1 -0
  98. package/dist/credentialSchemas-DDOLRCLF.mjs +237 -0
  99. package/dist/credentialSchemas-DDOLRCLF.mjs.map +1 -0
  100. package/dist/credentials-B5N5yKk6.mjs +267 -0
  101. package/dist/credentials-B5N5yKk6.mjs.map +1 -0
  102. package/dist/credentials-Zqr3QQYB.cjs +350 -0
  103. package/dist/credentials-Zqr3QQYB.cjs.map +1 -0
  104. package/dist/databases-BPOgTn1u.mjs +522 -0
  105. package/dist/databases-BPOgTn1u.mjs.map +1 -0
  106. package/dist/databases-fOaoBInm.cjs +625 -0
  107. package/dist/databases-fOaoBInm.cjs.map +1 -0
  108. package/dist/define-6poNqm5O.mjs +106 -0
  109. package/dist/define-6poNqm5O.mjs.map +1 -0
  110. package/dist/define-crmMcXFS.cjs +153 -0
  111. package/dist/define-crmMcXFS.cjs.map +1 -0
  112. package/dist/deploy/public.cjs +212 -0
  113. package/dist/deploy/public.cjs.map +1 -0
  114. package/dist/deploy/public.d.cts +654 -0
  115. package/dist/deploy/public.d.cts.map +1 -0
  116. package/dist/deploy/public.d.mts +654 -0
  117. package/dist/deploy/public.d.mts.map +1 -0
  118. package/dist/deploy/public.mjs +145 -0
  119. package/dist/deploy/public.mjs.map +1 -0
  120. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  121. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  122. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  123. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  124. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  125. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  126. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  127. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  128. package/dist/deploy/sniffer-envparser-worker.cjs +54 -0
  129. package/dist/deploy/sniffer-envparser-worker.cjs.map +1 -0
  130. package/dist/deploy/sniffer-envparser-worker.d.cts +1 -0
  131. package/dist/deploy/sniffer-envparser-worker.d.mts +1 -0
  132. package/dist/deploy/sniffer-envparser-worker.mjs +55 -0
  133. package/dist/deploy/sniffer-envparser-worker.mjs.map +1 -0
  134. package/dist/deploy/sniffer-hooks.cjs +13 -7
  135. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  136. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  137. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  138. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  139. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  140. package/dist/deploy/sniffer-hooks.mjs +10 -3
  141. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  142. package/dist/deploy/sniffer-loader.cjs +16 -7
  143. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  144. package/dist/deploy/sniffer-loader.d.cts +1 -1
  145. package/dist/deploy/sniffer-loader.d.mts +1 -1
  146. package/dist/deploy/sniffer-loader.mjs +14 -3
  147. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  148. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  149. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  150. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  151. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  152. package/dist/deploy/sniffer-routes-worker.mjs +4 -4
  153. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  154. package/dist/deploy/sniffer-worker.cjs +15 -6
  155. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  156. package/dist/deploy/sniffer-worker.d.cts +1 -3
  157. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  158. package/dist/deploy/sniffer-worker.d.mts +1 -3
  159. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  160. package/dist/deploy/sniffer-worker.mjs +15 -4
  161. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  162. package/dist/deploy-BMM2hx-K.cjs +2401 -0
  163. package/dist/deploy-BMM2hx-K.cjs.map +1 -0
  164. package/dist/deploy-D5YhwDng.mjs +2328 -0
  165. package/dist/deploy-D5YhwDng.mjs.map +1 -0
  166. package/dist/derive-B4vDpzgP.mjs +150 -0
  167. package/dist/derive-B4vDpzgP.mjs.map +1 -0
  168. package/dist/derive-DAbo49sm.cjs +161 -0
  169. package/dist/derive-DAbo49sm.cjs.map +1 -0
  170. package/dist/discover-C5roJuc9.mjs +560 -0
  171. package/dist/discover-C5roJuc9.mjs.map +1 -0
  172. package/dist/discover-CSW_BMWa.d.cts +125 -0
  173. package/dist/discover-CSW_BMWa.d.cts.map +1 -0
  174. package/dist/discover-DozUKs8f.cjs +639 -0
  175. package/dist/discover-DozUKs8f.cjs.map +1 -0
  176. package/dist/discover-xtT7fgWg.d.mts +125 -0
  177. package/dist/discover-xtT7fgWg.d.mts.map +1 -0
  178. package/dist/dns-BIYf20p7.cjs +1057 -0
  179. package/dist/dns-BIYf20p7.cjs.map +1 -0
  180. package/dist/dns-agf2VCdV.mjs +926 -0
  181. package/dist/dns-agf2VCdV.mjs.map +1 -0
  182. package/dist/dokploy-2p4PK6ej.mjs +38 -0
  183. package/dist/dokploy-2p4PK6ej.mjs.map +1 -0
  184. package/dist/dokploy-BANMTroy.cjs +38 -0
  185. package/dist/dokploy-BANMTroy.cjs.map +1 -0
  186. package/dist/drivers-BjGDYfnC.mjs +195 -0
  187. package/dist/drivers-BjGDYfnC.mjs.map +1 -0
  188. package/dist/drivers-DbjiYpW6.cjs +224 -0
  189. package/dist/drivers-DbjiYpW6.cjs.map +1 -0
  190. package/dist/eas-CNi16SoO.cjs +337 -0
  191. package/dist/eas-CNi16SoO.cjs.map +1 -0
  192. package/dist/eas-iT2JDHCh.mjs +334 -0
  193. package/dist/eas-iT2JDHCh.mjs.map +1 -0
  194. package/dist/{emit-CIlvnDvV.mjs → emit-C1e8qD08.mjs} +13 -26
  195. package/dist/emit-C1e8qD08.mjs.map +1 -0
  196. package/dist/{emit-CUD1BWls.cjs → emit-Dmc1nvdS.cjs} +31 -57
  197. package/dist/emit-Dmc1nvdS.cjs.map +1 -0
  198. package/dist/encryption-DkXVbyZc.mjs +89 -0
  199. package/dist/encryption-DkXVbyZc.mjs.map +1 -0
  200. package/dist/encryption-d2lLtkYx.cjs +90 -0
  201. package/dist/encryption-d2lLtkYx.cjs.map +1 -0
  202. package/dist/engine-CatKW6E-.mjs +3089 -0
  203. package/dist/engine-CatKW6E-.mjs.map +1 -0
  204. package/dist/engine-DlEHexED.cjs +3202 -0
  205. package/dist/engine-DlEHexED.cjs.map +1 -0
  206. package/dist/errors-D8Gwp5kU.mjs +23 -0
  207. package/dist/errors-D8Gwp5kU.mjs.map +1 -0
  208. package/dist/errors-DMC4Umsb.cjs +34 -0
  209. package/dist/errors-DMC4Umsb.cjs.map +1 -0
  210. package/dist/github-BAeaC1Pl.cjs +833 -0
  211. package/dist/github-BAeaC1Pl.cjs.map +1 -0
  212. package/dist/github-DErsqKGN.mjs +832 -0
  213. package/dist/github-DErsqKGN.mjs.map +1 -0
  214. package/dist/googlePlay-BVcfFWRO.cjs +931 -0
  215. package/dist/googlePlay-BVcfFWRO.cjs.map +1 -0
  216. package/dist/googlePlay-BXJ5ZjMK.mjs +931 -0
  217. package/dist/googlePlay-BXJ5ZjMK.mjs.map +1 -0
  218. package/dist/identity-CBXr4wNi.mjs +129 -0
  219. package/dist/identity-CBXr4wNi.mjs.map +1 -0
  220. package/dist/identity-CbLfgQNT.cjs +182 -0
  221. package/dist/identity-CbLfgQNT.cjs.map +1 -0
  222. package/dist/{index-BzJ7QJ9c.d.mts → index-8OfpOtSI.d.cts} +39 -20
  223. package/dist/index-8OfpOtSI.d.cts.map +1 -0
  224. package/dist/{index-CfMjtdVC.d.cts → index-Dpji6Bxq.d.mts} +39 -20
  225. package/dist/index-Dpji6Bxq.d.mts.map +1 -0
  226. package/dist/index.cjs +14291 -11898
  227. package/dist/index.cjs.map +1 -1
  228. package/dist/index.d.cts +1 -1
  229. package/dist/index.d.mts +1 -1
  230. package/dist/index.mjs +13938 -11560
  231. package/dist/index.mjs.map +1 -1
  232. package/dist/local-BwC2v2Y8.mjs +224 -0
  233. package/dist/local-BwC2v2Y8.mjs.map +1 -0
  234. package/dist/local-DNhnkugT.cjs +241 -0
  235. package/dist/local-DNhnkugT.cjs.map +1 -0
  236. package/dist/migrate-Bb1MmGHl.mjs +181 -0
  237. package/dist/migrate-Bb1MmGHl.mjs.map +1 -0
  238. package/dist/migrate-D79GI0XM.cjs +271 -0
  239. package/dist/migrate-D79GI0XM.cjs.map +1 -0
  240. package/dist/migrate-L4a273dY.cjs +181 -0
  241. package/dist/migrate-L4a273dY.cjs.map +1 -0
  242. package/dist/migrate-s4QizIoM.mjs +266 -0
  243. package/dist/migrate-s4QizIoM.mjs.map +1 -0
  244. package/dist/openapi.cjs +214 -10
  245. package/dist/openapi.cjs.map +1 -0
  246. package/dist/openapi.d.cts +38 -17
  247. package/dist/openapi.d.cts.map +1 -1
  248. package/dist/openapi.d.mts +38 -17
  249. package/dist/openapi.d.mts.map +1 -1
  250. package/dist/openapi.mjs +208 -5
  251. package/dist/openapi.mjs.map +1 -0
  252. package/dist/projectBucket-BBbQ1lHF.cjs +263 -0
  253. package/dist/projectBucket-BBbQ1lHF.cjs.map +1 -0
  254. package/dist/projectBucket-C_DN4WzF.mjs +222 -0
  255. package/dist/projectBucket-C_DN4WzF.mjs.map +1 -0
  256. package/dist/provider-BqpjG9QM.cjs +57 -0
  257. package/dist/provider-BqpjG9QM.cjs.map +1 -0
  258. package/dist/provider-CEOKk8NS.mjs +46 -0
  259. package/dist/provider-CEOKk8NS.mjs.map +1 -0
  260. package/dist/publish-CcTlmJT6.mjs +123 -0
  261. package/dist/publish-CcTlmJT6.mjs.map +1 -0
  262. package/dist/publish-ydscCYsW.cjs +124 -0
  263. package/dist/publish-ydscCYsW.cjs.map +1 -0
  264. package/dist/ready-BFFP838V.cjs +404 -0
  265. package/dist/ready-BFFP838V.cjs.map +1 -0
  266. package/dist/ready-BOfogqzr.mjs +375 -0
  267. package/dist/ready-BOfogqzr.mjs.map +1 -0
  268. package/dist/reconcile/public.cjs +3 -5
  269. package/dist/reconcile/public.d.cts +11 -87
  270. package/dist/reconcile/public.d.cts.map +1 -1
  271. package/dist/reconcile/public.d.mts +11 -87
  272. package/dist/reconcile/public.d.mts.map +1 -1
  273. package/dist/reconcile/public.mjs +3 -4
  274. package/dist/{reconcile-BI0tWkwz.mjs → reconcile--I7V4Klj.mjs} +4 -7
  275. package/dist/reconcile--I7V4Klj.mjs.map +1 -0
  276. package/dist/{reconcile-Bhw5fmKu.cjs → reconcile-CuCQBa5-.cjs} +5 -8
  277. package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
  278. package/dist/resolve-BLp2trep.mjs +263 -0
  279. package/dist/resolve-BLp2trep.mjs.map +1 -0
  280. package/dist/resolve-BgL-brF9.cjs +316 -0
  281. package/dist/resolve-BgL-brF9.cjs.map +1 -0
  282. package/dist/rollback-2cyLXEH1.cjs +165 -0
  283. package/dist/rollback-2cyLXEH1.cjs.map +1 -0
  284. package/dist/rollback-DwqZ8zzj.mjs +136 -0
  285. package/dist/rollback-DwqZ8zzj.mjs.map +1 -0
  286. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  287. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  288. package/dist/run-BJLIerMM.mjs +133 -0
  289. package/dist/run-BJLIerMM.mjs.map +1 -0
  290. package/dist/run-fVZ-rLnc.cjs +174 -0
  291. package/dist/run-fVZ-rLnc.cjs.map +1 -0
  292. package/dist/runtime-ACdfK59n.d.cts +82 -0
  293. package/dist/runtime-ACdfK59n.d.cts.map +1 -0
  294. package/dist/runtime-YyQuekxi.d.mts +82 -0
  295. package/dist/runtime-YyQuekxi.d.mts.map +1 -0
  296. package/dist/s3-CrPoA89T.cjs +215 -0
  297. package/dist/s3-CrPoA89T.cjs.map +1 -0
  298. package/dist/s3-DQXZdmCM.mjs +215 -0
  299. package/dist/s3-DQXZdmCM.mjs.map +1 -0
  300. package/dist/sandbox/config-worker.cjs +43 -0
  301. package/dist/sandbox/config-worker.cjs.map +1 -0
  302. package/dist/sandbox/config-worker.d.cts +1 -0
  303. package/dist/sandbox/config-worker.d.mts +1 -0
  304. package/dist/sandbox/config-worker.mjs +44 -0
  305. package/dist/sandbox/config-worker.mjs.map +1 -0
  306. package/dist/sandbox/credentials-worker.cjs +54 -0
  307. package/dist/sandbox/credentials-worker.cjs.map +1 -0
  308. package/dist/sandbox/credentials-worker.d.cts +1 -0
  309. package/dist/sandbox/credentials-worker.d.mts +1 -0
  310. package/dist/sandbox/credentials-worker.mjs +55 -0
  311. package/dist/sandbox/credentials-worker.mjs.map +1 -0
  312. package/dist/sandbox/discover-worker.cjs +50 -0
  313. package/dist/sandbox/discover-worker.cjs.map +1 -0
  314. package/dist/sandbox/discover-worker.d.cts +1 -0
  315. package/dist/sandbox/discover-worker.d.mts +1 -0
  316. package/dist/sandbox/discover-worker.mjs +51 -0
  317. package/dist/sandbox/discover-worker.mjs.map +1 -0
  318. package/dist/sandbox/migrate-worker.cjs +75 -0
  319. package/dist/sandbox/migrate-worker.cjs.map +1 -0
  320. package/dist/sandbox/migrate-worker.d.cts +1 -0
  321. package/dist/sandbox/migrate-worker.d.mts +1 -0
  322. package/dist/sandbox/migrate-worker.mjs +76 -0
  323. package/dist/sandbox/migrate-worker.mjs.map +1 -0
  324. package/dist/sandbox-C4g1eG31.d.mts +104 -0
  325. package/dist/sandbox-C4g1eG31.d.mts.map +1 -0
  326. package/dist/sandbox-CHv3OYXg.cjs +165 -0
  327. package/dist/sandbox-CHv3OYXg.cjs.map +1 -0
  328. package/dist/sandbox-CbVB7uOD.mjs +118 -0
  329. package/dist/sandbox-CbVB7uOD.mjs.map +1 -0
  330. package/dist/sandbox-CdKgQ3XU.d.cts +104 -0
  331. package/dist/sandbox-CdKgQ3XU.d.cts.map +1 -0
  332. package/dist/{workspace-DPV7FtAv.cjs → schemas-BCwKKA42.mjs} +958 -1816
  333. package/dist/schemas-BCwKKA42.mjs.map +1 -0
  334. package/dist/{workspace-CtnZnWsa.mjs → schemas-BQ_v0lEX.cjs} +1048 -1626
  335. package/dist/schemas-BQ_v0lEX.cjs.map +1 -0
  336. package/dist/secretsManager-CQORubp9.mjs +97 -0
  337. package/dist/secretsManager-CQORubp9.mjs.map +1 -0
  338. package/dist/secretsManager-RAGcEDX1.cjs +108 -0
  339. package/dist/secretsManager-RAGcEDX1.cjs.map +1 -0
  340. package/dist/seeds-C2w4UqVP.cjs +9347 -0
  341. package/dist/seeds-C2w4UqVP.cjs.map +1 -0
  342. package/dist/seeds-Cwtv-U9-.mjs +8350 -0
  343. package/dist/seeds-Cwtv-U9-.mjs.map +1 -0
  344. package/dist/serverSetup-BdFOD93s.cjs +631 -0
  345. package/dist/serverSetup-BdFOD93s.cjs.map +1 -0
  346. package/dist/serverSetup-utKsoyGH.mjs +631 -0
  347. package/dist/serverSetup-utKsoyGH.mjs.map +1 -0
  348. package/dist/sniffer-8C4q6Szd.mjs +1825 -0
  349. package/dist/sniffer-8C4q6Szd.mjs.map +1 -0
  350. package/dist/sniffer-CF7wNxMo.cjs +1998 -0
  351. package/dist/sniffer-CF7wNxMo.cjs.map +1 -0
  352. package/dist/sst-B-Uz4cvm.cjs +464 -0
  353. package/dist/sst-B-Uz4cvm.cjs.map +1 -0
  354. package/dist/sst-C1pxbFEd.mjs +441 -0
  355. package/dist/sst-C1pxbFEd.mjs.map +1 -0
  356. package/dist/stage-BvM_u2z4.mjs +302 -0
  357. package/dist/stage-BvM_u2z4.mjs.map +1 -0
  358. package/dist/stage-DEQJGW3r.cjs +313 -0
  359. package/dist/stage-DEQJGW3r.cjs.map +1 -0
  360. package/dist/stages-Cb9rqRbN.mjs +190 -0
  361. package/dist/stages-Cb9rqRbN.mjs.map +1 -0
  362. package/dist/stages-D4SnG5yl.cjs +190 -0
  363. package/dist/stages-D4SnG5yl.cjs.map +1 -0
  364. package/dist/target/public.cjs +15 -0
  365. package/dist/target/public.d.cts +28 -0
  366. package/dist/target/public.d.cts.map +1 -0
  367. package/dist/target/public.d.mts +28 -0
  368. package/dist/target/public.d.mts.map +1 -0
  369. package/dist/target/public.mjs +4 -0
  370. package/dist/terminal-CW_dWeTe.mjs +85 -0
  371. package/dist/terminal-CW_dWeTe.mjs.map +1 -0
  372. package/dist/terminal-DJlqcW_U.cjs +85 -0
  373. package/dist/terminal-DJlqcW_U.cjs.map +1 -0
  374. package/dist/types-B6UXlEkf.d.cts +7650 -0
  375. package/dist/types-B6UXlEkf.d.cts.map +1 -0
  376. package/dist/types-HqVPddRK.d.mts +7649 -0
  377. package/dist/types-HqVPddRK.d.mts.map +1 -0
  378. package/dist/utils-D2Nk1Nv2.cjs +205 -0
  379. package/dist/utils-D2Nk1Nv2.cjs.map +1 -0
  380. package/dist/utils-D_fxUqvU.mjs +156 -0
  381. package/dist/utils-D_fxUqvU.mjs.map +1 -0
  382. package/dist/vitest.cjs +65 -0
  383. package/dist/vitest.cjs.map +1 -0
  384. package/dist/vitest.d.cts +29 -0
  385. package/dist/vitest.d.cts.map +1 -0
  386. package/dist/vitest.d.mts +29 -0
  387. package/dist/vitest.d.mts.map +1 -0
  388. package/dist/vitest.mjs +65 -0
  389. package/dist/vitest.mjs.map +1 -0
  390. package/dist/workerRuntime-BXfhbe13.cjs +108 -0
  391. package/dist/workerRuntime-BXfhbe13.cjs.map +1 -0
  392. package/dist/workerRuntime-CsOyBRx2.mjs +79 -0
  393. package/dist/workerRuntime-CsOyBRx2.mjs.map +1 -0
  394. package/dist/workspace/index.cjs +8 -4
  395. package/dist/workspace/index.d.cts +3 -3
  396. package/dist/workspace/index.d.mts +3 -3
  397. package/dist/workspace/index.mjs +2 -3
  398. package/dist/workspace-BwqQnool.cjs +2806 -0
  399. package/dist/workspace-BwqQnool.cjs.map +1 -0
  400. package/dist/workspace-D1QbNd55.mjs +2394 -0
  401. package/dist/workspace-D1QbNd55.mjs.map +1 -0
  402. package/package.json +54 -22
  403. package/dist/CachedStateProvider-BEBl2wQT.cjs +0 -60
  404. package/dist/CachedStateProvider-BEBl2wQT.cjs.map +0 -1
  405. package/dist/CachedStateProvider-C-8wtlto.mjs +0 -3
  406. package/dist/CachedStateProvider-Co4n5Wvs.mjs +0 -54
  407. package/dist/CachedStateProvider-Co4n5Wvs.mjs.map +0 -1
  408. package/dist/CachedStateProvider-DqhGpzsm.cjs +0 -3
  409. package/dist/HostingerProvider-BOvsgATO.cjs.map +0 -1
  410. package/dist/HostingerProvider-BcyFRbqV.mjs.map +0 -1
  411. package/dist/LocalStateProvider-Bq-0C0sg.mjs +0 -42
  412. package/dist/LocalStateProvider-Bq-0C0sg.mjs.map +0 -1
  413. package/dist/LocalStateProvider-yjXZXZDM.cjs +0 -43
  414. package/dist/LocalStateProvider-yjXZXZDM.cjs.map +0 -1
  415. package/dist/Route53Provider-C0xmer8U.mjs.map +0 -1
  416. package/dist/Route53Provider-CH9XH7bz.cjs.map +0 -1
  417. package/dist/SSMStateProvider-CXtNgPfy.cjs +0 -66
  418. package/dist/SSMStateProvider-CXtNgPfy.cjs.map +0 -1
  419. package/dist/SSMStateProvider-DOZifZfE.mjs +0 -66
  420. package/dist/SSMStateProvider-DOZifZfE.mjs.map +0 -1
  421. package/dist/backup-provisioner-DXXg6FIL.mjs.map +0 -1
  422. package/dist/backup-provisioner-cE2PuCTb.cjs.map +0 -1
  423. package/dist/bundler-BMekgx7a.cjs.map +0 -1
  424. package/dist/bundler-Bux2iF-v.mjs.map +0 -1
  425. package/dist/chunk-Duj1WY3L.mjs +0 -7
  426. package/dist/config-DTsVjKZD.mjs +0 -402
  427. package/dist/config-DTsVjKZD.mjs.map +0 -1
  428. package/dist/config-RYR9j6EF.cjs +0 -462
  429. package/dist/config-RYR9j6EF.cjs.map +0 -1
  430. package/dist/config.d.cts.map +0 -1
  431. package/dist/config.d.mts.map +0 -1
  432. package/dist/credentials-B5zRHdAl.mjs +0 -141
  433. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  434. package/dist/credentials-BapzjyV5.cjs +0 -195
  435. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  436. package/dist/credentials-DQRvPz2S.cjs +0 -2769
  437. package/dist/credentials-DQRvPz2S.cjs.map +0 -1
  438. package/dist/credentials-jMJC63qs.mjs +0 -2625
  439. package/dist/credentials-jMJC63qs.mjs.map +0 -1
  440. package/dist/discover-BYHQwQqu.mjs +0 -242
  441. package/dist/discover-BYHQwQqu.mjs.map +0 -1
  442. package/dist/discover-DmW9Bscc.cjs +0 -290
  443. package/dist/discover-DmW9Bscc.cjs.map +0 -1
  444. package/dist/dokploy-api-5cK2InBm.cjs +0 -3
  445. package/dist/dokploy-api-D2Ny4Jrc.mjs +0 -3
  446. package/dist/dokploy-api-pdaBryoY.mjs +0 -706
  447. package/dist/dokploy-api-pdaBryoY.mjs.map +0 -1
  448. package/dist/dokploy-api-zqKe9lHH.cjs +0 -718
  449. package/dist/dokploy-api-zqKe9lHH.cjs.map +0 -1
  450. package/dist/emit-CIlvnDvV.mjs.map +0 -1
  451. package/dist/emit-CUD1BWls.cjs.map +0 -1
  452. package/dist/encryption-D2pL3tHH.cjs +0 -54
  453. package/dist/encryption-D2pL3tHH.cjs.map +0 -1
  454. package/dist/encryption-YDsXXi6w.mjs +0 -3
  455. package/dist/encryption-_4zwjOAR.mjs +0 -42
  456. package/dist/encryption-_4zwjOAR.mjs.map +0 -1
  457. package/dist/encryption-sQ2Oxx0d.cjs +0 -4
  458. package/dist/fullstack-secrets-B6KBHf-g.mjs +0 -87
  459. package/dist/fullstack-secrets-B6KBHf-g.mjs.map +0 -1
  460. package/dist/fullstack-secrets-DL8v0y4D.cjs +0 -99
  461. package/dist/fullstack-secrets-DL8v0y4D.cjs.map +0 -1
  462. package/dist/generator-CNzBw7g5.cjs +0 -289
  463. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  464. package/dist/generator-VE2JrFlY.mjs +0 -253
  465. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  466. package/dist/github-BThvbf2W.cjs +0 -197
  467. package/dist/github-BThvbf2W.cjs.map +0 -1
  468. package/dist/github-DpMZurEK.mjs +0 -196
  469. package/dist/github-DpMZurEK.mjs.map +0 -1
  470. package/dist/index-BzJ7QJ9c.d.mts.map +0 -1
  471. package/dist/index-CfMjtdVC.d.cts.map +0 -1
  472. package/dist/keystore-C9rint2E.cjs +0 -101
  473. package/dist/keystore-C9rint2E.cjs.map +0 -1
  474. package/dist/keystore-TxeYM7an.mjs +0 -83
  475. package/dist/keystore-TxeYM7an.mjs.map +0 -1
  476. package/dist/openapi-Bs3-5q_r.mjs +0 -2021
  477. package/dist/openapi-Bs3-5q_r.mjs.map +0 -1
  478. package/dist/openapi-DWLTsYLL.cjs +0 -2075
  479. package/dist/openapi-DWLTsYLL.cjs.map +0 -1
  480. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  481. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  482. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  483. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  484. package/dist/openapi-react-query.cjs +0 -4
  485. package/dist/openapi-react-query.d.cts +0 -11
  486. package/dist/openapi-react-query.d.cts.map +0 -1
  487. package/dist/openapi-react-query.d.mts +0 -11
  488. package/dist/openapi-react-query.d.mts.map +0 -1
  489. package/dist/openapi-react-query.mjs +0 -4
  490. package/dist/reconcile-BI0tWkwz.mjs.map +0 -1
  491. package/dist/reconcile-Bhw5fmKu.cjs.map +0 -1
  492. package/dist/setup-BmLoNrDX.mjs +0 -12
  493. package/dist/setup-BrR1_xGy.cjs +0 -12
  494. package/dist/setup-BsNR2LBG.cjs +0 -467
  495. package/dist/setup-BsNR2LBG.cjs.map +0 -1
  496. package/dist/setup-D5-JMknk.mjs +0 -437
  497. package/dist/setup-D5-JMknk.mjs.map +0 -1
  498. package/dist/storage-B020InPW.mjs +0 -222
  499. package/dist/storage-B020InPW.mjs.map +0 -1
  500. package/dist/storage-CSNplaJn.cjs +0 -282
  501. package/dist/storage-CSNplaJn.cjs.map +0 -1
  502. package/dist/storage-DGBzMLZa.mjs +0 -4
  503. package/dist/storage-DlVol_oj.cjs +0 -8
  504. package/dist/sync-0ILCb-1S.cjs +0 -93
  505. package/dist/sync-0ILCb-1S.cjs.map +0 -1
  506. package/dist/sync-CzHXiR9c.mjs +0 -76
  507. package/dist/sync-CzHXiR9c.mjs.map +0 -1
  508. package/dist/sync-DYENfOt4.cjs +0 -4
  509. package/dist/sync-HAau6h_R.mjs +0 -3
  510. package/dist/types-DVIx8I1N.d.mts +0 -1950
  511. package/dist/types-DVIx8I1N.d.mts.map +0 -1
  512. package/dist/types-PMP_qXRY.d.cts +0 -1950
  513. package/dist/types-PMP_qXRY.d.cts.map +0 -1
  514. package/dist/workspace-Cji6lE8E.cjs +0 -10
  515. package/dist/workspace-CkJAtRIX.mjs +0 -9
  516. package/dist/workspace-CtnZnWsa.mjs.map +0 -1
  517. package/dist/workspace-DPV7FtAv.cjs.map +0 -1
@@ -0,0 +1,931 @@
1
+ import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
2
+ import { s as gkmHome } from "./run-BJLIerMM.mjs";
3
+ import { loadWorkspaceConfig } from "./config.mjs";
4
+ import { l as canPrompt, n as mobileStage } from "./index.mjs";
5
+ import { t as loadStage } from "./stage-BvM_u2z4.mjs";
6
+ import { chooseMobileApp, withStageProfiles } from "./eas-iT2JDHCh.mjs";
7
+ import { delimiter, extname, join } from "node:path";
8
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
9
+ import { readFile, writeFile } from "node:fs/promises";
10
+ import { spawn } from "node:child_process";
11
+ import { createSign } from "node:crypto";
12
+ //#region src/mobile/googlePlay/easApi.ts
13
+ /**
14
+ * EAS, as `gkm deploy:google-play` reaches it: the GraphQL API eas-cli itself
15
+ * calls, with an `EXPO_TOKEN` — to upload a Google service account key and
16
+ * assign it to the app's Android credentials for EAS Submit, which is what
17
+ * `eas credentials` does interactively.
18
+ *
19
+ * The documents are eas-cli's own (24.x), each selecting only what gkm reads:
20
+ * eas-cli's credentials fragment also brings back the app's keystore and its
21
+ * passwords, which gkm has no reason to hold.
22
+ */
23
+ const EAS_GRAPHQL = "https://api.expo.dev/graphql";
24
+ /** No `EXPO_TOKEN` to call EAS with. */
25
+ var ExpoTokenMissing = class extends GkmError {
26
+ constructor() {
27
+ super("gkm uploads the key to EAS with an access token, and EXPO_TOKEN is not set. Create one at https://expo.dev/settings/access-tokens and export it as EXPO_TOKEN.");
28
+ this.name = "ExpoTokenMissing";
29
+ }
30
+ };
31
+ /** EAS refused a call. */
32
+ var EasApiError = class extends GkmError {
33
+ operation;
34
+ detail;
35
+ constructor(operation, detail) {
36
+ super(`EAS refused ${operation}: ${detail}`);
37
+ this.operation = operation;
38
+ this.detail = detail;
39
+ this.name = "EasApiError";
40
+ }
41
+ };
42
+ const KEY_FIELDS = "id clientEmail privateKeyIdentifier";
43
+ function easApi(token = process.env.EXPO_TOKEN, endpoint = EAS_GRAPHQL) {
44
+ const call = async (operation, query, variables) => {
45
+ if (!token) throw new ExpoTokenMissing();
46
+ const response = await fetch(endpoint, {
47
+ method: "POST",
48
+ headers: {
49
+ authorization: `Bearer ${token}`,
50
+ "content-type": "application/json"
51
+ },
52
+ body: JSON.stringify({
53
+ query,
54
+ variables,
55
+ operationName: operation
56
+ })
57
+ });
58
+ const body = await response.json().catch(() => ({}));
59
+ if (!response.ok || body.errors?.length || !body.data) throw new EasApiError(operation, body.errors?.map((error) => error.message).join("; ") || `HTTP ${response.status}`);
60
+ return body.data;
61
+ };
62
+ const credentialsFields = `id googleServiceAccountKeyForSubmissions { ${KEY_FIELDS} }`;
63
+ const asCredentials = (credentials) => ({
64
+ id: credentials.id,
65
+ ...credentials.googleServiceAccountKeyForSubmissions ? { submissionsKey: credentials.googleServiceAccountKeyForSubmissions } : {}
66
+ });
67
+ return {
68
+ async project(projectId) {
69
+ const app = (await call("AppByIdQuery", `query AppByIdQuery($appId: String!) {
70
+ app { byId(appId: $appId) { id fullName ownerAccount { id name } } }
71
+ }`, { appId: projectId })).app.byId;
72
+ return {
73
+ accountId: app.ownerAccount.id,
74
+ accountName: app.ownerAccount.name,
75
+ fullName: app.fullName
76
+ };
77
+ },
78
+ async androidCredentials(project, packageName) {
79
+ const existing = (await call("AndroidAppCredentialsByApplicationIdentifierQuery", `query AndroidAppCredentialsByApplicationIdentifierQuery(
80
+ $projectFullName: String!
81
+ $applicationIdentifier: String
82
+ $legacyOnly: Boolean
83
+ ) {
84
+ app {
85
+ byFullName(fullName: $projectFullName) {
86
+ id
87
+ androidAppCredentials(
88
+ filter: { applicationIdentifier: $applicationIdentifier, legacyOnly: $legacyOnly }
89
+ ) { ${credentialsFields} }
90
+ }
91
+ }
92
+ }`, {
93
+ projectFullName: project.fullName,
94
+ applicationIdentifier: packageName,
95
+ legacyOnly: false
96
+ })).app.byFullName.androidAppCredentials[0];
97
+ if (existing) return asCredentials(existing);
98
+ const created = await call("CreateAndroidAppCredentialsMutation", `mutation CreateAndroidAppCredentialsMutation(
99
+ $androidAppCredentialsInput: AndroidAppCredentialsInput!
100
+ $appId: ID!
101
+ $applicationIdentifier: String!
102
+ ) {
103
+ androidAppCredentials {
104
+ createAndroidAppCredentials(
105
+ androidAppCredentialsInput: $androidAppCredentialsInput
106
+ appId: $appId
107
+ applicationIdentifier: $applicationIdentifier
108
+ ) { ${credentialsFields} }
109
+ }
110
+ }`, {
111
+ androidAppCredentialsInput: {},
112
+ appId: project.projectId,
113
+ applicationIdentifier: packageName
114
+ });
115
+ return asCredentials(created.androidAppCredentials.createAndroidAppCredentials);
116
+ },
117
+ async createKey(accountId, json) {
118
+ return (await call("CreateGoogleServiceAccountKeyMutation", `mutation CreateGoogleServiceAccountKeyMutation(
119
+ $googleServiceAccountKeyInput: GoogleServiceAccountKeyInput!
120
+ $accountId: ID!
121
+ ) {
122
+ googleServiceAccountKey {
123
+ createGoogleServiceAccountKey(
124
+ googleServiceAccountKeyInput: $googleServiceAccountKeyInput
125
+ accountId: $accountId
126
+ ) { ${KEY_FIELDS} }
127
+ }
128
+ }`, {
129
+ googleServiceAccountKeyInput: { jsonKey: json },
130
+ accountId
131
+ })).googleServiceAccountKey.createGoogleServiceAccountKey;
132
+ },
133
+ async useForSubmissions(credentialsId, keyId) {
134
+ await call("SetGoogleServiceAccountKeyForSubmissionsMutation", `mutation SetGoogleServiceAccountKeyForSubmissionsMutation(
135
+ $androidAppCredentialsId: ID!
136
+ $googleServiceAccountKeyId: ID!
137
+ ) {
138
+ androidAppCredentials {
139
+ setGoogleServiceAccountKeyForSubmissions(
140
+ id: $androidAppCredentialsId
141
+ googleServiceAccountKeyId: $googleServiceAccountKeyId
142
+ ) { id }
143
+ }
144
+ }`, {
145
+ androidAppCredentialsId: credentialsId,
146
+ googleServiceAccountKeyId: keyId
147
+ });
148
+ },
149
+ async keys(accountName) {
150
+ const keys = [];
151
+ let after = null;
152
+ do {
153
+ const page = (await call("GoogleServiceAccountKeysPaginatedByAccountQuery", `query GoogleServiceAccountKeysPaginatedByAccountQuery(
154
+ $accountName: String!
155
+ $after: String
156
+ $first: Int
157
+ ) {
158
+ account {
159
+ byName(accountName: $accountName) {
160
+ id
161
+ googleServiceAccountKeysPaginated(after: $after, first: $first) {
162
+ edges { node { ${KEY_FIELDS} } }
163
+ pageInfo { hasNextPage endCursor }
164
+ }
165
+ }
166
+ }
167
+ }`, {
168
+ accountName,
169
+ after,
170
+ first: 50
171
+ })).account.byName.googleServiceAccountKeysPaginated;
172
+ keys.push(...page.edges.map((edge) => edge.node));
173
+ after = page.pageInfo.hasNextPage ? page.pageInfo.endCursor : null;
174
+ } while (after);
175
+ return keys;
176
+ },
177
+ async deleteKey(id) {
178
+ await call("DeleteGoogleServiceAccountKeyMutation", `mutation DeleteGoogleServiceAccountKeyMutation($googleServiceAccountKeyId: ID!) {
179
+ googleServiceAccountKey { deleteGoogleServiceAccountKey(id: $googleServiceAccountKeyId) { id } }
180
+ }`, { googleServiceAccountKeyId: id });
181
+ }
182
+ };
183
+ }
184
+ //#endregion
185
+ //#region src/mobile/googlePlay/google.ts
186
+ /**
187
+ * Google, as `gkm deploy:google-play` reaches it: a token for the person
188
+ * running it, and the Cloud APIs that make a project, a service account and
189
+ * its key.
190
+ *
191
+ * The token is gcloud's own application-default credential, with the
192
+ * `cloud-platform` and `androidpublisher` scopes — no OAuth client of gkm's —
193
+ * kept in gkm's own gcloud config (`<gkm home>/gcloud`), so the person's own
194
+ * gcloud setup is never read or changed. Every call carries the project as
195
+ * its quota project (`x-goog-user-project`), which the Play Developer API
196
+ * requires of a user credential.
197
+ */
198
+ /** The scopes the sign-in asks for. */
199
+ const GOOGLE_SCOPES = ["https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/androidpublisher"];
200
+ /** `gcloud` is not installed. */
201
+ var GcloudMissing = class extends GkmError {
202
+ constructor() {
203
+ super("gkm signs in to Google with gcloud, and there is no `gcloud` here. Install the Google Cloud CLI: https://cloud.google.com/sdk/docs/install.");
204
+ this.name = "GcloudMissing";
205
+ }
206
+ };
207
+ /** Not signed in, and no terminal to sign in from. */
208
+ var GoogleSignInRequired = class extends GkmError {
209
+ config;
210
+ constructor(config) {
211
+ super(`Signing in to Google opens a browser, and this run has no terminal. Run it once where you can sign in, as a Play Console admin: CLOUDSDK_CONFIG=${config} gcloud auth application-default login --scopes=${GOOGLE_SCOPES.join(",")}.`);
212
+ this.config = config;
213
+ this.name = "GoogleSignInRequired";
214
+ }
215
+ };
216
+ /** A Google API refused a call. */
217
+ var GoogleApiError = class extends GkmError {
218
+ method;
219
+ url;
220
+ status;
221
+ detail;
222
+ constructor(method, url, status, detail) {
223
+ super(`Google answered ${status} to ${method} ${url}: ${detail}`);
224
+ this.method = method;
225
+ this.url = url;
226
+ this.status = status;
227
+ this.detail = detail;
228
+ this.name = "GoogleApiError";
229
+ }
230
+ };
231
+ /** A long-running Google operation did not finish in time. */
232
+ var GoogleOperationTimedOut = class extends GkmError {
233
+ operation;
234
+ constructor(operation) {
235
+ super(`Google's operation ${operation} had not finished after a minute. Run the command again: what it finished is kept.`);
236
+ this.operation = operation;
237
+ this.name = "GoogleOperationTimedOut";
238
+ }
239
+ };
240
+ /** Where gkm keeps its gcloud sign-in. */
241
+ function gcloudConfig(env = process.env) {
242
+ return join(gkmHome(env), "gcloud");
243
+ }
244
+ function gcloud(args, config, inherit) {
245
+ return new Promise((resolve, reject) => {
246
+ const child = spawn("gcloud", [...args], {
247
+ stdio: [
248
+ "inherit",
249
+ inherit ? "inherit" : "pipe",
250
+ inherit ? "inherit" : "pipe"
251
+ ],
252
+ env: {
253
+ ...process.env,
254
+ CLOUDSDK_CONFIG: config
255
+ }
256
+ });
257
+ let stdout = "";
258
+ child.stdout?.on("data", (chunk) => {
259
+ stdout += chunk.toString();
260
+ });
261
+ child.on("error", (error) => reject(error.code === "ENOENT" ? new GcloudMissing() : error));
262
+ child.on("close", (code) => resolve({
263
+ code,
264
+ stdout
265
+ }));
266
+ });
267
+ }
268
+ /** gcloud's application-default credential, in gkm's own gcloud config. */
269
+ function gcloudSignIn(config = gcloudConfig()) {
270
+ return { async token({ interactive }) {
271
+ const print = () => gcloud([
272
+ "auth",
273
+ "application-default",
274
+ "print-access-token"
275
+ ], config, false);
276
+ let printed = await print();
277
+ if (printed.code !== 0) {
278
+ if (!interactive) throw new GoogleSignInRequired(config);
279
+ await gcloud([
280
+ "auth",
281
+ "application-default",
282
+ "login",
283
+ `--scopes=${GOOGLE_SCOPES.join(",")}`
284
+ ], config, true);
285
+ printed = await print();
286
+ if (printed.code !== 0) throw new GoogleSignInRequired(config);
287
+ }
288
+ return printed.stdout.trim();
289
+ } };
290
+ }
291
+ function googleClient(token, quotaProject) {
292
+ return { async request(method, url, body, options) {
293
+ const headers = {
294
+ authorization: `Bearer ${token}`,
295
+ ...quotaProject ? { "x-goog-user-project": quotaProject } : {}
296
+ };
297
+ let payload;
298
+ if (options?.raw) {
299
+ headers["content-type"] = options.raw.contentType;
300
+ payload = options.raw.data;
301
+ } else if (body !== void 0) {
302
+ headers["content-type"] = "application/json";
303
+ payload = JSON.stringify(body);
304
+ }
305
+ const response = await fetch(url, {
306
+ method,
307
+ headers,
308
+ ...payload !== void 0 ? { body: payload } : {}
309
+ });
310
+ const text = await response.text();
311
+ if (!response.ok) {
312
+ let detail = text;
313
+ try {
314
+ detail = JSON.parse(text).error?.message ?? text;
315
+ } catch {}
316
+ throw new GoogleApiError(method, url, response.status, detail);
317
+ }
318
+ return text ? JSON.parse(text) : {};
319
+ } };
320
+ }
321
+ /** A long-running operation, polled until it is done. */
322
+ async function finished(client, base, operation, options = {}) {
323
+ let current = operation;
324
+ for (let attempt = 0; !current.done; attempt++) {
325
+ if (attempt >= (options.attempts ?? 30)) throw new GoogleOperationTimedOut(current.name ?? "(unnamed)");
326
+ await new Promise((resolve) => setTimeout(resolve, options.intervalMs ?? 2e3));
327
+ current = await client.request("GET", `${base}/${current.name}`);
328
+ }
329
+ if (current.error) throw new GoogleApiError("GET", `${base}/${current.name}`, 500, current.error.message ?? "the operation failed");
330
+ }
331
+ //#endregion
332
+ //#region src/mobile/googlePlay/gcp.ts
333
+ /**
334
+ * The Google Cloud side of publishing to Play: a project with the Android
335
+ * Publisher API on, and a service account in it whose JSON key EAS Submit
336
+ * uses. Each step finds what is there before it creates anything, so a
337
+ * second run reuses the project and the account and only makes a new key.
338
+ */
339
+ const CLOUD_RESOURCE_MANAGER = "https://cloudresourcemanager.googleapis.com/v3";
340
+ const SERVICE_USAGE = "https://serviceusage.googleapis.com/v1";
341
+ const IAM = "https://iam.googleapis.com/v1";
342
+ /** The API EAS Submit and gkm call Play through. */
343
+ const ANDROID_PUBLISHER_API = "androidpublisher.googleapis.com";
344
+ /** A project id or service account id gkm would derive is not a valid one. */
345
+ var GoogleIdInvalid = class extends GkmError {
346
+ kind;
347
+ id;
348
+ constructor(kind, id) {
349
+ super(`'${id}' is not a valid Google ${kind} id: 6 to 30 lowercase letters, digits and hyphens, starting with a letter and not ending in a hyphen. ` + (kind === "project" ? "Name one with --project." : ""));
350
+ this.kind = kind;
351
+ this.id = id;
352
+ this.name = "GoogleIdInvalid";
353
+ }
354
+ };
355
+ /** The project could not be created — most often, its id is someone else's. */
356
+ var GoogleProjectUnavailable = class extends GkmError {
357
+ project;
358
+ detail;
359
+ constructor(project, detail) {
360
+ super(`Could not create the Google Cloud project '${project}' (${detail}). Project ids are global: name another, or one you already have, with --project.`);
361
+ this.project = project;
362
+ this.detail = detail;
363
+ this.name = "GoogleProjectUnavailable";
364
+ }
365
+ };
366
+ const ID = /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/;
367
+ /**
368
+ * An id Google accepts, from a workspace's name: `shop` → `shop-play`.
369
+ * Lowercased, anything else made a hyphen, cut to 30.
370
+ */
371
+ function playId(workspace) {
372
+ return `${workspace.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^[^a-z]+|-+$/g, "").slice(0, 25).replace(/-+$/, "")}-play`;
373
+ }
374
+ /** Throws unless `id` is a valid project or service account id. */
375
+ function assertGoogleId(kind, id) {
376
+ if (!ID.test(id)) throw new GoogleIdInvalid(kind, id);
377
+ }
378
+ /**
379
+ * The project, created when it is not there. Answers whether it was made.
380
+ *
381
+ * @throws {GoogleProjectUnavailable}
382
+ */
383
+ async function ensureProject(client, project, displayName, options = {}) {
384
+ assertGoogleId("project", project);
385
+ try {
386
+ await client.request("GET", `${CLOUD_RESOURCE_MANAGER}/projects/${project}`);
387
+ return false;
388
+ } catch (error) {
389
+ if (!(error instanceof GoogleApiError) || ![403, 404].includes(error.status)) throw error;
390
+ }
391
+ try {
392
+ const operation = await client.request("POST", `${CLOUD_RESOURCE_MANAGER}/projects`, {
393
+ projectId: project,
394
+ displayName: displayName.slice(0, 30)
395
+ });
396
+ await finished(client, CLOUD_RESOURCE_MANAGER, operation, options);
397
+ } catch (error) {
398
+ if (error instanceof GoogleApiError) throw new GoogleProjectUnavailable(project, error.detail);
399
+ throw error;
400
+ }
401
+ return true;
402
+ }
403
+ /** The Android Publisher API, on in the project. */
404
+ async function enablePublisherApi(client, project, options = {}) {
405
+ const operation = await client.request("POST", `${SERVICE_USAGE}/projects/${project}/services/${ANDROID_PUBLISHER_API}:enable`, {});
406
+ await finished(client, SERVICE_USAGE, operation, options);
407
+ }
408
+ /** The service account's email, which is what Play and EAS know it by. */
409
+ function serviceAccountEmail(project, account) {
410
+ return `${account}@${project}.iam.gserviceaccount.com`;
411
+ }
412
+ /** The service account, created when it is not there. Answers its email. */
413
+ async function ensureServiceAccount(client, project, account, displayName) {
414
+ assertGoogleId("service account", account);
415
+ const email = serviceAccountEmail(project, account);
416
+ try {
417
+ await client.request("GET", `${IAM}/projects/${project}/serviceAccounts/${email}`);
418
+ return email;
419
+ } catch (error) {
420
+ if (!(error instanceof GoogleApiError) || error.status !== 404) throw error;
421
+ }
422
+ await client.request("POST", `${IAM}/projects/${project}/serviceAccounts`, {
423
+ accountId: account,
424
+ serviceAccount: { displayName: displayName.slice(0, 100) }
425
+ });
426
+ return email;
427
+ }
428
+ /** A new key for the account. Its JSON exists only in what this returns. */
429
+ async function createKey(client, project, email) {
430
+ const key = await client.request("POST", `${IAM}/projects/${project}/serviceAccounts/${email}/keys`, {});
431
+ return {
432
+ name: key.name,
433
+ json: Buffer.from(key.privateKeyData, "base64").toString("utf8")
434
+ };
435
+ }
436
+ /** The account's keys that someone made — not Google's own. */
437
+ async function listKeys(client, project, email) {
438
+ const { keys = [] } = await client.request("GET", `${IAM}/projects/${project}/serviceAccounts/${email}/keys?keyTypes=USER_MANAGED`);
439
+ return keys.map(({ name }) => ({ name }));
440
+ }
441
+ async function deleteKey(client, key) {
442
+ await client.request("DELETE", `${IAM}/${key.name}`);
443
+ }
444
+ /** A key's id: the last part of its name. */
445
+ function keyId(key) {
446
+ return key.name.split("/").pop();
447
+ }
448
+ //#endregion
449
+ //#region src/mobile/googlePlay/play.ts
450
+ /**
451
+ * Play Console, through the Play Developer API (androidpublisher v3): the
452
+ * service account's access to the app, the store listing as code, and a
453
+ * check that the new key can act on the app.
454
+ */
455
+ const PLAY = "https://androidpublisher.googleapis.com/androidpublisher/v3";
456
+ const PLAY_UPLOAD = "https://androidpublisher.googleapis.com/upload/androidpublisher/v3";
457
+ /** What Play answers about a package no app in the account has. */
458
+ const PACKAGE_MISSING = /packages are not available/i;
459
+ /** The app is not in Play Console yet, and Play has no API that makes one. */
460
+ var PlayAppMissing = class extends GkmError {
461
+ packageName;
462
+ developer;
463
+ constructor(packageName, developer) {
464
+ super(`Play Console has no app '${packageName}', and Play has no API that creates one. Create it at https://play.google.com/console/developers/${developer}/create-new-app, with ${packageName} as its package, then run this again.`);
465
+ this.packageName = packageName;
466
+ this.developer = developer;
467
+ this.name = "PlayAppMissing";
468
+ }
469
+ };
470
+ /** The new key could not open an edit on the app. */
471
+ var PlayKeyUnverified = class extends GkmError {
472
+ email;
473
+ detail;
474
+ constructor(email, detail) {
475
+ super(`The new key for ${email} could not open an edit on the app (${detail}). Its access can take a few minutes to reach Play: run this again shortly.`);
476
+ this.email = email;
477
+ this.detail = detail;
478
+ this.name = "PlayKeyUnverified";
479
+ }
480
+ };
481
+ /**
482
+ * The app-level permissions the service account needs: releasing to the
483
+ * testing tracks, to production only where a stage submits there, and the
484
+ * store listing where the workspace keeps one.
485
+ */
486
+ function playPermissions(options) {
487
+ return [
488
+ "CAN_MANAGE_TRACK_APKS",
489
+ ...options.tracks.includes("production") ? ["CAN_MANAGE_PUBLIC_APKS"] : [],
490
+ ...options.listing ? ["CAN_MANAGE_PUBLIC_LISTING"] : []
491
+ ].sort();
492
+ }
493
+ /**
494
+ * The service account in Play Console with exactly `permissions` on the
495
+ * app: invited with the grant in one call — Play refuses a user with no
496
+ * permission, and a grant for a user not yet there — and, already there,
497
+ * its grant made what it should be. Answers what changed.
498
+ *
499
+ * @throws {PlayAppMissing}
500
+ */
501
+ async function ensurePlayAccess(client, options) {
502
+ const { developer, email, packageName } = options;
503
+ const permissions = [...options.permissions].sort();
504
+ const users = `${PLAY}/developers/${developer}/users`;
505
+ const missing = (error) => error instanceof GoogleApiError && PACKAGE_MISSING.test(error.detail) ? new PlayAppMissing(packageName, developer) : error;
506
+ const { users: listed = [] } = await client.request("GET", `${users}?pageSize=-1`);
507
+ const user = listed.find((candidate) => candidate.email === email);
508
+ if (!user) {
509
+ await client.request("POST", users, {
510
+ email,
511
+ grants: [{
512
+ packageName,
513
+ appLevelPermissions: permissions
514
+ }]
515
+ }).catch((error) => {
516
+ throw missing(error);
517
+ });
518
+ return "invited";
519
+ }
520
+ const grant = user.grants?.find((g) => g.packageName === packageName);
521
+ const grantPath = `${users}/${encodeURIComponent(email)}/grants`;
522
+ if (!grant) {
523
+ await client.request("POST", grantPath, {
524
+ packageName,
525
+ appLevelPermissions: permissions
526
+ }).catch((error) => {
527
+ throw missing(error);
528
+ });
529
+ return "granted";
530
+ }
531
+ if ([...grant.appLevelPermissions ?? []].sort().join() === permissions.join()) return "unchanged";
532
+ await client.request("PATCH", `${grantPath}/${packageName}?updateMask=appLevelPermissions`, { appLevelPermissions: permissions });
533
+ return "updated";
534
+ }
535
+ /** An access token for the key itself: a signed JWT, exchanged. */
536
+ async function keyToken(key) {
537
+ const tokenUri = key.token_uri ?? "https://oauth2.googleapis.com/token";
538
+ const now = Math.floor(Date.now() / 1e3);
539
+ const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
540
+ const unsigned = `${encode({
541
+ alg: "RS256",
542
+ typ: "JWT"
543
+ })}.${encode({
544
+ iss: key.client_email,
545
+ scope: "https://www.googleapis.com/auth/androidpublisher",
546
+ aud: tokenUri,
547
+ iat: now,
548
+ exp: now + 600
549
+ })}`;
550
+ const signature = createSign("RSA-SHA256").update(unsigned).sign(key.private_key).toString("base64url");
551
+ const response = await fetch(tokenUri, {
552
+ method: "POST",
553
+ headers: { "content-type": "application/x-www-form-urlencoded" },
554
+ body: new URLSearchParams({
555
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
556
+ assertion: `${unsigned}.${signature}`
557
+ })
558
+ });
559
+ const body = await response.json().catch(() => ({}));
560
+ if (!response.ok || !body.access_token) throw new PlayKeyUnverified(key.client_email, body.error_description ?? `token exchange answered ${response.status}`);
561
+ return body.access_token;
562
+ }
563
+ /**
564
+ * Proof the key and its grant work: as the key, open an edit on the app and
565
+ * discard it — what EAS Submit's first call is.
566
+ *
567
+ * @throws {PlayKeyUnverified}
568
+ */
569
+ async function verifyKey(key, packageName) {
570
+ const client = googleClient(await keyToken(key));
571
+ try {
572
+ const edit = await client.request("POST", `${PLAY}/applications/${packageName}/edits`, {});
573
+ await client.request("DELETE", `${PLAY}/applications/${packageName}/edits/${edit.id}`);
574
+ } catch (error) {
575
+ if (error instanceof GoogleApiError) throw new PlayKeyUnverified(key.client_email, error.detail);
576
+ throw error;
577
+ }
578
+ }
579
+ /** The image kinds Play's listing takes, as fastlane supply names them. */
580
+ const IMAGE_TYPES = [
581
+ "icon",
582
+ "featureGraphic",
583
+ "promoGraphic",
584
+ "tvBanner",
585
+ "phoneScreenshots",
586
+ "sevenInchScreenshots",
587
+ "tenInchScreenshots",
588
+ "tvScreenshots",
589
+ "wearScreenshots"
590
+ ];
591
+ /**
592
+ * `<app>/store/play`, read: undefined where there is none.
593
+ *
594
+ * ```
595
+ * store/play/
596
+ * data-safety.csv
597
+ * listings/en-US/title.txt, short_description.txt, full_description.txt, video.txt
598
+ * listings/en-US/images/icon.png, featureGraphic.png
599
+ * listings/en-US/images/phoneScreenshots/1.png, 2.png …
600
+ * ```
601
+ */
602
+ function readPlayStore(appDir) {
603
+ const root = join(appDir, "store", "play");
604
+ if (!existsSync(root)) return void 0;
605
+ const text = (path) => existsSync(path) ? readFileSync(path, "utf8").trim() : void 0;
606
+ const listings = [];
607
+ const listingsDir = join(root, "listings");
608
+ for (const language of existsSync(listingsDir) ? readdirSync(listingsDir).sort() : []) {
609
+ const dir = join(listingsDir, language);
610
+ if (!statSync(dir).isDirectory()) continue;
611
+ const images = {};
612
+ const imagesDir = join(dir, "images");
613
+ for (const type of IMAGE_TYPES) {
614
+ const single = [
615
+ ".png",
616
+ ".jpg",
617
+ ".jpeg"
618
+ ].map((ext) => join(imagesDir, `${type}${ext}`)).find(existsSync);
619
+ const many = join(imagesDir, type);
620
+ const files = single ? [single] : existsSync(many) ? readdirSync(many).filter((f) => /\.(png|jpe?g)$/i.test(f)).sort().map((f) => join(many, f)) : [];
621
+ if (files.length > 0) images[type] = files;
622
+ }
623
+ const listing = {
624
+ language,
625
+ images
626
+ };
627
+ const title = text(join(dir, "title.txt"));
628
+ const shortDescription = text(join(dir, "short_description.txt"));
629
+ const fullDescription = text(join(dir, "full_description.txt"));
630
+ const video = text(join(dir, "video.txt"));
631
+ if (title) listing.title = title;
632
+ if (shortDescription) listing.shortDescription = shortDescription;
633
+ if (fullDescription) listing.fullDescription = fullDescription;
634
+ if (video) listing.video = video;
635
+ listings.push(listing);
636
+ }
637
+ const dataSafety = text(join(root, "data-safety.csv"));
638
+ return {
639
+ listings,
640
+ ...dataSafety ? { dataSafety } : {}
641
+ };
642
+ }
643
+ /**
644
+ * Push the listing through one edit, committed: each locale's text, and each
645
+ * image kind replaced by the files kept. Then the data safety form, which
646
+ * Play takes outside an edit. Answers whether the listing was pushed: an
647
+ * app that has never had an upload may refuse an edit, and that is left for
648
+ * the next run, not failed.
649
+ */
650
+ async function pushPlayStore(client, packageName, store) {
651
+ const app = `${PLAY}/applications/${packageName}`;
652
+ let listing = false;
653
+ let reason;
654
+ if (store.listings.length > 0) {
655
+ let edit;
656
+ try {
657
+ edit = await client.request("POST", `${app}/edits`, {});
658
+ } catch (error) {
659
+ if (!(error instanceof GoogleApiError)) throw error;
660
+ reason = error.detail;
661
+ }
662
+ if (edit) {
663
+ const base = `${app}/edits/${edit.id}/listings`;
664
+ for (const entry of store.listings) {
665
+ const { images, ...text } = entry;
666
+ if (text.title || text.shortDescription || text.fullDescription) await client.request("PUT", `${base}/${entry.language}`, text);
667
+ for (const [type, files] of Object.entries(images)) {
668
+ await client.request("DELETE", `${base}/${entry.language}/${type}`);
669
+ for (const file of files ?? []) await client.request("POST", `${PLAY_UPLOAD}/applications/${packageName}/edits/${edit.id}/listings/${entry.language}/${type}?uploadType=media`, void 0, { raw: {
670
+ contentType: extname(file).toLowerCase() === ".png" ? "image/png" : "image/jpeg",
671
+ data: readFileSync(file)
672
+ } });
673
+ }
674
+ }
675
+ await client.request("POST", `${app}/edits/${edit.id}:commit`);
676
+ listing = true;
677
+ }
678
+ }
679
+ let dataSafety = false;
680
+ if (store.dataSafety) {
681
+ await client.request("POST", `${app}/dataSafety`, { safetyLabels: store.dataSafety });
682
+ dataSafety = true;
683
+ }
684
+ return {
685
+ listing,
686
+ dataSafety,
687
+ ...reason ? { reason } : {}
688
+ };
689
+ }
690
+ /** What Play Console only takes by hand, for the person to tick off. */
691
+ const PLAY_CONSOLE_CHECKLIST = [
692
+ "App content → Privacy policy: the URL of the published policy",
693
+ "App content → App access: how a reviewer signs in",
694
+ "App content → Ads: whether the app shows ads",
695
+ "App content → Content rating: the questionnaire",
696
+ "App content → Target audience and content",
697
+ "App content → Health apps / Health Connect, where the app reads health data",
698
+ "App content → Sensitive permissions, where the app asks for any",
699
+ "Release → the first upload of a new app, by hand"
700
+ ];
701
+ //#endregion
702
+ //#region src/mobile/googlePlay/index.ts
703
+ /**
704
+ * `gkm deploy:google-play`: what EAS Submit needs to publish a `MobileApp`
705
+ * to Google Play, set up in one run — the counterpart of `gkm deploy:github`
706
+ * for the AWS side.
707
+ *
708
+ * 1. Each deployed stage's track and release status into `eas.json`
709
+ * (`submit.<stage>.android`), from `mobileStage`.
710
+ * 2. Google: the project (`--project`, else `<workspace>-play`, made when
711
+ * absent) with the Android Publisher API on, and the service account
712
+ * `<workspace>-play` in it, found or made.
713
+ * 3. Play Console: the account invited with a grant on the app alone, its
714
+ * permissions following the stages' tracks — production releases only
715
+ * when a stage submits there. An app not in Play Console yet is a step
716
+ * only a person can take; interactively, the run says so and waits.
717
+ * 4. A new JSON key, held in memory: uploaded to EAS, assigned to the app's
718
+ * Android credentials for EAS Submit, and proved by opening and
719
+ * discarding an edit with it. Only then are the account's older keys
720
+ * deleted, from EAS and from Google — a failed run leaves the old key
721
+ * working.
722
+ * 5. The store listing kept beside the app (`store/play/`), pushed.
723
+ * 6. What Play Console only takes by hand, as a checklist.
724
+ *
725
+ * Running it again rotates the key and pushes the listing.
726
+ */
727
+ const logger = console;
728
+ /** No Play developer account to act in. */
729
+ var PlayDeveloperMissing = class extends GkmError {
730
+ constructor() {
731
+ super("Name the Play developer account: --developer <id>. It is the number in Play Console's address: https://play.google.com/console/developers/<id>/….");
732
+ this.name = "PlayDeveloperMissing";
733
+ }
734
+ };
735
+ /** The app's Expo config has no Android package, or no EAS project. */
736
+ var ExpoConfigIncomplete = class extends GkmError {
737
+ app;
738
+ missing;
739
+ constructor(app, missing) {
740
+ super(missing === "android.package" ? `'${app}' has no android.package in its Expo config: Play knows an app by its package. Set it in app.config.ts: android: { package: 'com.acme.shop' }.` : `'${app}' has no extra.eas.projectId in its Expo config: it is not linked to an EAS project. Run \`eas init\` in the app.`);
741
+ this.app = app;
742
+ this.missing = missing;
743
+ this.name = "ExpoConfigIncomplete";
744
+ }
745
+ };
746
+ /** `expo config` could not read the app's config. */
747
+ var ExpoConfigFailed = class extends GkmError {
748
+ dir;
749
+ detail;
750
+ constructor(dir, detail) {
751
+ super(`Could not read the Expo config in ${dir} (${detail}). Check that \`npx expo config --json\` works there.`);
752
+ this.dir = dir;
753
+ this.detail = detail;
754
+ this.name = "ExpoConfigFailed";
755
+ }
756
+ };
757
+ /** The workspace deploys no stage. */
758
+ var NoDeployedStage = class extends GkmError {
759
+ constructor() {
760
+ super("gkm.config.ts deploys no stage, so there is nothing to publish to: add one to stages.deployed.");
761
+ this.name = "NoDeployedStage";
762
+ }
763
+ };
764
+ /** `expo config --json`, run with the app's Expo — its own, or the workspace's. */
765
+ function expoConfig(dir, root, env) {
766
+ return new Promise((resolve, reject) => {
767
+ const child = spawn("expo", [
768
+ "config",
769
+ "--json",
770
+ "--type",
771
+ "public"
772
+ ], {
773
+ cwd: dir,
774
+ stdio: [
775
+ "ignore",
776
+ "pipe",
777
+ "pipe"
778
+ ],
779
+ env: {
780
+ ...process.env,
781
+ ...env,
782
+ PATH: [
783
+ join(dir, "node_modules", ".bin"),
784
+ join(root, "node_modules", ".bin"),
785
+ process.env.PATH
786
+ ].join(delimiter)
787
+ }
788
+ });
789
+ let stdout = "";
790
+ let stderr = "";
791
+ child.stdout.on("data", (chunk) => {
792
+ stdout += chunk.toString();
793
+ });
794
+ child.stderr.on("data", (chunk) => {
795
+ stderr += chunk.toString();
796
+ });
797
+ child.on("error", (error) => reject(new ExpoConfigFailed(dir, error.message)));
798
+ child.on("close", (code) => {
799
+ if (code !== 0) {
800
+ reject(new ExpoConfigFailed(dir, stderr.trim() || `exit ${code}`));
801
+ return;
802
+ }
803
+ try {
804
+ resolve(JSON.parse(stdout));
805
+ } catch {
806
+ reject(new ExpoConfigFailed(dir, `no JSON: ${stdout.slice(0, 200)}`));
807
+ }
808
+ });
809
+ });
810
+ }
811
+ const defaultGooglePlayDeps = {
812
+ signIn: gcloudSignIn(),
813
+ eas: easApi(),
814
+ expoConfig,
815
+ interactive: canPrompt(),
816
+ sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms))
817
+ };
818
+ /**
819
+ * Set up publishing a mobile app to Google Play.
820
+ *
821
+ * @throws {PlayDeveloperMissing}, {ExpoConfigIncomplete}, {PlayAppMissing},
822
+ * {PlayKeyUnverified} — and what each step's API throws
823
+ */
824
+ async function deployGooglePlay(options, deps = defaultGooglePlayDeps) {
825
+ if (!options.developer) throw new PlayDeveloperMissing();
826
+ const developer = options.developer;
827
+ const declared = (await loadWorkspaceConfig(options.cwd)).workspace.stages;
828
+ const stageName = options.stage ?? declared.protected?.[0] ?? declared.deployed[0];
829
+ if (!stageName) throw new NoDeployedStage();
830
+ const loaded = await loadStage({
831
+ stage: stageName,
832
+ ...options.cwd ? { cwd: options.cwd } : {},
833
+ ...options.profile ? { profile: options.profile } : {}
834
+ });
835
+ const { workspace, manifest, stack } = loaded;
836
+ const declaration = chooseMobileApp(manifest, options.app, loaded.appName);
837
+ const name = declaration.id;
838
+ const dir = join(workspace.root, declaration.app.path);
839
+ const values = stack.mobileApps.find((candidate) => candidate.id === declaration.id)?.values ?? {};
840
+ const config = await deps.expoConfig(dir, workspace.root, values);
841
+ const packageName = config.android?.package;
842
+ if (!packageName) throw new ExpoConfigIncomplete(name, "android.package");
843
+ const projectId = config.extra?.eas?.projectId;
844
+ if (!projectId) throw new ExpoConfigIncomplete(name, "extra.eas.projectId");
845
+ const stages = workspace.stages.deployed.map((stage) => mobileStage(workspace, declaration, stage));
846
+ const easJsonPath = join(dir, "eas.json");
847
+ const before = existsSync(easJsonPath) ? JSON.parse(await readFile(easJsonPath, "utf8")) : {};
848
+ const after = stages.reduce(withStageProfiles, before);
849
+ if (JSON.stringify(before) !== JSON.stringify(after)) {
850
+ await writeFile(easJsonPath, `${JSON.stringify(after, null, 2)}\n`);
851
+ logger.log(`📝 ${easJsonPath}: each stage's build and submit profiles`);
852
+ }
853
+ const store = readPlayStore(dir);
854
+ const permissions = playPermissions({
855
+ tracks: stages.map((stage) => stage.android.track),
856
+ listing: (store?.listings.length ?? 0) > 0
857
+ });
858
+ const project = options.project ?? playId(workspace.name);
859
+ assertGoogleId("project", project);
860
+ const account = playId(workspace.name);
861
+ const token = await deps.signIn.token({ interactive: deps.interactive });
862
+ const created = await ensureProject(googleClient(token), project, `${workspace.name} Play`);
863
+ logger.log(`☁️ Google Cloud project ${project}${created ? " (created)" : ""}`);
864
+ const client = googleClient(token, project);
865
+ await enablePublisherApi(client, project);
866
+ const email = await ensureServiceAccount(client, project, account, `${workspace.name} publishing (gkm)`);
867
+ logger.log(`🤖 Service account ${email}`);
868
+ let access;
869
+ for (let attempt = 0; !access; attempt++) try {
870
+ access = await ensurePlayAccess(client, {
871
+ developer,
872
+ email,
873
+ packageName,
874
+ permissions
875
+ });
876
+ } catch (error) {
877
+ if (!(error instanceof PlayAppMissing) || !deps.interactive) throw error;
878
+ if (attempt === 0) logger.log(`\n⏳ ${error.message}\n Waiting for it…`);
879
+ await deps.sleep(15e3);
880
+ }
881
+ logger.log(`🎟️ Play access on ${packageName}: ${access} (${permissions.join(", ")})`);
882
+ const older = await listKeys(client, project, email);
883
+ const key = await createKey(client, project, email);
884
+ const json = JSON.parse(key.json);
885
+ const easProject = await deps.eas.project(projectId);
886
+ const credentials = await deps.eas.androidCredentials({
887
+ projectId,
888
+ fullName: easProject.fullName
889
+ }, packageName);
890
+ const easKey = await deps.eas.createKey(easProject.accountId, json);
891
+ await deps.eas.useForSubmissions(credentials.id, easKey.id);
892
+ logger.log(`🔑 New key ${keyId(key)} assigned to EAS Submit for ${packageName}`);
893
+ for (let attempt = 0;; attempt++) try {
894
+ await verifyKey(json, packageName);
895
+ break;
896
+ } catch (error) {
897
+ if (!(error instanceof PlayKeyUnverified) || attempt >= 5) throw error;
898
+ await deps.sleep(1e4);
899
+ }
900
+ logger.log("✅ The key opens an edit on the app");
901
+ const easOlder = (await deps.eas.keys(easProject.accountName)).filter((candidate) => candidate.clientEmail === email && candidate.id !== easKey.id);
902
+ for (const old of easOlder) await deps.eas.deleteKey(old.id);
903
+ for (const old of older) await deleteKey(client, old);
904
+ if (older.length + easOlder.length > 0) logger.log(`🧹 Deleted ${older.length} older key(s) from Google, ${easOlder.length} from EAS`);
905
+ const listing = store ? await pushPlayStore(client, packageName, store) : void 0;
906
+ if (listing?.listing) logger.log("🛍️ Store listing pushed");
907
+ if (store && !listing?.listing && listing?.reason) logger.log(`⏭️ Store listing not pushed yet (${listing.reason}): run this again after the app's first upload`);
908
+ if (listing?.dataSafety) logger.log("🛡️ Data safety pushed");
909
+ logger.log("\nLeft to do in Play Console, by hand:");
910
+ for (const item of PLAY_CONSOLE_CHECKLIST) logger.log(` [ ] ${item}`);
911
+ return {
912
+ packageName,
913
+ project,
914
+ email,
915
+ permissions,
916
+ access,
917
+ key: {
918
+ google: keyId(key),
919
+ eas: easKey.id
920
+ },
921
+ deleted: {
922
+ google: older.map(keyId),
923
+ eas: easOlder.map((candidate) => candidate.id)
924
+ },
925
+ listing
926
+ };
927
+ }
928
+ //#endregion
929
+ export { deployGooglePlay };
930
+
931
+ //# sourceMappingURL=googlePlay-BXJ5ZjMK.mjs.map