shipscreens 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (605) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +27 -0
  3. package/bin/shipscreens.js +664 -0
  4. package/cli/assetRefs.js +33 -0
  5. package/cli/auth.js +454 -0
  6. package/cli/buildOutputs.js +146 -0
  7. package/cli/commands/auth.js +65 -0
  8. package/cli/commands/build.js +347 -0
  9. package/cli/commands/copyImport.js +263 -0
  10. package/cli/commands/exportFramefile.js +404 -0
  11. package/cli/commands/init.js +339 -0
  12. package/cli/commands/lock.js +144 -0
  13. package/cli/commands/plan.js +203 -0
  14. package/cli/commands/stage.js +318 -0
  15. package/cli/commands/validate.js +89 -0
  16. package/cli/commands/verify.js +659 -0
  17. package/cli/commands/wizard.js +266 -0
  18. package/cli/dataUrl.js +19 -0
  19. package/cli/fastlaneZip.js +115 -0
  20. package/cli/hash.js +13 -0
  21. package/cli/loadConfig.js +55 -0
  22. package/cli/outputPaths.js +24 -0
  23. package/cli/packageRoot.js +8 -0
  24. package/cli/pathUtils.js +25 -0
  25. package/cli/rendererServer.js +48 -0
  26. package/cli/repoRoot.js +23 -0
  27. package/cli/rootPolicy.js +17 -0
  28. package/cli/schema.js +290 -0
  29. package/cli/snapshotFromConfig.js +116 -0
  30. package/cli/staticServer.js +102 -0
  31. package/cli/templateConfig.js +51 -0
  32. package/cli/viteServer.js +40 -0
  33. package/dist/app/apple-touch-icon.png +0 -0
  34. package/dist/app/assets/AgentCli-8e28laT4.js +17 -0
  35. package/dist/app/assets/AgentCli-8e28laT4.js.map +1 -0
  36. package/dist/app/assets/App-DU0xew0e.js +13 -0
  37. package/dist/app/assets/App-DU0xew0e.js.map +1 -0
  38. package/dist/app/assets/AppReviewAso-OLwc4Rw_.js +4 -0
  39. package/dist/app/assets/AppReviewAso-OLwc4Rw_.js.map +1 -0
  40. package/dist/app/assets/Cancelled-BoeZQa1S.js +2 -0
  41. package/dist/app/assets/Cancelled-BoeZQa1S.js.map +1 -0
  42. package/dist/app/assets/CliPreflightCard-CxYyogdF.js +2 -0
  43. package/dist/app/assets/CliPreflightCard-CxYyogdF.js.map +1 -0
  44. package/dist/app/assets/CopyButton-CGfuSJtU.js +2 -0
  45. package/dist/app/assets/CopyButton-CGfuSJtU.js.map +1 -0
  46. package/dist/app/assets/FastlaneScreenshots-CFT6IiRb.js +52 -0
  47. package/dist/app/assets/FastlaneScreenshots-CFT6IiRb.js.map +1 -0
  48. package/dist/app/assets/FirstExport-B_UDacZm.js +6 -0
  49. package/dist/app/assets/FirstExport-B_UDacZm.js.map +1 -0
  50. package/dist/app/assets/FivePanelFramework-C1z_xUbe.js +60 -0
  51. package/dist/app/assets/FivePanelFramework-C1z_xUbe.js.map +1 -0
  52. package/dist/app/assets/ForgotPassword-ZQ8U3ejz.js +2 -0
  53. package/dist/app/assets/ForgotPassword-ZQ8U3ejz.js.map +1 -0
  54. package/dist/app/assets/Landing-DAIP71DD.js +2 -0
  55. package/dist/app/assets/Landing-DAIP71DD.js.map +1 -0
  56. package/dist/app/assets/LanguageSwitcher-D93nCuuR.js +2 -0
  57. package/dist/app/assets/LanguageSwitcher-D93nCuuR.js.map +1 -0
  58. package/dist/app/assets/Legal-Koe7vi6H.js +2 -0
  59. package/dist/app/assets/Legal-Koe7vi6H.js.map +1 -0
  60. package/dist/app/assets/NotFound-CfY31vMZ.js +2 -0
  61. package/dist/app/assets/NotFound-CfY31vMZ.js.map +1 -0
  62. package/dist/app/assets/Pricing-BQwtFVbj.js +2 -0
  63. package/dist/app/assets/Pricing-BQwtFVbj.js.map +1 -0
  64. package/dist/app/assets/Privacy-CaHf2UM7.js +2 -0
  65. package/dist/app/assets/Privacy-CaHf2UM7.js.map +1 -0
  66. package/dist/app/assets/SignIn-Cyi2_-Mn.js +2 -0
  67. package/dist/app/assets/SignIn-Cyi2_-Mn.js.map +1 -0
  68. package/dist/app/assets/SignUp-C9QH5po_.js +2 -0
  69. package/dist/app/assets/SignUp-C9QH5po_.js.map +1 -0
  70. package/dist/app/assets/SiteHeader-Dj3gDOnR.js +2 -0
  71. package/dist/app/assets/SiteHeader-Dj3gDOnR.js.map +1 -0
  72. package/dist/app/assets/StickyMobileCta-uyWGVhdc.js +2 -0
  73. package/dist/app/assets/StickyMobileCta-uyWGVhdc.js.map +1 -0
  74. package/dist/app/assets/StoreAssetsPipeline-BJlnD3kD.js +4 -0
  75. package/dist/app/assets/StoreAssetsPipeline-BJlnD3kD.js.map +1 -0
  76. package/dist/app/assets/Success-B7k7FvJj.js +2 -0
  77. package/dist/app/assets/Success-B7k7FvJj.js.map +1 -0
  78. package/dist/app/assets/Terms-DgJWOeUD.js +2 -0
  79. package/dist/app/assets/Terms-DgJWOeUD.js.map +1 -0
  80. package/dist/app/assets/ToolsIndex-xMPoFom9.js +6 -0
  81. package/dist/app/assets/ToolsIndex-xMPoFom9.js.map +1 -0
  82. package/dist/app/assets/WorkloadCalculator-Bdt6qPR3.js +5 -0
  83. package/dist/app/assets/WorkloadCalculator-Bdt6qPR3.js.map +1 -0
  84. package/dist/app/assets/calculator-CWfp5Day.js +2 -0
  85. package/dist/app/assets/calculator-CWfp5Day.js.map +1 -0
  86. package/dist/app/assets/check-BWCiUZ-C.js +2 -0
  87. package/dist/app/assets/check-BWCiUZ-C.js.map +1 -0
  88. package/dist/app/assets/chevron-down-DbSAem1L.js +2 -0
  89. package/dist/app/assets/chevron-down-DbSAem1L.js.map +1 -0
  90. package/dist/app/assets/circle-check-CeakjiXC.js +2 -0
  91. package/dist/app/assets/circle-check-CeakjiXC.js.map +1 -0
  92. package/dist/app/assets/clipboard-copy-DgTgnK84.js +2 -0
  93. package/dist/app/assets/clipboard-copy-DgTgnK84.js.map +1 -0
  94. package/dist/app/assets/copy-C9t_FzCZ.js +2 -0
  95. package/dist/app/assets/copy-C9t_FzCZ.js.map +1 -0
  96. package/dist/app/assets/crop-B7IxIx6D.js +2 -0
  97. package/dist/app/assets/crop-B7IxIx6D.js.map +1 -0
  98. package/dist/app/assets/download-65Zuvgwm.js +2 -0
  99. package/dist/app/assets/download-65Zuvgwm.js.map +1 -0
  100. package/dist/app/assets/eye-ouNo8Nv5.js +2 -0
  101. package/dist/app/assets/eye-ouNo8Nv5.js.map +1 -0
  102. package/dist/app/assets/grid-3x3-U1Nk_ppf.js +2 -0
  103. package/dist/app/assets/grid-3x3-U1Nk_ppf.js.map +1 -0
  104. package/dist/app/assets/hero/cli-build-tree-15s.mp4 +0 -0
  105. package/dist/app/assets/hero/cli-build-tree-15s.webm +0 -0
  106. package/dist/app/assets/hero/cli-build-tree-25s.mp4 +0 -0
  107. package/dist/app/assets/hero/cli-build-tree-25s.webm +0 -0
  108. package/dist/app/assets/hero/cli-build-tree-poster.png +0 -0
  109. package/dist/app/assets/hero/demo.gif +0 -0
  110. package/dist/app/assets/hero/demo.mp4 +0 -0
  111. package/dist/app/assets/hero/demo.webm +0 -0
  112. package/dist/app/assets/icons/apple-touch-icon.png +0 -0
  113. package/dist/app/assets/icons/device-base.png +0 -0
  114. package/dist/app/assets/icons/favicon-16x16.png +0 -0
  115. package/dist/app/assets/icons/favicon-32x32.png +0 -0
  116. package/dist/app/assets/icons/favicon.ico +0 -0
  117. package/dist/app/assets/icons/favicon.svg +1 -0
  118. package/dist/app/assets/index-B8Y8Y-Mi.js +180 -0
  119. package/dist/app/assets/index-B8Y8Y-Mi.js.map +1 -0
  120. package/dist/app/assets/index-hyiQFYGv.css +1 -0
  121. package/dist/app/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  122. package/dist/app/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  123. package/dist/app/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  124. package/dist/app/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  125. package/dist/app/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
  126. package/dist/app/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  127. package/dist/app/assets/inter-cyrillic-700-normal-CjBOestx.woff2 +0 -0
  128. package/dist/app/assets/inter-cyrillic-700-normal-DrXBdSj3.woff +0 -0
  129. package/dist/app/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  130. package/dist/app/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  131. package/dist/app/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  132. package/dist/app/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  133. package/dist/app/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
  134. package/dist/app/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  135. package/dist/app/assets/inter-cyrillic-ext-700-normal-BjwYoWNd.woff2 +0 -0
  136. package/dist/app/assets/inter-cyrillic-ext-700-normal-LO58E6JB.woff +0 -0
  137. package/dist/app/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  138. package/dist/app/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  139. package/dist/app/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  140. package/dist/app/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  141. package/dist/app/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
  142. package/dist/app/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  143. package/dist/app/assets/inter-greek-700-normal-BUv2fZ6O.woff +0 -0
  144. package/dist/app/assets/inter-greek-700-normal-C3JjAnD8.woff2 +0 -0
  145. package/dist/app/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  146. package/dist/app/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  147. package/dist/app/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  148. package/dist/app/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  149. package/dist/app/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
  150. package/dist/app/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  151. package/dist/app/assets/inter-greek-ext-700-normal-BoQ6DsYi.woff +0 -0
  152. package/dist/app/assets/inter-greek-ext-700-normal-qfdV9bQt.woff2 +0 -0
  153. package/dist/app/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  154. package/dist/app/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  155. package/dist/app/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  156. package/dist/app/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  157. package/dist/app/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  158. package/dist/app/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  159. package/dist/app/assets/inter-latin-700-normal-BLAVimhd.woff +0 -0
  160. package/dist/app/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  161. package/dist/app/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  162. package/dist/app/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  163. package/dist/app/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  164. package/dist/app/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  165. package/dist/app/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
  166. package/dist/app/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  167. package/dist/app/assets/inter-latin-ext-700-normal-Ca8adRJv.woff2 +0 -0
  168. package/dist/app/assets/inter-latin-ext-700-normal-TidjK2hL.woff +0 -0
  169. package/dist/app/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  170. package/dist/app/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  171. package/dist/app/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  172. package/dist/app/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  173. package/dist/app/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
  174. package/dist/app/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  175. package/dist/app/assets/inter-vietnamese-700-normal-BZaoP0fm.woff +0 -0
  176. package/dist/app/assets/inter-vietnamese-700-normal-DlLaEgI2.woff2 +0 -0
  177. package/dist/app/assets/layout-grid-X9Sgull2.js +2 -0
  178. package/dist/app/assets/layout-grid-X9Sgull2.js.map +1 -0
  179. package/dist/app/assets/merriweather-cyrillic-400-normal-AvfsDsMQ.woff2 +0 -0
  180. package/dist/app/assets/merriweather-cyrillic-400-normal-DAcQ8g-H.woff +0 -0
  181. package/dist/app/assets/merriweather-cyrillic-700-normal-CHCcU-4a.woff +0 -0
  182. package/dist/app/assets/merriweather-cyrillic-700-normal-wbY04GlL.woff2 +0 -0
  183. package/dist/app/assets/merriweather-cyrillic-ext-400-normal-D9NYhYTq.woff2 +0 -0
  184. package/dist/app/assets/merriweather-cyrillic-ext-400-normal-Di6yW_eE.woff +0 -0
  185. package/dist/app/assets/merriweather-cyrillic-ext-700-normal-Bk1p9YoV.woff2 +0 -0
  186. package/dist/app/assets/merriweather-cyrillic-ext-700-normal-DoooT6Vg.woff +0 -0
  187. package/dist/app/assets/merriweather-latin-400-normal-CvqO63Ah.woff +0 -0
  188. package/dist/app/assets/merriweather-latin-400-normal-G4kZaoXi.woff2 +0 -0
  189. package/dist/app/assets/merriweather-latin-700-normal-D4-nzrAh.woff +0 -0
  190. package/dist/app/assets/merriweather-latin-700-normal-DoUP8Ce-.woff2 +0 -0
  191. package/dist/app/assets/merriweather-latin-ext-400-normal-CLqijLtt.woff +0 -0
  192. package/dist/app/assets/merriweather-latin-ext-400-normal-CWVzVQq3.woff2 +0 -0
  193. package/dist/app/assets/merriweather-latin-ext-700-normal-CaBzXGOk.woff +0 -0
  194. package/dist/app/assets/merriweather-latin-ext-700-normal-jHnxg2Kc.woff2 +0 -0
  195. package/dist/app/assets/merriweather-vietnamese-400-normal-Dh8WVvgZ.woff +0 -0
  196. package/dist/app/assets/merriweather-vietnamese-400-normal-hNacsVs_.woff2 +0 -0
  197. package/dist/app/assets/merriweather-vietnamese-700-normal-Bp6kWjW5.woff2 +0 -0
  198. package/dist/app/assets/merriweather-vietnamese-700-normal-C7_HxHBa.woff +0 -0
  199. package/dist/app/assets/montserrat-cyrillic-400-normal-BPq32Q8K.woff2 +0 -0
  200. package/dist/app/assets/montserrat-cyrillic-400-normal-jEs4Tk-Z.woff +0 -0
  201. package/dist/app/assets/montserrat-cyrillic-700-normal-BvLYcGP1.woff +0 -0
  202. package/dist/app/assets/montserrat-cyrillic-700-normal-D-Pqjtdp.woff2 +0 -0
  203. package/dist/app/assets/montserrat-cyrillic-ext-400-normal-DRPPeomZ.woff +0 -0
  204. package/dist/app/assets/montserrat-cyrillic-ext-400-normal-Xqov12YL.woff2 +0 -0
  205. package/dist/app/assets/montserrat-cyrillic-ext-700-normal-D-Mk2xRJ.woff +0 -0
  206. package/dist/app/assets/montserrat-cyrillic-ext-700-normal-MyDreaeu.woff2 +0 -0
  207. package/dist/app/assets/montserrat-latin-400-normal-BLhwKU8k.woff2 +0 -0
  208. package/dist/app/assets/montserrat-latin-400-normal-xItZbAXg.woff +0 -0
  209. package/dist/app/assets/montserrat-latin-700-normal-BWkrl476.woff +0 -0
  210. package/dist/app/assets/montserrat-latin-700-normal-BdjcYUrC.woff2 +0 -0
  211. package/dist/app/assets/montserrat-latin-ext-400-normal-B8bwfy6Y.woff2 +0 -0
  212. package/dist/app/assets/montserrat-latin-ext-400-normal-BffdBkAA.woff +0 -0
  213. package/dist/app/assets/montserrat-latin-ext-700-normal-BOP2Nhf0.woff2 +0 -0
  214. package/dist/app/assets/montserrat-latin-ext-700-normal-DdDFr05Z.woff +0 -0
  215. package/dist/app/assets/montserrat-vietnamese-400-normal-BeEscFYY.woff +0 -0
  216. package/dist/app/assets/montserrat-vietnamese-400-normal-D4oHqQTd.woff2 +0 -0
  217. package/dist/app/assets/montserrat-vietnamese-700-normal-C0x1De3p.woff2 +0 -0
  218. package/dist/app/assets/montserrat-vietnamese-700-normal-DnwGT2D9.woff +0 -0
  219. package/dist/app/assets/playfair-display-cyrillic-400-normal-CjW2EstV.woff2 +0 -0
  220. package/dist/app/assets/playfair-display-cyrillic-400-normal-ZiRag6zj.woff +0 -0
  221. package/dist/app/assets/playfair-display-cyrillic-700-normal-Dk1mTcxf.woff +0 -0
  222. package/dist/app/assets/playfair-display-cyrillic-700-normal-Dw3uKy19.woff2 +0 -0
  223. package/dist/app/assets/playfair-display-latin-400-normal-CFtfchNt.woff2 +0 -0
  224. package/dist/app/assets/playfair-display-latin-400-normal-DHYHbkg3.woff +0 -0
  225. package/dist/app/assets/playfair-display-latin-700-normal-Bc_1Q1cG.woff +0 -0
  226. package/dist/app/assets/playfair-display-latin-700-normal-CuDiGg7c.woff2 +0 -0
  227. package/dist/app/assets/playfair-display-latin-ext-400-normal-BxlSGspa.woff2 +0 -0
  228. package/dist/app/assets/playfair-display-latin-ext-400-normal-qdZwdvNS.woff +0 -0
  229. package/dist/app/assets/playfair-display-latin-ext-700-normal-C58ejOkc.woff2 +0 -0
  230. package/dist/app/assets/playfair-display-latin-ext-700-normal-D5HUU8GT.woff +0 -0
  231. package/dist/app/assets/playfair-display-vietnamese-400-normal-BV2APVTb.woff2 +0 -0
  232. package/dist/app/assets/playfair-display-vietnamese-400-normal-BbvUAu4N.woff +0 -0
  233. package/dist/app/assets/playfair-display-vietnamese-700-normal-CaKJSIny.woff2 +0 -0
  234. package/dist/app/assets/playfair-display-vietnamese-700-normal-Cr1rw0mr.woff +0 -0
  235. package/dist/app/assets/proof/output-01.png +0 -0
  236. package/dist/app/assets/proof/output-02.png +0 -0
  237. package/dist/app/assets/proof/output-03.png +0 -0
  238. package/dist/app/assets/proof/output-04.png +0 -0
  239. package/dist/app/assets/roboto-cyrillic-400-normal-DAIM1_dR.woff2 +0 -0
  240. package/dist/app/assets/roboto-cyrillic-400-normal-DZJji7Rx.woff +0 -0
  241. package/dist/app/assets/roboto-cyrillic-500-normal-BI4HuXre.woff +0 -0
  242. package/dist/app/assets/roboto-cyrillic-500-normal-hCeO1jFL.woff2 +0 -0
  243. package/dist/app/assets/roboto-cyrillic-700-normal-BiSG5NnW.woff2 +0 -0
  244. package/dist/app/assets/roboto-cyrillic-700-normal-KqaQ5bNp.woff +0 -0
  245. package/dist/app/assets/roboto-cyrillic-ext-400-normal-DtZHuW6i.woff +0 -0
  246. package/dist/app/assets/roboto-cyrillic-ext-400-normal-DzMWdK87.woff2 +0 -0
  247. package/dist/app/assets/roboto-cyrillic-ext-500-normal-B7rQpwPu.woff2 +0 -0
  248. package/dist/app/assets/roboto-cyrillic-ext-500-normal-C927yMrb.woff +0 -0
  249. package/dist/app/assets/roboto-cyrillic-ext-700-normal-BuQgZIrO.woff +0 -0
  250. package/dist/app/assets/roboto-cyrillic-ext-700-normal-UFn0vR9r.woff2 +0 -0
  251. package/dist/app/assets/roboto-greek-400-normal-CcizSnRP.woff +0 -0
  252. package/dist/app/assets/roboto-greek-400-normal-jFM2czAU.woff2 +0 -0
  253. package/dist/app/assets/roboto-greek-500-normal-BJMS0heP.woff2 +0 -0
  254. package/dist/app/assets/roboto-greek-500-normal-BLLWU9W-.woff +0 -0
  255. package/dist/app/assets/roboto-greek-700-normal-BcGn9doz.woff2 +0 -0
  256. package/dist/app/assets/roboto-greek-700-normal-D3kmAf0K.woff +0 -0
  257. package/dist/app/assets/roboto-latin-400-normal-068yxgMN.woff +0 -0
  258. package/dist/app/assets/roboto-latin-400-normal-CNwBRw8h.woff2 +0 -0
  259. package/dist/app/assets/roboto-latin-500-normal-CC5nhZkh.woff +0 -0
  260. package/dist/app/assets/roboto-latin-500-normal-CkrA1NAy.woff2 +0 -0
  261. package/dist/app/assets/roboto-latin-700-normal-CXeAXeti.woff2 +0 -0
  262. package/dist/app/assets/roboto-latin-700-normal-DUekQERp.woff +0 -0
  263. package/dist/app/assets/roboto-latin-ext-400-normal-ZYmyxeOy.woff2 +0 -0
  264. package/dist/app/assets/roboto-latin-ext-400-normal-eTRLN0Nt.woff +0 -0
  265. package/dist/app/assets/roboto-latin-ext-500-normal-C_ARlJGk.woff2 +0 -0
  266. package/dist/app/assets/roboto-latin-ext-500-normal-FFcS8vBN.woff +0 -0
  267. package/dist/app/assets/roboto-latin-ext-700-normal-70GS1MYH.woff2 +0 -0
  268. package/dist/app/assets/roboto-latin-ext-700-normal-BS1OuQqR.woff +0 -0
  269. package/dist/app/assets/roboto-math-400-normal-B3wgz80t.woff2 +0 -0
  270. package/dist/app/assets/roboto-math-400-normal-rzxYvyVt.woff +0 -0
  271. package/dist/app/assets/roboto-math-500-normal-CFNaIMFC.woff2 +0 -0
  272. package/dist/app/assets/roboto-math-500-normal-DaFX-ZC8.woff +0 -0
  273. package/dist/app/assets/roboto-math-700-normal-VUAI6Bz2.woff2 +0 -0
  274. package/dist/app/assets/roboto-math-700-normal-pYD1nhov.woff +0 -0
  275. package/dist/app/assets/roboto-symbols-400-normal-Tzuungub.woff +0 -0
  276. package/dist/app/assets/roboto-symbols-400-normal-fF1SLJBj.woff2 +0 -0
  277. package/dist/app/assets/roboto-symbols-500-normal-BXFTxrNR.woff2 +0 -0
  278. package/dist/app/assets/roboto-symbols-500-normal-CAhAe-ik.woff +0 -0
  279. package/dist/app/assets/roboto-symbols-700-normal-CuuvBBxy.woff +0 -0
  280. package/dist/app/assets/roboto-symbols-700-normal-rJi6RjIy.woff2 +0 -0
  281. package/dist/app/assets/roboto-vietnamese-400-normal-CDDxGrUb.woff2 +0 -0
  282. package/dist/app/assets/roboto-vietnamese-400-normal-DmXaN3yE.woff +0 -0
  283. package/dist/app/assets/roboto-vietnamese-500-normal-DW96CsrR.woff +0 -0
  284. package/dist/app/assets/roboto-vietnamese-500-normal-HYpufUYk.woff2 +0 -0
  285. package/dist/app/assets/roboto-vietnamese-700-normal-Dz0HwF-w.woff +0 -0
  286. package/dist/app/assets/roboto-vietnamese-700-normal-iKxYNAzq.woff2 +0 -0
  287. package/dist/app/assets/rocket-BjOXauLe.js +2 -0
  288. package/dist/app/assets/rocket-BjOXauLe.js.map +1 -0
  289. package/dist/app/assets/shield-check-CFNhE_aD.js +2 -0
  290. package/dist/app/assets/shield-check-CFNhE_aD.js.map +1 -0
  291. package/dist/app/assets/signIn-CVoSzqCz.js +2 -0
  292. package/dist/app/assets/signIn-CVoSzqCz.js.map +1 -0
  293. package/dist/app/assets/smartphone-BcQB9gIh.js +2 -0
  294. package/dist/app/assets/smartphone-BcQB9gIh.js.map +1 -0
  295. package/dist/app/assets/terminal-CGhryJds.js +2 -0
  296. package/dist/app/assets/terminal-CGhryJds.js.map +1 -0
  297. package/dist/app/assets/useAuth-lZZC20Tl.js +4 -0
  298. package/dist/app/assets/useAuth-lZZC20Tl.js.map +1 -0
  299. package/dist/app/favicon-16x16.png +0 -0
  300. package/dist/app/favicon-32x32.png +0 -0
  301. package/dist/app/favicon.ico +0 -0
  302. package/dist/app/favicon.svg +10 -0
  303. package/dist/app/index.html +43 -0
  304. package/dist/apple-touch-icon.png +0 -0
  305. package/dist/assets/AgentCli-8e28laT4.js +17 -0
  306. package/dist/assets/AgentCli-8e28laT4.js.map +1 -0
  307. package/dist/assets/App-DU0xew0e.js +13 -0
  308. package/dist/assets/App-DU0xew0e.js.map +1 -0
  309. package/dist/assets/AppReviewAso-OLwc4Rw_.js +4 -0
  310. package/dist/assets/AppReviewAso-OLwc4Rw_.js.map +1 -0
  311. package/dist/assets/Cancelled-BoeZQa1S.js +2 -0
  312. package/dist/assets/Cancelled-BoeZQa1S.js.map +1 -0
  313. package/dist/assets/CliPreflightCard-CxYyogdF.js +2 -0
  314. package/dist/assets/CliPreflightCard-CxYyogdF.js.map +1 -0
  315. package/dist/assets/CopyButton-CGfuSJtU.js +2 -0
  316. package/dist/assets/CopyButton-CGfuSJtU.js.map +1 -0
  317. package/dist/assets/FastlaneScreenshots-CFT6IiRb.js +52 -0
  318. package/dist/assets/FastlaneScreenshots-CFT6IiRb.js.map +1 -0
  319. package/dist/assets/FirstExport-B_UDacZm.js +6 -0
  320. package/dist/assets/FirstExport-B_UDacZm.js.map +1 -0
  321. package/dist/assets/FivePanelFramework-C1z_xUbe.js +60 -0
  322. package/dist/assets/FivePanelFramework-C1z_xUbe.js.map +1 -0
  323. package/dist/assets/ForgotPassword-ZQ8U3ejz.js +2 -0
  324. package/dist/assets/ForgotPassword-ZQ8U3ejz.js.map +1 -0
  325. package/dist/assets/Landing-DAIP71DD.js +2 -0
  326. package/dist/assets/Landing-DAIP71DD.js.map +1 -0
  327. package/dist/assets/LanguageSwitcher-D93nCuuR.js +2 -0
  328. package/dist/assets/LanguageSwitcher-D93nCuuR.js.map +1 -0
  329. package/dist/assets/Legal-Koe7vi6H.js +2 -0
  330. package/dist/assets/Legal-Koe7vi6H.js.map +1 -0
  331. package/dist/assets/NotFound-CfY31vMZ.js +2 -0
  332. package/dist/assets/NotFound-CfY31vMZ.js.map +1 -0
  333. package/dist/assets/Pricing-BQwtFVbj.js +2 -0
  334. package/dist/assets/Pricing-BQwtFVbj.js.map +1 -0
  335. package/dist/assets/Privacy-CaHf2UM7.js +2 -0
  336. package/dist/assets/Privacy-CaHf2UM7.js.map +1 -0
  337. package/dist/assets/SignIn-Cyi2_-Mn.js +2 -0
  338. package/dist/assets/SignIn-Cyi2_-Mn.js.map +1 -0
  339. package/dist/assets/SignUp-C9QH5po_.js +2 -0
  340. package/dist/assets/SignUp-C9QH5po_.js.map +1 -0
  341. package/dist/assets/SiteHeader-Dj3gDOnR.js +2 -0
  342. package/dist/assets/SiteHeader-Dj3gDOnR.js.map +1 -0
  343. package/dist/assets/StickyMobileCta-uyWGVhdc.js +2 -0
  344. package/dist/assets/StickyMobileCta-uyWGVhdc.js.map +1 -0
  345. package/dist/assets/StoreAssetsPipeline-BJlnD3kD.js +4 -0
  346. package/dist/assets/StoreAssetsPipeline-BJlnD3kD.js.map +1 -0
  347. package/dist/assets/Success-B7k7FvJj.js +2 -0
  348. package/dist/assets/Success-B7k7FvJj.js.map +1 -0
  349. package/dist/assets/Terms-DgJWOeUD.js +2 -0
  350. package/dist/assets/Terms-DgJWOeUD.js.map +1 -0
  351. package/dist/assets/ToolsIndex-xMPoFom9.js +6 -0
  352. package/dist/assets/ToolsIndex-xMPoFom9.js.map +1 -0
  353. package/dist/assets/WorkloadCalculator-Bdt6qPR3.js +5 -0
  354. package/dist/assets/WorkloadCalculator-Bdt6qPR3.js.map +1 -0
  355. package/dist/assets/calculator-CWfp5Day.js +2 -0
  356. package/dist/assets/calculator-CWfp5Day.js.map +1 -0
  357. package/dist/assets/check-BWCiUZ-C.js +2 -0
  358. package/dist/assets/check-BWCiUZ-C.js.map +1 -0
  359. package/dist/assets/chevron-down-DbSAem1L.js +2 -0
  360. package/dist/assets/chevron-down-DbSAem1L.js.map +1 -0
  361. package/dist/assets/circle-check-CeakjiXC.js +2 -0
  362. package/dist/assets/circle-check-CeakjiXC.js.map +1 -0
  363. package/dist/assets/clipboard-copy-DgTgnK84.js +2 -0
  364. package/dist/assets/clipboard-copy-DgTgnK84.js.map +1 -0
  365. package/dist/assets/copy-C9t_FzCZ.js +2 -0
  366. package/dist/assets/copy-C9t_FzCZ.js.map +1 -0
  367. package/dist/assets/crop-B7IxIx6D.js +2 -0
  368. package/dist/assets/crop-B7IxIx6D.js.map +1 -0
  369. package/dist/assets/download-65Zuvgwm.js +2 -0
  370. package/dist/assets/download-65Zuvgwm.js.map +1 -0
  371. package/dist/assets/eye-ouNo8Nv5.js +2 -0
  372. package/dist/assets/eye-ouNo8Nv5.js.map +1 -0
  373. package/dist/assets/grid-3x3-U1Nk_ppf.js +2 -0
  374. package/dist/assets/grid-3x3-U1Nk_ppf.js.map +1 -0
  375. package/dist/assets/hero/cli-build-tree-15s.mp4 +0 -0
  376. package/dist/assets/hero/cli-build-tree-15s.webm +0 -0
  377. package/dist/assets/hero/cli-build-tree-25s.mp4 +0 -0
  378. package/dist/assets/hero/cli-build-tree-25s.webm +0 -0
  379. package/dist/assets/hero/cli-build-tree-poster.png +0 -0
  380. package/dist/assets/hero/demo.gif +0 -0
  381. package/dist/assets/hero/demo.mp4 +0 -0
  382. package/dist/assets/hero/demo.webm +0 -0
  383. package/dist/assets/icons/apple-touch-icon.png +0 -0
  384. package/dist/assets/icons/device-base.png +0 -0
  385. package/dist/assets/icons/favicon-16x16.png +0 -0
  386. package/dist/assets/icons/favicon-32x32.png +0 -0
  387. package/dist/assets/icons/favicon.ico +0 -0
  388. package/dist/assets/icons/favicon.svg +1 -0
  389. package/dist/assets/index-B8Y8Y-Mi.js +180 -0
  390. package/dist/assets/index-B8Y8Y-Mi.js.map +1 -0
  391. package/dist/assets/index-hyiQFYGv.css +1 -0
  392. package/dist/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  393. package/dist/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  394. package/dist/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  395. package/dist/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  396. package/dist/assets/inter-cyrillic-600-normal-4D_pXhcN.woff +0 -0
  397. package/dist/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  398. package/dist/assets/inter-cyrillic-700-normal-CjBOestx.woff2 +0 -0
  399. package/dist/assets/inter-cyrillic-700-normal-DrXBdSj3.woff +0 -0
  400. package/dist/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  401. package/dist/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  402. package/dist/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  403. package/dist/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  404. package/dist/assets/inter-cyrillic-ext-600-normal-Bcila6Z-.woff +0 -0
  405. package/dist/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  406. package/dist/assets/inter-cyrillic-ext-700-normal-BjwYoWNd.woff2 +0 -0
  407. package/dist/assets/inter-cyrillic-ext-700-normal-LO58E6JB.woff +0 -0
  408. package/dist/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  409. package/dist/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  410. package/dist/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  411. package/dist/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  412. package/dist/assets/inter-greek-600-normal-BZpKdvQh.woff +0 -0
  413. package/dist/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  414. package/dist/assets/inter-greek-700-normal-BUv2fZ6O.woff +0 -0
  415. package/dist/assets/inter-greek-700-normal-C3JjAnD8.woff2 +0 -0
  416. package/dist/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  417. package/dist/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  418. package/dist/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  419. package/dist/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  420. package/dist/assets/inter-greek-ext-600-normal-B8X0CLgF.woff +0 -0
  421. package/dist/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  422. package/dist/assets/inter-greek-ext-700-normal-BoQ6DsYi.woff +0 -0
  423. package/dist/assets/inter-greek-ext-700-normal-qfdV9bQt.woff2 +0 -0
  424. package/dist/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  425. package/dist/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  426. package/dist/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  427. package/dist/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  428. package/dist/assets/inter-latin-600-normal-CiBQ2DWP.woff +0 -0
  429. package/dist/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  430. package/dist/assets/inter-latin-700-normal-BLAVimhd.woff +0 -0
  431. package/dist/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  432. package/dist/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  433. package/dist/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  434. package/dist/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  435. package/dist/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  436. package/dist/assets/inter-latin-ext-600-normal-CIVaiw4L.woff +0 -0
  437. package/dist/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  438. package/dist/assets/inter-latin-ext-700-normal-Ca8adRJv.woff2 +0 -0
  439. package/dist/assets/inter-latin-ext-700-normal-TidjK2hL.woff +0 -0
  440. package/dist/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  441. package/dist/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  442. package/dist/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  443. package/dist/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  444. package/dist/assets/inter-vietnamese-600-normal-BuLX-rYi.woff +0 -0
  445. package/dist/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  446. package/dist/assets/inter-vietnamese-700-normal-BZaoP0fm.woff +0 -0
  447. package/dist/assets/inter-vietnamese-700-normal-DlLaEgI2.woff2 +0 -0
  448. package/dist/assets/layout-grid-X9Sgull2.js +2 -0
  449. package/dist/assets/layout-grid-X9Sgull2.js.map +1 -0
  450. package/dist/assets/merriweather-cyrillic-400-normal-AvfsDsMQ.woff2 +0 -0
  451. package/dist/assets/merriweather-cyrillic-400-normal-DAcQ8g-H.woff +0 -0
  452. package/dist/assets/merriweather-cyrillic-700-normal-CHCcU-4a.woff +0 -0
  453. package/dist/assets/merriweather-cyrillic-700-normal-wbY04GlL.woff2 +0 -0
  454. package/dist/assets/merriweather-cyrillic-ext-400-normal-D9NYhYTq.woff2 +0 -0
  455. package/dist/assets/merriweather-cyrillic-ext-400-normal-Di6yW_eE.woff +0 -0
  456. package/dist/assets/merriweather-cyrillic-ext-700-normal-Bk1p9YoV.woff2 +0 -0
  457. package/dist/assets/merriweather-cyrillic-ext-700-normal-DoooT6Vg.woff +0 -0
  458. package/dist/assets/merriweather-latin-400-normal-CvqO63Ah.woff +0 -0
  459. package/dist/assets/merriweather-latin-400-normal-G4kZaoXi.woff2 +0 -0
  460. package/dist/assets/merriweather-latin-700-normal-D4-nzrAh.woff +0 -0
  461. package/dist/assets/merriweather-latin-700-normal-DoUP8Ce-.woff2 +0 -0
  462. package/dist/assets/merriweather-latin-ext-400-normal-CLqijLtt.woff +0 -0
  463. package/dist/assets/merriweather-latin-ext-400-normal-CWVzVQq3.woff2 +0 -0
  464. package/dist/assets/merriweather-latin-ext-700-normal-CaBzXGOk.woff +0 -0
  465. package/dist/assets/merriweather-latin-ext-700-normal-jHnxg2Kc.woff2 +0 -0
  466. package/dist/assets/merriweather-vietnamese-400-normal-Dh8WVvgZ.woff +0 -0
  467. package/dist/assets/merriweather-vietnamese-400-normal-hNacsVs_.woff2 +0 -0
  468. package/dist/assets/merriweather-vietnamese-700-normal-Bp6kWjW5.woff2 +0 -0
  469. package/dist/assets/merriweather-vietnamese-700-normal-C7_HxHBa.woff +0 -0
  470. package/dist/assets/montserrat-cyrillic-400-normal-BPq32Q8K.woff2 +0 -0
  471. package/dist/assets/montserrat-cyrillic-400-normal-jEs4Tk-Z.woff +0 -0
  472. package/dist/assets/montserrat-cyrillic-700-normal-BvLYcGP1.woff +0 -0
  473. package/dist/assets/montserrat-cyrillic-700-normal-D-Pqjtdp.woff2 +0 -0
  474. package/dist/assets/montserrat-cyrillic-ext-400-normal-DRPPeomZ.woff +0 -0
  475. package/dist/assets/montserrat-cyrillic-ext-400-normal-Xqov12YL.woff2 +0 -0
  476. package/dist/assets/montserrat-cyrillic-ext-700-normal-D-Mk2xRJ.woff +0 -0
  477. package/dist/assets/montserrat-cyrillic-ext-700-normal-MyDreaeu.woff2 +0 -0
  478. package/dist/assets/montserrat-latin-400-normal-BLhwKU8k.woff2 +0 -0
  479. package/dist/assets/montserrat-latin-400-normal-xItZbAXg.woff +0 -0
  480. package/dist/assets/montserrat-latin-700-normal-BWkrl476.woff +0 -0
  481. package/dist/assets/montserrat-latin-700-normal-BdjcYUrC.woff2 +0 -0
  482. package/dist/assets/montserrat-latin-ext-400-normal-B8bwfy6Y.woff2 +0 -0
  483. package/dist/assets/montserrat-latin-ext-400-normal-BffdBkAA.woff +0 -0
  484. package/dist/assets/montserrat-latin-ext-700-normal-BOP2Nhf0.woff2 +0 -0
  485. package/dist/assets/montserrat-latin-ext-700-normal-DdDFr05Z.woff +0 -0
  486. package/dist/assets/montserrat-vietnamese-400-normal-BeEscFYY.woff +0 -0
  487. package/dist/assets/montserrat-vietnamese-400-normal-D4oHqQTd.woff2 +0 -0
  488. package/dist/assets/montserrat-vietnamese-700-normal-C0x1De3p.woff2 +0 -0
  489. package/dist/assets/montserrat-vietnamese-700-normal-DnwGT2D9.woff +0 -0
  490. package/dist/assets/playfair-display-cyrillic-400-normal-CjW2EstV.woff2 +0 -0
  491. package/dist/assets/playfair-display-cyrillic-400-normal-ZiRag6zj.woff +0 -0
  492. package/dist/assets/playfair-display-cyrillic-700-normal-Dk1mTcxf.woff +0 -0
  493. package/dist/assets/playfair-display-cyrillic-700-normal-Dw3uKy19.woff2 +0 -0
  494. package/dist/assets/playfair-display-latin-400-normal-CFtfchNt.woff2 +0 -0
  495. package/dist/assets/playfair-display-latin-400-normal-DHYHbkg3.woff +0 -0
  496. package/dist/assets/playfair-display-latin-700-normal-Bc_1Q1cG.woff +0 -0
  497. package/dist/assets/playfair-display-latin-700-normal-CuDiGg7c.woff2 +0 -0
  498. package/dist/assets/playfair-display-latin-ext-400-normal-BxlSGspa.woff2 +0 -0
  499. package/dist/assets/playfair-display-latin-ext-400-normal-qdZwdvNS.woff +0 -0
  500. package/dist/assets/playfair-display-latin-ext-700-normal-C58ejOkc.woff2 +0 -0
  501. package/dist/assets/playfair-display-latin-ext-700-normal-D5HUU8GT.woff +0 -0
  502. package/dist/assets/playfair-display-vietnamese-400-normal-BV2APVTb.woff2 +0 -0
  503. package/dist/assets/playfair-display-vietnamese-400-normal-BbvUAu4N.woff +0 -0
  504. package/dist/assets/playfair-display-vietnamese-700-normal-CaKJSIny.woff2 +0 -0
  505. package/dist/assets/playfair-display-vietnamese-700-normal-Cr1rw0mr.woff +0 -0
  506. package/dist/assets/proof/output-01.png +0 -0
  507. package/dist/assets/proof/output-02.png +0 -0
  508. package/dist/assets/proof/output-03.png +0 -0
  509. package/dist/assets/proof/output-04.png +0 -0
  510. package/dist/assets/roboto-cyrillic-400-normal-DAIM1_dR.woff2 +0 -0
  511. package/dist/assets/roboto-cyrillic-400-normal-DZJji7Rx.woff +0 -0
  512. package/dist/assets/roboto-cyrillic-500-normal-BI4HuXre.woff +0 -0
  513. package/dist/assets/roboto-cyrillic-500-normal-hCeO1jFL.woff2 +0 -0
  514. package/dist/assets/roboto-cyrillic-700-normal-BiSG5NnW.woff2 +0 -0
  515. package/dist/assets/roboto-cyrillic-700-normal-KqaQ5bNp.woff +0 -0
  516. package/dist/assets/roboto-cyrillic-ext-400-normal-DtZHuW6i.woff +0 -0
  517. package/dist/assets/roboto-cyrillic-ext-400-normal-DzMWdK87.woff2 +0 -0
  518. package/dist/assets/roboto-cyrillic-ext-500-normal-B7rQpwPu.woff2 +0 -0
  519. package/dist/assets/roboto-cyrillic-ext-500-normal-C927yMrb.woff +0 -0
  520. package/dist/assets/roboto-cyrillic-ext-700-normal-BuQgZIrO.woff +0 -0
  521. package/dist/assets/roboto-cyrillic-ext-700-normal-UFn0vR9r.woff2 +0 -0
  522. package/dist/assets/roboto-greek-400-normal-CcizSnRP.woff +0 -0
  523. package/dist/assets/roboto-greek-400-normal-jFM2czAU.woff2 +0 -0
  524. package/dist/assets/roboto-greek-500-normal-BJMS0heP.woff2 +0 -0
  525. package/dist/assets/roboto-greek-500-normal-BLLWU9W-.woff +0 -0
  526. package/dist/assets/roboto-greek-700-normal-BcGn9doz.woff2 +0 -0
  527. package/dist/assets/roboto-greek-700-normal-D3kmAf0K.woff +0 -0
  528. package/dist/assets/roboto-latin-400-normal-068yxgMN.woff +0 -0
  529. package/dist/assets/roboto-latin-400-normal-CNwBRw8h.woff2 +0 -0
  530. package/dist/assets/roboto-latin-500-normal-CC5nhZkh.woff +0 -0
  531. package/dist/assets/roboto-latin-500-normal-CkrA1NAy.woff2 +0 -0
  532. package/dist/assets/roboto-latin-700-normal-CXeAXeti.woff2 +0 -0
  533. package/dist/assets/roboto-latin-700-normal-DUekQERp.woff +0 -0
  534. package/dist/assets/roboto-latin-ext-400-normal-ZYmyxeOy.woff2 +0 -0
  535. package/dist/assets/roboto-latin-ext-400-normal-eTRLN0Nt.woff +0 -0
  536. package/dist/assets/roboto-latin-ext-500-normal-C_ARlJGk.woff2 +0 -0
  537. package/dist/assets/roboto-latin-ext-500-normal-FFcS8vBN.woff +0 -0
  538. package/dist/assets/roboto-latin-ext-700-normal-70GS1MYH.woff2 +0 -0
  539. package/dist/assets/roboto-latin-ext-700-normal-BS1OuQqR.woff +0 -0
  540. package/dist/assets/roboto-math-400-normal-B3wgz80t.woff2 +0 -0
  541. package/dist/assets/roboto-math-400-normal-rzxYvyVt.woff +0 -0
  542. package/dist/assets/roboto-math-500-normal-CFNaIMFC.woff2 +0 -0
  543. package/dist/assets/roboto-math-500-normal-DaFX-ZC8.woff +0 -0
  544. package/dist/assets/roboto-math-700-normal-VUAI6Bz2.woff2 +0 -0
  545. package/dist/assets/roboto-math-700-normal-pYD1nhov.woff +0 -0
  546. package/dist/assets/roboto-symbols-400-normal-Tzuungub.woff +0 -0
  547. package/dist/assets/roboto-symbols-400-normal-fF1SLJBj.woff2 +0 -0
  548. package/dist/assets/roboto-symbols-500-normal-BXFTxrNR.woff2 +0 -0
  549. package/dist/assets/roboto-symbols-500-normal-CAhAe-ik.woff +0 -0
  550. package/dist/assets/roboto-symbols-700-normal-CuuvBBxy.woff +0 -0
  551. package/dist/assets/roboto-symbols-700-normal-rJi6RjIy.woff2 +0 -0
  552. package/dist/assets/roboto-vietnamese-400-normal-CDDxGrUb.woff2 +0 -0
  553. package/dist/assets/roboto-vietnamese-400-normal-DmXaN3yE.woff +0 -0
  554. package/dist/assets/roboto-vietnamese-500-normal-DW96CsrR.woff +0 -0
  555. package/dist/assets/roboto-vietnamese-500-normal-HYpufUYk.woff2 +0 -0
  556. package/dist/assets/roboto-vietnamese-700-normal-Dz0HwF-w.woff +0 -0
  557. package/dist/assets/roboto-vietnamese-700-normal-iKxYNAzq.woff2 +0 -0
  558. package/dist/assets/rocket-BjOXauLe.js +2 -0
  559. package/dist/assets/rocket-BjOXauLe.js.map +1 -0
  560. package/dist/assets/shield-check-CFNhE_aD.js +2 -0
  561. package/dist/assets/shield-check-CFNhE_aD.js.map +1 -0
  562. package/dist/assets/signIn-CVoSzqCz.js +2 -0
  563. package/dist/assets/signIn-CVoSzqCz.js.map +1 -0
  564. package/dist/assets/smartphone-BcQB9gIh.js +2 -0
  565. package/dist/assets/smartphone-BcQB9gIh.js.map +1 -0
  566. package/dist/assets/terminal-CGhryJds.js +2 -0
  567. package/dist/assets/terminal-CGhryJds.js.map +1 -0
  568. package/dist/assets/useAuth-lZZC20Tl.js +4 -0
  569. package/dist/assets/useAuth-lZZC20Tl.js.map +1 -0
  570. package/dist/cancelled/index.html +34 -0
  571. package/dist/downloads/shipscreens-agent-cli-config.yml +48 -0
  572. package/dist/downloads/shipscreens-agent-cli-copy.csv +2 -0
  573. package/dist/favicon-16x16.png +0 -0
  574. package/dist/favicon-32x32.png +0 -0
  575. package/dist/favicon.ico +0 -0
  576. package/dist/favicon.svg +10 -0
  577. package/dist/forgot-password/index.html +34 -0
  578. package/dist/index.html +42 -0
  579. package/dist/legal/index.html +33 -0
  580. package/dist/og-image.png +0 -0
  581. package/dist/pricing/index.html +33 -0
  582. package/dist/privacy/index.html +33 -0
  583. package/dist/robots.txt +11 -0
  584. package/dist/signin/index.html +34 -0
  585. package/dist/signup/index.html +34 -0
  586. package/dist/sitemap.xml +51 -0
  587. package/dist/success/index.html +34 -0
  588. package/dist/templates/clean_blue.png +0 -0
  589. package/dist/templates/minimal_dark.png +0 -0
  590. package/dist/templates/split_modern.png +0 -0
  591. package/dist/templates/vibrant_gradient.png +0 -0
  592. package/dist/terms/index.html +33 -0
  593. package/dist/tools/5-panel-screenshot-framework/index.html +33 -0
  594. package/dist/tools/agent-cli/index.html +33 -0
  595. package/dist/tools/app-review-aso/index.html +33 -0
  596. package/dist/tools/fastlane-screenshots/index.html +33 -0
  597. package/dist/tools/first-export/index.html +33 -0
  598. package/dist/tools/index.html +33 -0
  599. package/dist/tools/screenshot-workload-calculator/index.html +33 -0
  600. package/dist/tools/store-assets-pipeline/index.html +33 -0
  601. package/package.json +36 -0
  602. package/src/constants/devices.js +122 -0
  603. package/templates/agent/agent-prompt.txt +21 -0
  604. package/templates/agent/copy.csv +2 -0
  605. package/templates/agent/shipscreens.config.yml +48 -0
@@ -0,0 +1,339 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { deflateSync } from 'node:zlib';
4
+ import { DEVICE_LIBRARY } from '../../src/constants/devices.js';
5
+
6
+ const DEFAULT_LOCALES = ['en-US'];
7
+ const DEFAULT_SLIDES = 5;
8
+ export const DEFAULT_DEVICES = [
9
+ { id: 'iphone69', platform: 'ios' },
10
+ { id: 'pixel8', platform: 'android', androidBucket: 'phoneScreenshots' },
11
+ ];
12
+
13
+ export const PLACEHOLDER_COLOR = [30, 41, 59, 255];
14
+ export const PLACEHOLDER_WIDTH = 1080;
15
+ export const PLACEHOLDER_HEIGHT = 1920;
16
+
17
+ const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
18
+
19
+ const CRC_TABLE = (() => {
20
+ const table = new Uint32Array(256);
21
+ for (let i = 0; i < table.length; i += 1) {
22
+ let c = i;
23
+ for (let k = 0; k < 8; k += 1) {
24
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
25
+ }
26
+ table[i] = c >>> 0;
27
+ }
28
+ return table;
29
+ })();
30
+
31
+ const crc32 = (buffer) => {
32
+ let crc = 0xffffffff;
33
+ for (const byte of buffer) {
34
+ crc = (crc >>> 8) ^ CRC_TABLE[(crc ^ byte) & 0xff];
35
+ }
36
+ return (crc ^ 0xffffffff) >>> 0;
37
+ };
38
+
39
+ const pngChunk = (type, data) => {
40
+ const typeBuffer = Buffer.from(type, 'ascii');
41
+ const length = Buffer.alloc(4);
42
+ length.writeUInt32BE(data.length);
43
+ const crcBuffer = Buffer.alloc(4);
44
+ const crc = crc32(Buffer.concat([typeBuffer, data]));
45
+ crcBuffer.writeUInt32BE(crc);
46
+ return Buffer.concat([length, typeBuffer, data, crcBuffer]);
47
+ };
48
+
49
+ export const createSolidPng = ({ width, height, color }) => {
50
+ const row = Buffer.alloc(1 + width * 4);
51
+ row[0] = 0;
52
+ for (let i = 0; i < width; i += 1) {
53
+ const offset = 1 + i * 4;
54
+ row[offset] = color[0];
55
+ row[offset + 1] = color[1];
56
+ row[offset + 2] = color[2];
57
+ row[offset + 3] = color[3];
58
+ }
59
+
60
+ const raw = Buffer.alloc(row.length * height);
61
+ for (let y = 0; y < height; y += 1) {
62
+ row.copy(raw, y * row.length);
63
+ }
64
+
65
+ const compressed = deflateSync(raw);
66
+ const ihdr = Buffer.alloc(13);
67
+ ihdr.writeUInt32BE(width, 0);
68
+ ihdr.writeUInt32BE(height, 4);
69
+ ihdr[8] = 8;
70
+ ihdr[9] = 6;
71
+ ihdr[10] = 0;
72
+ ihdr[11] = 0;
73
+ ihdr[12] = 0;
74
+
75
+ return Buffer.concat([
76
+ PNG_SIGNATURE,
77
+ pngChunk('IHDR', ihdr),
78
+ pngChunk('IDAT', compressed),
79
+ pngChunk('IEND', Buffer.alloc(0)),
80
+ ]);
81
+ };
82
+
83
+ const parseList = (raw) => {
84
+ if (!raw) return [];
85
+ return String(raw)
86
+ .split(',')
87
+ .map((item) => item.trim())
88
+ .filter(Boolean);
89
+ };
90
+
91
+ export const formatIndex = (value, width) => String(value).padStart(width, '0');
92
+
93
+ const yamlQuoteIfNeeded = (value) => {
94
+ if (value === null || value === undefined) return '';
95
+ const raw = String(value);
96
+ // YAML treats `# ...` as a comment. Hex colors like "#0f172a" must be quoted.
97
+ if (raw.startsWith('#')) return `'${raw.replace(/'/g, "''")}'`;
98
+ return raw;
99
+ };
100
+
101
+ export const buildConfigYaml = ({ locales, slides, devices, assets, style } = {}) => {
102
+ const primaryLocale = locales[0];
103
+ const indexWidth = Math.max(2, String(slides).length);
104
+ const lines = ['schemaVersion: 1', '', 'locales:'];
105
+
106
+ locales.forEach((localeId) => {
107
+ lines.push(` - id: ${localeId}`);
108
+ });
109
+
110
+ lines.push('', 'devices:');
111
+ (devices?.length ? devices : DEFAULT_DEVICES).forEach((device) => {
112
+ lines.push(` - id: ${device.id}`);
113
+ if (device.platform) lines.push(` platform: ${device.platform}`);
114
+ if (device.androidBucket) lines.push(` androidBucket: ${device.androidBucket}`);
115
+ });
116
+
117
+ if (assets?.background || assets?.logo || (assets?.badges && assets.badges.length)) {
118
+ lines.push('', 'assets:');
119
+ if (assets.background) {
120
+ lines.push(' background:');
121
+ lines.push(` type: ${assets.background.type}`);
122
+ if (assets.background.type === 'solid') {
123
+ lines.push(` color: ${yamlQuoteIfNeeded(assets.background.color)}`);
124
+ } else if (assets.background.type === 'gradient') {
125
+ lines.push(` start: ${yamlQuoteIfNeeded(assets.background.start)}`);
126
+ lines.push(` end: ${yamlQuoteIfNeeded(assets.background.end)}`);
127
+ if (typeof assets.background.angle === 'number') lines.push(` angle: ${assets.background.angle}`);
128
+ } else if (assets.background.type === 'image') {
129
+ lines.push(` path: ${assets.background.path}`);
130
+ if (typeof assets.background.blur === 'number') lines.push(` blur: ${assets.background.blur}`);
131
+ if (typeof assets.background.opacity === 'number') lines.push(` opacity: ${assets.background.opacity}`);
132
+ }
133
+ }
134
+ if (assets.logo?.path) {
135
+ lines.push(' logo:');
136
+ lines.push(` path: ${assets.logo.path}`);
137
+ }
138
+ if (assets.badges?.length) {
139
+ lines.push(' badges:');
140
+ assets.badges.forEach((badge) => {
141
+ lines.push(` - id: ${badge.id}`);
142
+ lines.push(` path: ${badge.path}`);
143
+ });
144
+ }
145
+ }
146
+
147
+ if (style && Object.keys(style).length) {
148
+ lines.push('', 'style:');
149
+ if (style.textColor) lines.push(` textColor: ${yamlQuoteIfNeeded(style.textColor)}`);
150
+ if (style.layoutMode) lines.push(` layoutMode: ${style.layoutMode}`);
151
+ if (typeof style.topSpacing === 'number') lines.push(` topSpacing: ${style.topSpacing}`);
152
+ if (typeof style.deviceScale === 'number') lines.push(` deviceScale: ${style.deviceScale}`);
153
+ if (style.frameColor) lines.push(` frameColor: ${style.frameColor}`);
154
+ if (style.selectedFont) lines.push(` selectedFont: ${style.selectedFont}`);
155
+ if (style.badgeType) lines.push(` badgeType: ${style.badgeType}`);
156
+ if (typeof style.headerSize === 'number') lines.push(` headerSize: ${style.headerSize}`);
157
+ if (typeof style.subHeaderSize === 'number') lines.push(` subHeaderSize: ${style.subHeaderSize}`);
158
+ if (style.orientation) lines.push(` orientation: ${style.orientation}`);
159
+ }
160
+
161
+ lines.push('', 'slides:');
162
+ for (let i = 1; i <= slides; i += 1) {
163
+ const index = formatIndex(i, indexWidth);
164
+ lines.push(` - id: ${i}`);
165
+ lines.push(' screenshot:');
166
+ lines.push(` path: assets/${primaryLocale}/${index}.png`);
167
+ if (locales.length > 1) {
168
+ lines.push(' screenshotsByLocale:');
169
+ locales.slice(1).forEach((localeId) => {
170
+ lines.push(` ${localeId}: assets/${localeId}/${index}.png`);
171
+ });
172
+ }
173
+ lines.push(' text:');
174
+ locales.forEach((localeId) => {
175
+ lines.push(` ${localeId}:`);
176
+ lines.push(` header: Replace headline ${i}`);
177
+ lines.push(` sub: Replace subtitle ${i}`);
178
+ });
179
+ }
180
+
181
+ return `${lines.join('\n')}\n`;
182
+ };
183
+
184
+ export const buildCopyCsv = ({ locales, slides }) => {
185
+ const headers = ['Locale'];
186
+ for (let i = 1; i <= slides; i += 1) {
187
+ headers.push(`Header_${i}`, `Subtitle_${i}`);
188
+ }
189
+
190
+ const rows = locales.map((localeId) => {
191
+ const cells = [localeId];
192
+ for (let i = 1; i <= slides; i += 1) {
193
+ cells.push(`Replace headline ${i}`, `Replace subtitle ${i}`);
194
+ }
195
+ return cells.join(',');
196
+ });
197
+
198
+ return `${headers.join(',')}\n${rows.join('\n')}\n`;
199
+ };
200
+
201
+ export const ensureDir = async (dirPath) => {
202
+ await fs.mkdir(dirPath, { recursive: true });
203
+ };
204
+
205
+ const pathExists = async (filePath) => {
206
+ try {
207
+ await fs.stat(filePath);
208
+ return true;
209
+ } catch (err) {
210
+ if (err?.code === 'ENOENT') return false;
211
+ throw err;
212
+ }
213
+ };
214
+
215
+ function normalizeDeviceConfig(rawDevices) {
216
+ if (!rawDevices?.length) return [];
217
+ return rawDevices.map((device) => ({
218
+ id: device.id,
219
+ platform: device.platform,
220
+ androidBucket: device.androidBucket,
221
+ }));
222
+ }
223
+
224
+ export function resolveDevices({ devices }) {
225
+ if (!devices) return DEFAULT_DEVICES;
226
+ const list = Array.isArray(devices) ? devices : parseList(devices);
227
+ if (!list.length) return DEFAULT_DEVICES;
228
+
229
+ const resolved = list.map((id) => {
230
+ const def = DEVICE_LIBRARY[id];
231
+ if (!def) {
232
+ throw new Error(`Unknown device id: ${id}. See src/constants/devices.js for valid ids.`);
233
+ }
234
+ const group = def.group || '';
235
+ const isAndroid = group.toLowerCase().includes('android');
236
+ const platform = isAndroid ? 'android' : 'ios';
237
+ const androidBucket =
238
+ platform === 'android'
239
+ ? group.toLowerCase().includes('tablet')
240
+ ? 'tenInchScreenshots'
241
+ : 'phoneScreenshots'
242
+ : undefined;
243
+ return { id, platform, androidBucket };
244
+ });
245
+
246
+ const androidBuckets = new Map();
247
+ resolved.forEach((device) => {
248
+ if (device.platform !== 'android') return;
249
+ const bucket = device.androidBucket || 'phoneScreenshots';
250
+ const existing = androidBuckets.get(bucket);
251
+ if (existing) {
252
+ throw new Error(
253
+ `Multiple Android devices map to the same Google Play bucket (${bucket}): ${existing.id}, ${device.id}\n` +
254
+ `Pick one Android device per bucket (phoneScreenshots/tenInchScreenshots).`
255
+ );
256
+ }
257
+ androidBuckets.set(bucket, device);
258
+ });
259
+
260
+ return normalizeDeviceConfig(resolved);
261
+ }
262
+
263
+ export async function runInit({ dir = '.', slides = DEFAULT_SLIDES, locales, devices, assets, style, force = false } = {}) {
264
+ const targetDir = path.resolve(process.cwd(), dir);
265
+ const localeList = parseList(locales);
266
+ const resolvedLocales = localeList.length ? localeList : DEFAULT_LOCALES;
267
+ const resolvedDevices = resolveDevices({ devices });
268
+
269
+ const slideCount = Number(slides || DEFAULT_SLIDES);
270
+ if (!Number.isInteger(slideCount) || slideCount < 1 || slideCount > 10) {
271
+ throw new Error('Invalid --slides value. Expected an integer between 1 and 10.');
272
+ }
273
+ if (!resolvedLocales.length) {
274
+ throw new Error('Invalid --locales value. Provide at least one locale id.');
275
+ }
276
+
277
+ const configPath = path.join(targetDir, 'shipscreens.config.yml');
278
+ const csvPath = path.join(targetDir, 'copy.csv');
279
+
280
+ const filesToCheck = [configPath, csvPath];
281
+ for (const localeId of resolvedLocales) {
282
+ for (let i = 1; i <= slideCount; i += 1) {
283
+ const index = formatIndex(i, Math.max(2, String(slideCount).length));
284
+ filesToCheck.push(path.join(targetDir, 'assets', localeId, `${index}.png`));
285
+ }
286
+ }
287
+
288
+ if (!force) {
289
+ const conflicts = [];
290
+ for (const filePath of filesToCheck) {
291
+ if (await pathExists(filePath)) conflicts.push(filePath);
292
+ }
293
+ if (conflicts.length) {
294
+ throw new Error(
295
+ `Init would overwrite existing files. Use --force to overwrite.\n` +
296
+ `Conflicts:\n${conflicts.map((item) => `- ${item}`).join('\n')}`
297
+ );
298
+ }
299
+ }
300
+
301
+ await ensureDir(targetDir);
302
+
303
+ const configYaml = buildConfigYaml({
304
+ locales: resolvedLocales,
305
+ slides: slideCount,
306
+ devices: resolvedDevices,
307
+ assets,
308
+ style,
309
+ });
310
+ await fs.writeFile(configPath, configYaml, 'utf8');
311
+
312
+ const csv = buildCopyCsv({ locales: resolvedLocales, slides: slideCount });
313
+ await fs.writeFile(csvPath, csv, 'utf8');
314
+
315
+ const placeholder = createSolidPng({
316
+ width: PLACEHOLDER_WIDTH,
317
+ height: PLACEHOLDER_HEIGHT,
318
+ color: PLACEHOLDER_COLOR,
319
+ });
320
+
321
+ const indexWidth = Math.max(2, String(slideCount).length);
322
+ for (const localeId of resolvedLocales) {
323
+ for (let i = 1; i <= slideCount; i += 1) {
324
+ const index = formatIndex(i, indexWidth);
325
+ const assetPath = path.join(targetDir, 'assets', localeId, `${index}.png`);
326
+ await ensureDir(path.dirname(assetPath));
327
+ await fs.writeFile(assetPath, placeholder);
328
+ }
329
+ }
330
+
331
+ return {
332
+ dir: targetDir,
333
+ configPath,
334
+ csvPath,
335
+ locales: resolvedLocales,
336
+ slides: slideCount,
337
+ devices: resolvedDevices,
338
+ };
339
+ }
@@ -0,0 +1,144 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { collectAssetReferences } from '../assetRefs.js';
4
+ import { loadShipScreensConfig } from '../loadConfig.js';
5
+ import { sha256File } from '../hash.js';
6
+ import { SHIPSCREENS_CONFIG_SCHEMA_VERSION } from '../schema.js';
7
+ import { isPathInsideRoot, resolveValidationRoot } from '../rootPolicy.js';
8
+
9
+ async function statFile(absolutePath) {
10
+ const stat = await fs.stat(absolutePath);
11
+ if (!stat.isFile()) {
12
+ throw new Error(`Not a file: ${absolutePath}`);
13
+ }
14
+ return stat;
15
+ }
16
+
17
+ function serializeLock(lock) {
18
+ return `${JSON.stringify(lock, null, 2)}\n`;
19
+ }
20
+
21
+ function compareStrings(a, b) {
22
+ if (a === b) return 0;
23
+ return a < b ? -1 : 1;
24
+ }
25
+
26
+ function resolveOutPath({ configDir, outPath }) {
27
+ if (!outPath) return path.join(configDir, 'shipscreens.lock.json');
28
+ if (path.isAbsolute(outPath)) return outPath;
29
+ return path.resolve(configDir, outPath);
30
+ }
31
+
32
+ function diffLockSummary({ expected, actual }) {
33
+ if (!actual || typeof actual !== 'object') {
34
+ return 'Existing lockfile is not a JSON object.';
35
+ }
36
+
37
+ const expectedAssets = Array.isArray(expected.assets) ? expected.assets : [];
38
+ const actualAssets = Array.isArray(actual.assets) ? actual.assets : [];
39
+ const expectedByPath = new Map(expectedAssets.map((a) => [a.path, a]));
40
+ const actualByPath = new Map(actualAssets.map((a) => [a.path, a]));
41
+
42
+ const added = [];
43
+ const removed = [];
44
+ const changed = [];
45
+
46
+ for (const [assetPath, expectedAsset] of expectedByPath.entries()) {
47
+ const actualAsset = actualByPath.get(assetPath);
48
+ if (!actualAsset) {
49
+ added.push(assetPath);
50
+ continue;
51
+ }
52
+ if (expectedAsset.sha256 !== actualAsset.sha256 || expectedAsset.bytes !== actualAsset.bytes) {
53
+ changed.push(assetPath);
54
+ }
55
+ }
56
+
57
+ for (const assetPath of actualByPath.keys()) {
58
+ if (!expectedByPath.has(assetPath)) removed.push(assetPath);
59
+ }
60
+
61
+ added.sort(compareStrings);
62
+ removed.sort(compareStrings);
63
+ changed.sort(compareStrings);
64
+
65
+ const lines = [`Lockfile differs: ${added.length} added, ${removed.length} removed, ${changed.length} changed`];
66
+
67
+ const maxDetails = 10;
68
+ added.slice(0, maxDetails).forEach((p) => lines.push(`+ ${p}`));
69
+ removed.slice(0, maxDetails).forEach((p) => lines.push(`- ${p}`));
70
+ changed.slice(0, maxDetails).forEach((p) => {
71
+ const e = expectedByPath.get(p);
72
+ const a = actualByPath.get(p);
73
+ lines.push(`~ ${p} (sha256 ${a.sha256} -> ${e.sha256}, bytes ${a.bytes} -> ${e.bytes})`);
74
+ });
75
+
76
+ if (added.length > maxDetails || removed.length > maxDetails || changed.length > maxDetails) {
77
+ lines.push('(diff truncated)');
78
+ }
79
+
80
+ return lines.join('\n');
81
+ }
82
+
83
+ export async function runLock({ configPath, outPath, check = false }) {
84
+ const { config, configDir } = await loadShipScreensConfig(configPath);
85
+ const { rootPath, rootRealPath } = await resolveValidationRoot({ configDir });
86
+
87
+ const refs = collectAssetReferences(config);
88
+ const uniqueAssetPaths = [...new Set(refs.map((r) => r.path))].sort(compareStrings);
89
+
90
+ const assets = [];
91
+ for (const assetPath of uniqueAssetPaths) {
92
+ const absoluteAssetPath = path.resolve(configDir, assetPath);
93
+ if (!isPathInsideRoot({ rootPath, candidatePath: absoluteAssetPath })) {
94
+ throw new Error(`Path escapes repo root: ${assetPath}`);
95
+ }
96
+ const stat = await statFile(absoluteAssetPath);
97
+ const realAssetPath = await fs.realpath(absoluteAssetPath);
98
+ if (!isPathInsideRoot({ rootPath: rootRealPath, candidatePath: realAssetPath })) {
99
+ throw new Error(`Symlink escapes repo root: ${assetPath} (resolves to ${realAssetPath})`);
100
+ }
101
+ const sha256 = await sha256File(absoluteAssetPath);
102
+ assets.push({
103
+ path: assetPath,
104
+ bytes: stat.size,
105
+ sha256,
106
+ });
107
+ }
108
+
109
+ const lock = {
110
+ version: 1,
111
+ configSchemaVersion: SHIPSCREENS_CONFIG_SCHEMA_VERSION,
112
+ assets,
113
+ };
114
+
115
+ const resolvedOutPath = resolveOutPath({ configDir, outPath });
116
+ const expected = serializeLock(lock);
117
+
118
+ if (check) {
119
+ let existing;
120
+ try {
121
+ existing = await fs.readFile(resolvedOutPath, 'utf8');
122
+ } catch (err) {
123
+ if (err?.code === 'ENOENT') {
124
+ throw new Error(`Lockfile missing: ${resolvedOutPath}\nRun: shipscreens lock --config ${configPath}`);
125
+ }
126
+ throw err;
127
+ }
128
+
129
+ if (existing !== expected) {
130
+ let parsedExisting = null;
131
+ try {
132
+ parsedExisting = JSON.parse(existing);
133
+ } catch {
134
+ // ignore parse error; summary will mention invalid JSON
135
+ }
136
+ throw new Error(`${diffLockSummary({ expected: lock, actual: parsedExisting })}\nRun: shipscreens lock`);
137
+ }
138
+
139
+ return { outPath: resolvedOutPath, assetCount: assets.length, checked: true };
140
+ }
141
+
142
+ await fs.writeFile(resolvedOutPath, expected, 'utf8');
143
+ return { outPath: resolvedOutPath, assetCount: assets.length, checked: false };
144
+ }
@@ -0,0 +1,203 @@
1
+ import path from 'node:path';
2
+ import { runValidate } from './validate.js';
3
+ import { loadShipScreensConfig } from '../loadConfig.js';
4
+ import { resolveOutRoot, resolveOutputPath, resolveZipOutPath } from '../outputPaths.js';
5
+ import { formatScreenshotIndex, getScreenshotIndexWidth } from '../buildOutputs.js';
6
+
7
+ function compareStrings(a, b) {
8
+ if (a === b) return 0;
9
+ return a < b ? -1 : 1;
10
+ }
11
+
12
+ function normalizeProfile(profile) {
13
+ const normalized = String(profile || 'any')
14
+ .trim()
15
+ .toLowerCase();
16
+ if (!['any', 'appstore', 'playstore'].includes(normalized)) {
17
+ throw new Error(`Unknown plan profile: ${normalized} (expected: appstore|playstore|any)`);
18
+ }
19
+ return normalized;
20
+ }
21
+
22
+ function toPosixPath(value) {
23
+ return String(value).split(path.sep).join('/');
24
+ }
25
+
26
+ function toDeviceSlug(deviceId) {
27
+ return String(deviceId).toLowerCase();
28
+ }
29
+
30
+ function getAndroidBucket(device) {
31
+ return device.androidBucket || 'phoneScreenshots';
32
+ }
33
+
34
+ function groupAndroidDevicesByBucket(devices) {
35
+ const map = new Map();
36
+ devices.forEach((device) => {
37
+ const bucket = getAndroidBucket(device);
38
+ const existing = map.get(bucket);
39
+ if (existing) {
40
+ throw new Error(
41
+ `Multiple Android devices map to the same Google Play bucket (${bucket}): ${existing.id}, ${device.id}\n` +
42
+ `Each bucket represents a single screenshot set on Google Play (writing both would overwrite / conflict).\n` +
43
+ `Set only one Android device per bucket, or set devices[].androidBucket explicitly.`
44
+ );
45
+ }
46
+ map.set(bucket, device);
47
+ });
48
+ return map;
49
+ }
50
+
51
+ function resolveOutRootRel({ configDir, outRoot }) {
52
+ const rel = path.relative(configDir, outRoot);
53
+ if (!rel) return '.';
54
+ return toPosixPath(rel);
55
+ }
56
+
57
+ function resolvePathRel({ baseDir, absolutePath }) {
58
+ const rel = path.relative(baseDir, absolutePath);
59
+ if (!rel) return '.';
60
+ return toPosixPath(rel);
61
+ }
62
+
63
+ export async function runPlan({ configPath, outDir, iosDir, androidDir, zipOut, profile } = {}) {
64
+ const normalizedProfile = normalizeProfile(profile);
65
+ await runValidate({ configPath });
66
+
67
+ const { config, configDir } = await loadShipScreensConfig(configPath);
68
+ const outRoot = resolveOutRoot({ configDir, outDir });
69
+
70
+ const resolvedIosDir = resolveOutputPath({
71
+ outRoot,
72
+ value: iosDir || config.output?.directory,
73
+ fallback: 'fastlane/screenshots',
74
+ });
75
+ const resolvedAndroidDir = resolveOutputPath({
76
+ outRoot,
77
+ value: androidDir || config.output?.androidDirectory,
78
+ fallback: 'fastlane/metadata/android',
79
+ });
80
+ const resolvedZipPath = resolveZipOutPath({ outRoot, zipOut });
81
+
82
+ const devices = Array.isArray(config.devices) ? config.devices : [];
83
+ const iosDevices = devices
84
+ .filter((d) => d.platform !== 'android')
85
+ .map((d) => ({ id: d.id, slug: toDeviceSlug(d.id) }))
86
+ .sort((a, b) => compareStrings(a.slug, b.slug));
87
+
88
+ const androidBuckets = [...groupAndroidDevicesByBucket(devices.filter((d) => d.platform === 'android')).entries()]
89
+ .sort(([a], [b]) => compareStrings(a, b))
90
+ .map(([bucket, device]) => ({ bucket, deviceId: device.id }));
91
+
92
+ const locales = (config.locales || []).map((l) => l.id).sort(compareStrings);
93
+ const slideCount = config.slides.length;
94
+ const indexWidth = getScreenshotIndexWidth(slideCount);
95
+ const indices = Array.from({ length: slideCount }, (_, idx) => formatScreenshotIndex(idx + 1, indexWidth));
96
+
97
+ const includeIos = normalizedProfile !== 'playstore';
98
+ const includeAndroid = normalizedProfile !== 'appstore';
99
+
100
+ if (includeIos && !iosDevices.length) {
101
+ throw new Error(`No iOS devices configured. Add at least one iOS device, or use --profile playstore.`);
102
+ }
103
+ if (includeAndroid && !androidBuckets.length) {
104
+ throw new Error(`No Android devices configured. Add at least one Android device, or use --profile appstore.`);
105
+ }
106
+
107
+ const outRootRel = resolveOutRootRel({ configDir, outRoot });
108
+ const iosDirRelToOut = resolvePathRel({ baseDir: outRoot, absolutePath: resolvedIosDir });
109
+ const androidDirRelToOut = resolvePathRel({ baseDir: outRoot, absolutePath: resolvedAndroidDir });
110
+ const zipPathRelToOut = resolvePathRel({ baseDir: outRoot, absolutePath: resolvedZipPath });
111
+
112
+ const iosSets = [];
113
+ if (includeIos) {
114
+ for (const localeId of locales) {
115
+ for (const device of iosDevices) {
116
+ const files = indices.map((padded) => `${device.slug}_${padded}.png`);
117
+ iosSets.push({
118
+ locale: localeId,
119
+ device: device.slug,
120
+ dir: path.posix.join(iosDirRelToOut, localeId),
121
+ files,
122
+ });
123
+ }
124
+ }
125
+ }
126
+
127
+ const androidSets = [];
128
+ if (includeAndroid) {
129
+ for (const localeId of locales) {
130
+ for (const { bucket } of androidBuckets) {
131
+ const files = indices.map((padded) => `${padded}.png`);
132
+ androidSets.push({
133
+ locale: localeId,
134
+ bucket,
135
+ dir: path.posix.join(androidDirRelToOut, localeId, 'images', bucket),
136
+ files,
137
+ });
138
+ }
139
+ }
140
+ }
141
+
142
+ const expectedDirFiles = [
143
+ ...iosSets.flatMap((set) => set.files.map((file) => path.posix.join(set.dir, file))),
144
+ ...androidSets.flatMap((set) => set.files.map((file) => path.posix.join(set.dir, file))),
145
+ ].sort(compareStrings);
146
+
147
+ const expectedZipEntries = [
148
+ ...iosSets.flatMap((set) => set.files.map((file) => path.posix.join('fastlane', 'screenshots', set.locale, file))),
149
+ ...androidSets.flatMap((set) =>
150
+ set.files.map((file) => path.posix.join('fastlane', 'metadata', 'android', set.locale, 'images', set.bucket, file))
151
+ ),
152
+ ].sort(compareStrings);
153
+
154
+ return {
155
+ version: 1,
156
+ profile: normalizedProfile,
157
+ out: {
158
+ root: outRootRel,
159
+ iosDir: iosDirRelToOut,
160
+ androidDir: androidDirRelToOut,
161
+ zipPath: zipPathRelToOut,
162
+ },
163
+ config: {
164
+ schemaVersion: config.schemaVersion,
165
+ locales,
166
+ slides: slideCount,
167
+ indexWidth,
168
+ indices,
169
+ iosDevices: iosDevices.map((d) => d.slug),
170
+ androidBuckets: androidBuckets.map((b) => b.bucket),
171
+ },
172
+ build: {
173
+ writes: {
174
+ dirFiles: expectedDirFiles,
175
+ zipEntries: expectedZipEntries,
176
+ },
177
+ clean: {
178
+ ios: {
179
+ locales,
180
+ deviceSlugs: iosDevices.map((d) => d.slug),
181
+ pattern: '<device>_<index>.png (unframed only)',
182
+ },
183
+ android: {
184
+ locales,
185
+ buckets: androidBuckets.map((b) => b.bucket),
186
+ pattern: '<index>.png',
187
+ },
188
+ },
189
+ },
190
+ stage: {
191
+ profiles: {
192
+ appstore: { includes: ['ios'], excludes: ['android'], iosVariant: 'auto' },
193
+ playstore: { includes: ['android'], excludes: ['ios'] },
194
+ any: { includes: ['ios', 'android'], excludes: [] },
195
+ },
196
+ notes: [
197
+ 'Use shipscreens stage --profile <appstore|playstore|any> to copy only upload-ready files into a new root.',
198
+ 'For profile=appstore, stage will refuse partial framed outputs and choose *_framed.png only when complete.',
199
+ ],
200
+ },
201
+ };
202
+ }
203
+