waybetter 0.1.1 → 0.7.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 (537) hide show
  1. package/README.md +139 -6
  2. package/bin/waybetter.mjs +43 -0
  3. package/build/runtime.mjs +105 -0
  4. package/cli/buildenv.mjs +130 -0
  5. package/cli/dev.mjs +97 -0
  6. package/cli/i18n.mjs +382 -0
  7. package/cli/manifests.mjs +383 -0
  8. package/cli/release.mjs +437 -0
  9. package/cli/releasecheck.mjs +15 -0
  10. package/cli/remote.mjs +260 -0
  11. package/cli/store.mjs +378 -0
  12. package/cli/strings.mjs +123 -0
  13. package/dist/runtime/column.d.ts +93 -0
  14. package/dist/runtime/column.js +451 -0
  15. package/dist/runtime/column.js.map +1 -0
  16. package/dist/runtime/commandReport.d.ts +19 -0
  17. package/dist/runtime/commandReport.js +47 -0
  18. package/dist/runtime/commandReport.js.map +1 -0
  19. package/dist/runtime/commands.d.ts +72 -0
  20. package/dist/runtime/commands.js +214 -0
  21. package/dist/runtime/commands.js.map +1 -0
  22. package/dist/runtime/devErrors.d.ts +16 -0
  23. package/dist/runtime/devErrors.js +30 -0
  24. package/dist/runtime/devErrors.js.map +1 -0
  25. package/dist/runtime/domHub.d.ts +21 -0
  26. package/dist/runtime/domHub.js +139 -4
  27. package/dist/runtime/domHub.js.map +1 -1
  28. package/dist/runtime/featureModules.d.ts +157 -0
  29. package/dist/runtime/featureModules.js +484 -0
  30. package/dist/runtime/featureModules.js.map +1 -0
  31. package/dist/runtime/featureTable.d.ts +144 -0
  32. package/dist/runtime/featureTable.js +223 -0
  33. package/dist/runtime/featureTable.js.map +1 -0
  34. package/dist/runtime/fonts.d.ts +22 -0
  35. package/dist/runtime/fonts.js +72 -0
  36. package/dist/runtime/fonts.js.map +1 -0
  37. package/dist/runtime/i18n.d.ts +138 -0
  38. package/dist/runtime/i18n.js +614 -0
  39. package/dist/runtime/i18n.js.map +1 -0
  40. package/dist/runtime/i18nCheck.d.ts +30 -0
  41. package/dist/runtime/i18nCheck.js +224 -0
  42. package/dist/runtime/i18nCheck.js.map +1 -0
  43. package/dist/runtime/pageLang.d.ts +8 -0
  44. package/dist/runtime/pageLang.js +64 -0
  45. package/dist/runtime/pageLang.js.map +1 -0
  46. package/dist/runtime/pageStrings.d.ts +35 -0
  47. package/dist/runtime/pageStrings.js +76 -0
  48. package/dist/runtime/pageStrings.js.map +1 -0
  49. package/dist/runtime/panelButton.d.ts +33 -0
  50. package/dist/runtime/panelButton.js +83 -0
  51. package/dist/runtime/panelButton.js.map +1 -0
  52. package/dist/runtime/permissions.d.ts +47 -0
  53. package/dist/runtime/permissions.js +141 -0
  54. package/dist/runtime/permissions.js.map +1 -0
  55. package/dist/runtime/pluginApi.d.ts +51 -2
  56. package/dist/runtime/pluginApi.js +137 -22
  57. package/dist/runtime/pluginApi.js.map +1 -1
  58. package/dist/runtime/pluginI18n.d.ts +29 -0
  59. package/dist/runtime/pluginI18n.js +119 -0
  60. package/dist/runtime/pluginI18n.js.map +1 -0
  61. package/dist/runtime/settingsForm.d.ts +66 -0
  62. package/dist/runtime/settingsForm.js +114 -0
  63. package/dist/runtime/settingsForm.js.map +1 -0
  64. package/dist/runtime/site.d.ts +5 -0
  65. package/dist/runtime/site.js +1 -1
  66. package/dist/runtime/site.js.map +1 -1
  67. package/dist/runtime/siteRuntime.d.ts +144 -0
  68. package/dist/runtime/siteRuntime.js +175 -0
  69. package/dist/runtime/siteRuntime.js.map +1 -0
  70. package/dist/runtime/stringPackHook.d.ts +84 -0
  71. package/dist/runtime/stringPackHook.js +220 -0
  72. package/dist/runtime/stringPackHook.js.map +1 -0
  73. package/dist/runtime/stringPackTranslate.d.ts +61 -0
  74. package/dist/runtime/stringPackTranslate.js +267 -0
  75. package/dist/runtime/stringPackTranslate.js.map +1 -0
  76. package/dist/runtime/stringPacks.d.ts +248 -0
  77. package/dist/runtime/stringPacks.js +610 -0
  78. package/dist/runtime/stringPacks.js.map +1 -0
  79. package/dist/runtime/styles.d.ts +15 -0
  80. package/dist/runtime/styles.js +81 -0
  81. package/dist/runtime/styles.js.map +1 -0
  82. package/dist/runtime/textNet.d.ts +15 -0
  83. package/dist/runtime/textNet.js +131 -0
  84. package/dist/runtime/textNet.js.map +1 -0
  85. package/dist/runtime/themeApi.d.ts +121 -0
  86. package/dist/runtime/themeApi.js +220 -0
  87. package/dist/runtime/themeApi.js.map +1 -0
  88. package/dist/runtime/themeBar.d.ts +28 -0
  89. package/dist/runtime/themeBar.js +82 -0
  90. package/dist/runtime/themeBar.js.map +1 -0
  91. package/dist/runtime/themeChoice.d.ts +52 -0
  92. package/dist/runtime/themeChoice.js +69 -0
  93. package/dist/runtime/themeChoice.js.map +1 -0
  94. package/dist/runtime/themeComponents.d.ts +435 -0
  95. package/dist/runtime/themeComponents.js +476 -0
  96. package/dist/runtime/themeComponents.js.map +1 -0
  97. package/dist/runtime/themeDecor.d.ts +73 -0
  98. package/dist/runtime/themeDecor.js +133 -0
  99. package/dist/runtime/themeDecor.js.map +1 -0
  100. package/dist/runtime/themeDerive.d.ts +69 -0
  101. package/dist/runtime/themeDerive.js +117 -0
  102. package/dist/runtime/themeDerive.js.map +1 -0
  103. package/dist/runtime/themeDoctor.d.ts +52 -0
  104. package/dist/runtime/themeDoctor.js +112 -0
  105. package/dist/runtime/themeDoctor.js.map +1 -0
  106. package/dist/runtime/themeGuards.d.ts +60 -0
  107. package/dist/runtime/themeGuards.js +235 -0
  108. package/dist/runtime/themeGuards.js.map +1 -0
  109. package/dist/runtime/themeIcons.d.ts +130 -0
  110. package/dist/runtime/themeIcons.js +271 -0
  111. package/dist/runtime/themeIcons.js.map +1 -0
  112. package/dist/runtime/themeInk.d.ts +37 -0
  113. package/dist/runtime/themeInk.js +111 -0
  114. package/dist/runtime/themeInk.js.map +1 -0
  115. package/dist/runtime/themeInvariants.d.ts +39 -0
  116. package/dist/runtime/themeInvariants.js +273 -0
  117. package/dist/runtime/themeInvariants.js.map +1 -0
  118. package/dist/runtime/themeRuntime.d.ts +114 -0
  119. package/dist/runtime/themeRuntime.js +570 -0
  120. package/dist/runtime/themeRuntime.js.map +1 -0
  121. package/dist/runtime/themeSchema.d.ts +10 -0
  122. package/dist/runtime/themeSchema.js +150 -0
  123. package/dist/runtime/themeSchema.js.map +1 -0
  124. package/dist/runtime/themeSpec.d.ts +263 -0
  125. package/dist/runtime/themeSpec.js +435 -0
  126. package/dist/runtime/themeSpec.js.map +1 -0
  127. package/dist/runtime/themeTokens.d.ts +12 -0
  128. package/dist/runtime/themeTokens.js +14 -6
  129. package/dist/runtime/themeTokens.js.map +1 -1
  130. package/dist/runtime/themeVariants.d.ts +30 -0
  131. package/dist/runtime/themeVariants.js +53 -0
  132. package/dist/runtime/themeVariants.js.map +1 -0
  133. package/dist/runtime/ui.d.ts +192 -0
  134. package/dist/runtime/ui.js +926 -0
  135. package/dist/runtime/ui.js.map +1 -0
  136. package/dist/shell/InstallDialog.d.ts +40 -0
  137. package/dist/shell/InstallDialog.js +176 -0
  138. package/dist/shell/InstallDialog.js.map +1 -0
  139. package/dist/shell/StoreView.d.ts +78 -0
  140. package/dist/shell/StoreView.js +108 -0
  141. package/dist/shell/StoreView.js.map +1 -0
  142. package/dist/shell/addressModel.js.map +1 -1
  143. package/dist/shell/chrome.js.map +1 -1
  144. package/dist/shell/deckModel.d.ts +117 -0
  145. package/dist/shell/deckModel.js +267 -0
  146. package/dist/shell/deckModel.js.map +1 -0
  147. package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
  148. package/dist/shell/frame/AccountSwitcher.js +243 -0
  149. package/dist/shell/frame/AccountSwitcher.js.map +1 -0
  150. package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
  151. package/dist/shell/frame/AddColumnDialog.js +81 -0
  152. package/dist/shell/frame/AddColumnDialog.js.map +1 -0
  153. package/dist/shell/frame/AppMenu.d.ts +44 -0
  154. package/dist/shell/frame/AppMenu.js +721 -0
  155. package/dist/shell/frame/AppMenu.js.map +1 -0
  156. package/dist/shell/frame/CommandPalette.d.ts +7 -0
  157. package/dist/shell/frame/CommandPalette.js +118 -0
  158. package/dist/shell/frame/CommandPalette.js.map +1 -0
  159. package/dist/shell/frame/DeckView.d.ts +13 -0
  160. package/dist/shell/frame/DeckView.js +287 -0
  161. package/dist/shell/frame/DeckView.js.map +1 -0
  162. package/dist/shell/frame/FindBar.d.ts +10 -0
  163. package/dist/shell/frame/FindBar.js +108 -0
  164. package/dist/shell/frame/FindBar.js.map +1 -0
  165. package/dist/shell/frame/MediaPanel.d.ts +8 -0
  166. package/dist/shell/frame/MediaPanel.js +76 -0
  167. package/dist/shell/frame/MediaPanel.js.map +1 -0
  168. package/dist/shell/frame/NewTabPage.d.ts +9 -0
  169. package/dist/shell/frame/NewTabPage.js +71 -0
  170. package/dist/shell/frame/NewTabPage.js.map +1 -0
  171. package/dist/shell/frame/PaneTheme.d.ts +16 -0
  172. package/dist/shell/frame/PaneTheme.js +67 -0
  173. package/dist/shell/frame/PaneTheme.js.map +1 -0
  174. package/dist/shell/frame/ReportDialog.d.ts +3 -0
  175. package/dist/shell/frame/ReportDialog.js +95 -0
  176. package/dist/shell/frame/ReportDialog.js.map +1 -0
  177. package/dist/shell/frame/Shell.d.ts +9 -0
  178. package/dist/shell/frame/Shell.js +1139 -0
  179. package/dist/shell/frame/Shell.js.map +1 -0
  180. package/dist/shell/frame/Titlebar.d.ts +17 -0
  181. package/dist/shell/frame/Titlebar.js +79 -0
  182. package/dist/shell/frame/Titlebar.js.map +1 -0
  183. package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
  184. package/dist/shell/frame/TitlebarExtras.js +202 -0
  185. package/dist/shell/frame/TitlebarExtras.js.map +1 -0
  186. package/dist/shell/frame/WebPanel.d.ts +4 -0
  187. package/dist/shell/frame/WebPanel.js +185 -0
  188. package/dist/shell/frame/WebPanel.js.map +1 -0
  189. package/dist/shell/frame/accountModel.d.ts +49 -0
  190. package/dist/shell/frame/accountModel.js +67 -0
  191. package/dist/shell/frame/accountModel.js.map +1 -0
  192. package/dist/shell/frame/accountSwitcher.css +91 -0
  193. package/dist/shell/frame/appI18n.d.ts +44 -0
  194. package/dist/shell/frame/appI18n.js +64 -0
  195. package/dist/shell/frame/appI18n.js.map +1 -0
  196. package/dist/shell/frame/appMenu.css +127 -0
  197. package/dist/shell/frame/backupModel.d.ts +38 -0
  198. package/dist/shell/frame/backupModel.js +192 -0
  199. package/dist/shell/frame/backupModel.js.map +1 -0
  200. package/dist/shell/frame/boot.d.ts +8 -0
  201. package/dist/shell/frame/boot.js +37 -0
  202. package/dist/shell/frame/boot.js.map +1 -0
  203. package/dist/shell/frame/brand.d.ts +1 -0
  204. package/dist/shell/frame/brand.js +4 -0
  205. package/dist/shell/frame/brand.js.map +1 -0
  206. package/dist/shell/frame/bridge.d.ts +35 -0
  207. package/dist/shell/frame/bridge.js +70 -0
  208. package/dist/shell/frame/bridge.js.map +1 -0
  209. package/dist/shell/frame/chromeTheme.d.ts +47 -0
  210. package/dist/shell/frame/chromeTheme.js +118 -0
  211. package/dist/shell/frame/chromeTheme.js.map +1 -0
  212. package/dist/shell/frame/deck.css +209 -0
  213. package/dist/shell/frame/deckStore.d.ts +89 -0
  214. package/dist/shell/frame/deckStore.js +239 -0
  215. package/dist/shell/frame/deckStore.js.map +1 -0
  216. package/dist/shell/frame/devHost.d.ts +35 -0
  217. package/dist/shell/frame/devHost.js +80 -0
  218. package/dist/shell/frame/devHost.js.map +1 -0
  219. package/dist/shell/frame/devModel.d.ts +7 -0
  220. package/dist/shell/frame/devModel.js +17 -0
  221. package/dist/shell/frame/devModel.js.map +1 -0
  222. package/dist/shell/frame/diag.d.ts +7 -0
  223. package/dist/shell/frame/diag.js +39 -0
  224. package/dist/shell/frame/diag.js.map +1 -0
  225. package/dist/shell/frame/edges.css +159 -0
  226. package/dist/shell/frame/findBar.css +14 -0
  227. package/dist/shell/frame/frameMessages.d.ts +248 -0
  228. package/dist/shell/frame/frameMessages.js +252 -0
  229. package/dist/shell/frame/frameMessages.js.map +1 -0
  230. package/dist/shell/frame/hooks.d.ts +39 -0
  231. package/dist/shell/frame/hooks.js +97 -0
  232. package/dist/shell/frame/hooks.js.map +1 -0
  233. package/dist/shell/frame/i18n.d.ts +27 -0
  234. package/dist/shell/frame/i18n.js +66 -0
  235. package/dist/shell/frame/i18n.js.map +1 -0
  236. package/dist/shell/frame/iconPack.d.ts +11 -0
  237. package/dist/shell/frame/iconPack.js +45 -0
  238. package/dist/shell/frame/iconPack.js.map +1 -0
  239. package/dist/shell/frame/icons.d.ts +71 -0
  240. package/dist/shell/frame/icons.js +75 -0
  241. package/dist/shell/frame/icons.js.map +1 -0
  242. package/dist/shell/frame/index.d.ts +34 -0
  243. package/dist/shell/frame/index.js +43 -0
  244. package/dist/shell/frame/index.js.map +1 -0
  245. package/dist/shell/frame/language.d.ts +58 -0
  246. package/dist/shell/frame/language.js +165 -0
  247. package/dist/shell/frame/language.js.map +1 -0
  248. package/dist/shell/frame/mediaModel.d.ts +47 -0
  249. package/dist/shell/frame/mediaModel.js +67 -0
  250. package/dist/shell/frame/mediaModel.js.map +1 -0
  251. package/dist/shell/frame/menuMessages.en.json +96 -0
  252. package/dist/shell/frame/menuModel.d.ts +319 -0
  253. package/dist/shell/frame/menuModel.js +301 -0
  254. package/dist/shell/frame/menuModel.js.map +1 -0
  255. package/dist/shell/frame/nativeMenu.d.ts +5 -0
  256. package/dist/shell/frame/nativeMenu.js +178 -0
  257. package/dist/shell/frame/nativeMenu.js.map +1 -0
  258. package/dist/shell/frame/nativeMenuModel.d.ts +102 -0
  259. package/dist/shell/frame/nativeMenuModel.js +186 -0
  260. package/dist/shell/frame/nativeMenuModel.js.map +1 -0
  261. package/dist/shell/frame/paletteModel.d.ts +139 -0
  262. package/dist/shell/frame/paletteModel.js +114 -0
  263. package/dist/shell/frame/paletteModel.js.map +1 -0
  264. package/dist/shell/frame/paneTheme.css +9 -0
  265. package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
  266. package/dist/shell/frame/pluginCommandStore.js +70 -0
  267. package/dist/shell/frame/pluginCommandStore.js.map +1 -0
  268. package/dist/shell/frame/reportModel.d.ts +52 -0
  269. package/dist/shell/frame/reportModel.js +105 -0
  270. package/dist/shell/frame/reportModel.js.map +1 -0
  271. package/dist/shell/frame/safeStore.d.ts +7 -0
  272. package/dist/shell/frame/safeStore.js +40 -0
  273. package/dist/shell/frame/safeStore.js.map +1 -0
  274. package/dist/shell/frame/searchInput.d.ts +2 -0
  275. package/dist/shell/frame/searchInput.js +11 -0
  276. package/dist/shell/frame/searchInput.js.map +1 -0
  277. package/dist/shell/frame/shell.css +634 -0
  278. package/dist/shell/frame/site.d.ts +206 -0
  279. package/dist/shell/frame/site.js +22 -0
  280. package/dist/shell/frame/site.js.map +1 -0
  281. package/dist/shell/frame/state.d.ts +101 -0
  282. package/dist/shell/frame/state.js +286 -0
  283. package/dist/shell/frame/state.js.map +1 -0
  284. package/dist/shell/frame/syncGate.d.ts +10 -0
  285. package/dist/shell/frame/syncGate.js +36 -0
  286. package/dist/shell/frame/syncGate.js.map +1 -0
  287. package/dist/shell/frame/syncHost.d.ts +35 -0
  288. package/dist/shell/frame/syncHost.js +85 -0
  289. package/dist/shell/frame/syncHost.js.map +1 -0
  290. package/dist/shell/frame/tabStill.d.ts +2 -0
  291. package/dist/shell/frame/tabStill.js +62 -0
  292. package/dist/shell/frame/tabStill.js.map +1 -0
  293. package/dist/shell/frame/themeScopes.d.ts +29 -0
  294. package/dist/shell/frame/themeScopes.js +61 -0
  295. package/dist/shell/frame/themeScopes.js.map +1 -0
  296. package/dist/shell/frame/themeStore.d.ts +99 -0
  297. package/dist/shell/frame/themeStore.js +267 -0
  298. package/dist/shell/frame/themeStore.js.map +1 -0
  299. package/dist/shell/frame/windowBinding.d.ts +2 -0
  300. package/dist/shell/frame/windowBinding.js +7 -0
  301. package/dist/shell/frame/windowBinding.js.map +1 -0
  302. package/dist/shell/frame/workspaceModel.d.ts +82 -0
  303. package/dist/shell/frame/workspaceModel.js +250 -0
  304. package/dist/shell/frame/workspaceModel.js.map +1 -0
  305. package/dist/shell/frame/workspaces.css +84 -0
  306. package/dist/shell/frame/workspaces.d.ts +22 -0
  307. package/dist/shell/frame/workspaces.js +125 -0
  308. package/dist/shell/frame/workspaces.js.map +1 -0
  309. package/dist/shell/frame/zoomStore.d.ts +10 -0
  310. package/dist/shell/frame/zoomStore.js +65 -0
  311. package/dist/shell/frame/zoomStore.js.map +1 -0
  312. package/dist/shell/installController.d.ts +137 -0
  313. package/dist/shell/installController.js +172 -0
  314. package/dist/shell/installController.js.map +1 -0
  315. package/dist/shell/installerMessages.d.ts +30 -0
  316. package/dist/shell/installerMessages.js +36 -0
  317. package/dist/shell/installerMessages.js.map +1 -0
  318. package/dist/shell/linkDrop.js.map +1 -1
  319. package/dist/shell/messages.d.ts +16 -0
  320. package/dist/shell/messages.js +27 -0
  321. package/dist/shell/messages.js.map +1 -0
  322. package/dist/shell/palette.js.map +1 -1
  323. package/dist/shell/paneModel.d.ts +22 -0
  324. package/dist/shell/paneModel.js +24 -1
  325. package/dist/shell/paneModel.js.map +1 -1
  326. package/dist/shell/panel/Appearance.d.ts +8 -0
  327. package/dist/shell/panel/Appearance.js +265 -0
  328. package/dist/shell/panel/Appearance.js.map +1 -0
  329. package/dist/shell/panel/BackupPanel.d.ts +5 -0
  330. package/dist/shell/panel/BackupPanel.js +198 -0
  331. package/dist/shell/panel/BackupPanel.js.map +1 -0
  332. package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
  333. package/dist/shell/panel/DeveloperPanel.js +51 -0
  334. package/dist/shell/panel/DeveloperPanel.js.map +1 -0
  335. package/dist/shell/panel/FeatureToggles.d.ts +13 -0
  336. package/dist/shell/panel/FeatureToggles.js +42 -0
  337. package/dist/shell/panel/FeatureToggles.js.map +1 -0
  338. package/dist/shell/panel/Home.d.ts +3 -0
  339. package/dist/shell/panel/Home.js +23 -0
  340. package/dist/shell/panel/Home.js.map +1 -0
  341. package/dist/shell/panel/IconPackInstall.d.ts +15 -0
  342. package/dist/shell/panel/IconPackInstall.js +41 -0
  343. package/dist/shell/panel/IconPackInstall.js.map +1 -0
  344. package/dist/shell/panel/LanguageSettings.d.ts +1 -0
  345. package/dist/shell/panel/LanguageSettings.js +54 -0
  346. package/dist/shell/panel/LanguageSettings.js.map +1 -0
  347. package/dist/shell/panel/MakePanel.d.ts +3 -0
  348. package/dist/shell/panel/MakePanel.js +237 -0
  349. package/dist/shell/panel/MakePanel.js.map +1 -0
  350. package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
  351. package/dist/shell/panel/MarkdownDoc.js +35 -0
  352. package/dist/shell/panel/MarkdownDoc.js.map +1 -0
  353. package/dist/shell/panel/Modes.d.ts +40 -0
  354. package/dist/shell/panel/Modes.js +270 -0
  355. package/dist/shell/panel/Modes.js.map +1 -0
  356. package/dist/shell/panel/NavIcon.d.ts +4 -0
  357. package/dist/shell/panel/NavIcon.js +6 -0
  358. package/dist/shell/panel/NavIcon.js.map +1 -0
  359. package/dist/shell/panel/Panel.d.ts +7 -0
  360. package/dist/shell/panel/Panel.js +139 -0
  361. package/dist/shell/panel/Panel.js.map +1 -0
  362. package/dist/shell/panel/PluginFeatures.d.ts +24 -0
  363. package/dist/shell/panel/PluginFeatures.js +165 -0
  364. package/dist/shell/panel/PluginFeatures.js.map +1 -0
  365. package/dist/shell/panel/Plugins.d.ts +33 -0
  366. package/dist/shell/panel/Plugins.js +112 -0
  367. package/dist/shell/panel/Plugins.js.map +1 -0
  368. package/dist/shell/panel/PowerSettings.d.ts +4 -0
  369. package/dist/shell/panel/PowerSettings.js +52 -0
  370. package/dist/shell/panel/PowerSettings.js.map +1 -0
  371. package/dist/shell/panel/Settings.d.ts +23 -0
  372. package/dist/shell/panel/Settings.js +117 -0
  373. package/dist/shell/panel/Settings.js.map +1 -0
  374. package/dist/shell/panel/ShareSetup.d.ts +8 -0
  375. package/dist/shell/panel/ShareSetup.js +130 -0
  376. package/dist/shell/panel/ShareSetup.js.map +1 -0
  377. package/dist/shell/panel/StoreSection.d.ts +7 -0
  378. package/dist/shell/panel/StoreSection.js +78 -0
  379. package/dist/shell/panel/StoreSection.js.map +1 -0
  380. package/dist/shell/panel/StringPacks.d.ts +20 -0
  381. package/dist/shell/panel/StringPacks.js +131 -0
  382. package/dist/shell/panel/StringPacks.js.map +1 -0
  383. package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
  384. package/dist/shell/panel/ThemeBuilder.js +205 -0
  385. package/dist/shell/panel/ThemeBuilder.js.map +1 -0
  386. package/dist/shell/panel/backup.css +34 -0
  387. package/dist/shell/panel/builder.css +240 -0
  388. package/dist/shell/panel/builderModel.d.ts +55 -0
  389. package/dist/shell/panel/builderModel.js +95 -0
  390. package/dist/shell/panel/builderModel.js.map +1 -0
  391. package/dist/shell/panel/compare.d.ts +10 -0
  392. package/dist/shell/panel/compare.js +51 -0
  393. package/dist/shell/panel/compare.js.map +1 -0
  394. package/dist/shell/panel/controls.d.ts +135 -0
  395. package/dist/shell/panel/controls.js +213 -0
  396. package/dist/shell/panel/controls.js.map +1 -0
  397. package/dist/shell/panel/featureModel.d.ts +69 -0
  398. package/dist/shell/panel/featureModel.js +79 -0
  399. package/dist/shell/panel/featureModel.js.map +1 -0
  400. package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
  401. package/dist/shell/panel/fonts/FontBrowser.js +189 -0
  402. package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
  403. package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
  404. package/dist/shell/panel/fonts/FontRoles.js +77 -0
  405. package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
  406. package/dist/shell/panel/fonts/catalog.d.ts +37 -0
  407. package/dist/shell/panel/fonts/catalog.js +68 -0
  408. package/dist/shell/panel/fonts/catalog.js.map +1 -0
  409. package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
  410. package/dist/shell/panel/index.d.ts +20 -0
  411. package/dist/shell/panel/index.js +34 -0
  412. package/dist/shell/panel/index.js.map +1 -0
  413. package/dist/shell/panel/languageModel.d.ts +5 -0
  414. package/dist/shell/panel/languageModel.js +7 -0
  415. package/dist/shell/panel/languageModel.js.map +1 -0
  416. package/dist/shell/panel/make.css +73 -0
  417. package/dist/shell/panel/makeModel.d.ts +32 -0
  418. package/dist/shell/panel/makeModel.js +84 -0
  419. package/dist/shell/panel/makeModel.js.map +1 -0
  420. package/dist/shell/panel/markdown.d.ts +46 -0
  421. package/dist/shell/panel/markdown.js +100 -0
  422. package/dist/shell/panel/markdown.js.map +1 -0
  423. package/dist/shell/panel/nav.d.ts +12 -0
  424. package/dist/shell/panel/nav.js +50 -0
  425. package/dist/shell/panel/nav.js.map +1 -0
  426. package/dist/shell/panel/panel.css +401 -0
  427. package/dist/shell/panel/panelMessages.d.ts +803 -0
  428. package/dist/shell/panel/panelMessages.js +779 -0
  429. package/dist/shell/panel/panelMessages.js.map +1 -0
  430. package/dist/shell/panel/plugins.css +59 -0
  431. package/dist/shell/panel/setupModel.d.ts +87 -0
  432. package/dist/shell/panel/setupModel.js +152 -0
  433. package/dist/shell/panel/setupModel.js.map +1 -0
  434. package/dist/shell/panel/site.d.ts +259 -0
  435. package/dist/shell/panel/site.js +25 -0
  436. package/dist/shell/panel/site.js.map +1 -0
  437. package/dist/shell/panel/strings.css +7 -0
  438. package/dist/shell/panel/themes.d.ts +10 -0
  439. package/dist/shell/panel/themes.js +8 -0
  440. package/dist/shell/panel/themes.js.map +1 -0
  441. package/dist/shell/profileModel.d.ts +3 -2
  442. package/dist/shell/profileModel.js +7 -5
  443. package/dist/shell/profileModel.js.map +1 -1
  444. package/dist/shell/store.css +250 -0
  445. package/dist/shell/storeMessages.d.ts +193 -0
  446. package/dist/shell/storeMessages.js +196 -0
  447. package/dist/shell/storeMessages.js.map +1 -0
  448. package/dist/shell/storeModel.d.ts +205 -0
  449. package/dist/shell/storeModel.js +146 -0
  450. package/dist/shell/storeModel.js.map +1 -0
  451. package/dist/shell/stringPacksModel.d.ts +44 -0
  452. package/dist/shell/stringPacksModel.js +99 -0
  453. package/dist/shell/stringPacksModel.js.map +1 -0
  454. package/dist/shell/updateModel.d.ts +2 -1
  455. package/dist/shell/updateModel.js +5 -4
  456. package/dist/shell/updateModel.js.map +1 -1
  457. package/dist/shell/windowControls.d.ts +4 -0
  458. package/dist/shell/windowControls.js +5 -0
  459. package/dist/shell/windowControls.js.map +1 -1
  460. package/i18n-config.schema.json +29 -0
  461. package/i18n-meta.schema.json +26 -0
  462. package/i18n.schema.json +42 -0
  463. package/icons.schema.json +655 -0
  464. package/languages.schema.json +23 -0
  465. package/locales/ar-x-fm.json +11 -0
  466. package/locales/ar.json +1388 -0
  467. package/locales/bg.json +1387 -0
  468. package/locales/bn.json +1387 -0
  469. package/locales/ca.json +1387 -0
  470. package/locales/cs.json +1387 -0
  471. package/locales/da.json +1387 -0
  472. package/locales/de.json +1387 -0
  473. package/locales/el.json +1387 -0
  474. package/locales/en-GB.json +27 -0
  475. package/locales/en.json +1386 -0
  476. package/locales/en.meta.json +51 -0
  477. package/locales/es.json +1387 -0
  478. package/locales/eu.json +1387 -0
  479. package/locales/fa.json +1388 -0
  480. package/locales/fi.json +1387 -0
  481. package/locales/fil.json +1387 -0
  482. package/locales/fr.json +1387 -0
  483. package/locales/ga.json +1387 -0
  484. package/locales/gl.json +1387 -0
  485. package/locales/gu.json +1387 -0
  486. package/locales/ha.json +1387 -0
  487. package/locales/he.json +1388 -0
  488. package/locales/hi.json +1387 -0
  489. package/locales/hr.json +1387 -0
  490. package/locales/hu.json +1387 -0
  491. package/locales/id.json +1387 -0
  492. package/locales/ig.json +1387 -0
  493. package/locales/it.json +1387 -0
  494. package/locales/ja.json +1387 -0
  495. package/locales/kn.json +1387 -0
  496. package/locales/ko.json +1387 -0
  497. package/locales/mr.json +1387 -0
  498. package/locales/ms.json +1387 -0
  499. package/locales/nb.json +1387 -0
  500. package/locales/nl.json +1387 -0
  501. package/locales/pl.json +1387 -0
  502. package/locales/pt.json +1387 -0
  503. package/locales/ro.json +1387 -0
  504. package/locales/ru.json +1387 -0
  505. package/locales/sk.json +1387 -0
  506. package/locales/sr.json +1387 -0
  507. package/locales/sv.json +1387 -0
  508. package/locales/ta.json +1387 -0
  509. package/locales/th.json +1387 -0
  510. package/locales/tr.json +1387 -0
  511. package/locales/uk.json +1387 -0
  512. package/locales/ur.json +1388 -0
  513. package/locales/vi.json +1387 -0
  514. package/locales/yo.json +1387 -0
  515. package/locales/zh-Hans.json +1387 -0
  516. package/locales/zh-Hant.json +1387 -0
  517. package/package.json +138 -5
  518. package/store-catalog.schema.json +78 -0
  519. package/theme.schema.json +4668 -0
  520. package/windows/installer.nsi +946 -0
  521. package/windows/languages/Basque.nsh +28 -0
  522. package/windows/languages/Catalan.nsh +28 -0
  523. package/windows/languages/Croatian.nsh +28 -0
  524. package/windows/languages/Czech.nsh +28 -0
  525. package/windows/languages/Danish.nsh +28 -0
  526. package/windows/languages/Finnish.nsh +28 -0
  527. package/windows/languages/Galician.nsh +28 -0
  528. package/windows/languages/Greek.nsh +28 -0
  529. package/windows/languages/Hungarian.nsh +28 -0
  530. package/windows/languages/Indonesian.nsh +28 -0
  531. package/windows/languages/Irish.nsh +28 -0
  532. package/windows/languages/Malay.nsh +28 -0
  533. package/windows/languages/Polish.nsh +28 -0
  534. package/windows/languages/Romanian.nsh +28 -0
  535. package/windows/languages/Serbian.nsh +28 -0
  536. package/windows/languages/Slovak.nsh +28 -0
  537. package/windows/languages/Thai.nsh +28 -0
@@ -0,0 +1,437 @@
1
+ // `waybetter release windows|macos`: a signed native release of a wayBetter app and its update
2
+ // manifest (`latest.json`). It never uploads anything: it prints the exact upload steps for the
3
+ // owner to run. Configured by the app's `waybetter.release.json` (found from the working directory
4
+ // up, or `--config <file>`):
5
+ //
6
+ // {
7
+ // "product": "wayBetter for X", // names in messages
8
+ // "artifact": "wayBetter-for-X", // space-free file names on the CDN
9
+ // "desktopDir": "apps/desktop", // the Tauri app (package.json, src-tauri/)
10
+ // "keysDir": "~/.better-twttr-keys", // holds native.key (minisign); never committed
11
+ // "keysDirEnv": "BT_KEYS_DIR", // env override of keysDir
12
+ // "cdnBase": "https://cdn1.crt.fyi/better-twttr",
13
+ // "apiBase": "https://twttr.crt.fyi", // the update API (verification steps)
14
+ // "outDir": "releases", // releases/upload (files), releases/native/latest.json
15
+ // "manifestValidator": { "module": "packages/contracts/dist/index.js", "export": "NativeRelease",
16
+ // "hint": "build packages/contracts first" }, // optional, zod-like .parse
17
+ // "prepareCommand": "bun install --frozen-lockfile", // remote/WSL builds: runs first in the unpacked sources
18
+ // "distribution": { "publisher": "CRT", "id": "CRT.Name", "homepage": "https://...", "license": "...", "shortDescription": "...", "downloadBase": "https://..." },
19
+ // // manifests written after each release step (see cli/manifests.mjs)
20
+ // "exportExclude": ["verification"] // remote/WSL builds: app-repo paths left out of the upload
21
+ // }
22
+ //
23
+ // The Windows build runs with the path-free build environment (cli/buildenv.mjs). Every artifact
24
+ // (the installer, the main binary, the front end, the dmg and the updater bundle) goes through the
25
+ // optional release check (cli/releasecheck.mjs, WAYBETTER_RELEASE_CHECK) before anything is
26
+ // copied, signed or written.
27
+ //
28
+ // The private key is read only into the build's environment (Windows) or handed to the Tauri
29
+ // signer by path (macOS). Nothing here prints, copies or moves it.
30
+ import { spawnSync } from 'node:child_process';
31
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
32
+ import { homedir } from 'node:os';
33
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
34
+ import { pathToFileURL } from 'node:url';
35
+ import { pathFreeBuildEnv } from './buildenv.mjs';
36
+ import { runReleaseCheck } from './releasecheck.mjs';
37
+ import { CHANNELS, resolveSpec, writeManifests } from './manifests.mjs';
38
+ import { buildLinuxWsl, buildMacRemote, scanBuilt } from './remote.mjs';
39
+
40
+ export const CONFIG_FILE = 'waybetter.release.json';
41
+
42
+ export const RELEASE_USAGE = `Usage:
43
+ waybetter release windows [--skip-build] [--notes "text"] [--config <file>]
44
+ Signed NSIS build (Tauri, updater artifacts), the installer and .sig in <outDir>/upload,
45
+ <outDir>/native/latest.json (other platforms of the same version kept), upload steps printed.
46
+ waybetter release macos --dmg <file.dmg> --updater <file.app.tar.gz> [--arch universal] [--config <file>]
47
+ Signs the updater bundle of a universal macOS build here, copies both into <outDir>/upload and
48
+ adds darwin-aarch64 and darwin-x86_64 to latest.json (run the Windows step first).
49
+ waybetter release macos --remote <user@host> [--ssh-key <file>] [--remote-dir <dir>] [--commit <ref>] [--build-only]
50
+ Builds the COMMITTED state (HEAD, or --commit <ref>, and the submodules at their recorded commits, exported with
51
+ git archive, never the working tree) on a Mac over SSH, universal and ad-hoc signed, without
52
+ a build path in it; brings the .dmg and .app.tar.gz to <outDir>/build/macos, scans them here,
53
+ then (unless --build-only) continues as above. The built .app stays in the remote work
54
+ folder (<remote-dir>/out); nothing is installed or replaced on the Mac. Env: WAYBETTER_MAC_SSH (user@host), WAYBETTER_MAC_SSH_KEY.
55
+ waybetter release linux --wsl [<distro>] [--remote-dir <dir>] [--commit <ref>] [--build-only]
56
+ Builds the committed state in WSL (default distro Ubuntu-22.04, or WAYBETTER_WSL_DISTRO): the
57
+ AppImage and the .deb in <outDir>/build/linux, scanned here; then (unless --build-only) the
58
+ same as \`release linux --appimage\`.
59
+ waybetter release linux --appimage <file.AppImage> --deb <file.deb> [--config <file>]
60
+ Signs the AppImage (the Linux update payload) here, copies both into <outDir>/upload and adds
61
+ linux-x86_64 to latest.json (run the Windows step first).
62
+
63
+ Config: ${CONFIG_FILE} in the app's root (product, artifact, desktopDir, keysDir, keysDirEnv,
64
+ cdnBase, apiBase, outDir, optional manifestValidator). Env: CARGO_TARGET_DIR, CDN_BASE,
65
+ DEPLOY_TARGET, CDN_DIR, RELEASES_DIR, WAYBETTER_RELEASE_CHECK (an optional command run on every
66
+ artifact first). The build is path-free (waybetter build-env). Nothing is ever uploaded.`;
67
+
68
+ class ReleaseError extends Error {}
69
+ const fail = message => { throw new ReleaseError(message); };
70
+
71
+ /** Finds and reads the release config: `--config`, else the nearest waybetter.release.json. */
72
+ export function loadReleaseConfig(cwd, file) {
73
+ let path = file ? resolve(cwd, file) : undefined;
74
+ if (!path) {
75
+ for (let dir = resolve(cwd); ; dir = dirname(dir)) {
76
+ if (existsSync(join(dir, CONFIG_FILE))) { path = join(dir, CONFIG_FILE); break; }
77
+ if (dirname(dir) === dir) fail(`no ${CONFIG_FILE} in ${cwd} or above (or pass --config)`);
78
+ }
79
+ }
80
+ if (!existsSync(path)) fail(`config not found: ${path}`);
81
+ let raw;
82
+ try { raw = JSON.parse(readFileSync(path, 'utf8')); } catch (error) { fail(`${path}: ${error.message}`); }
83
+ return normalizeReleaseConfig(raw, dirname(path));
84
+ }
85
+
86
+ const home = value => value.replace(/^~(?=$|[\\/])/, homedir());
87
+
88
+ /** Validated config with absolute paths (`root`: the folder holding the config file). */
89
+ export function normalizeReleaseConfig(raw, root) {
90
+ const text = (key, fallback) => {
91
+ const value = raw[key] ?? fallback;
92
+ if (typeof value !== 'string' || !value.trim()) fail(`${CONFIG_FILE}: "${key}" must be a non-empty string`);
93
+ return value.trim();
94
+ };
95
+ const url = key => {
96
+ const value = text(key).replace(/\/+$/, '');
97
+ if (!/^https:\/\/[^\s/]+/.test(value)) fail(`${CONFIG_FILE}: "${key}" must be an https URL`);
98
+ return value;
99
+ };
100
+ const artifact = text('artifact');
101
+ if (!/^[A-Za-z0-9._-]+$/.test(artifact)) fail(`${CONFIG_FILE}: "artifact" must be a space-free file name part`);
102
+ const validator = raw.manifestValidator;
103
+ if (validator !== undefined && (typeof validator?.module !== 'string' || typeof validator?.export !== 'string')) {
104
+ fail(`${CONFIG_FILE}: "manifestValidator" needs "module" and "export"`);
105
+ }
106
+ const at = value => (isAbsolute(value) ? value : resolve(root, value));
107
+ const desktopDir = at(text('desktopDir'));
108
+ return {
109
+ root,
110
+ product: text('product'),
111
+ artifact,
112
+ desktopDir,
113
+ tauriDir: join(desktopDir, 'src-tauri'),
114
+ keysDir: at(home(text('keysDir'))),
115
+ keysDirEnv: raw.keysDirEnv === undefined ? undefined : text('keysDirEnv'),
116
+ keyFile: text('keyFile', 'native.key'),
117
+ cdnBase: url('cdnBase'),
118
+ apiBase: url('apiBase'),
119
+ outDir: at(text('outDir', 'releases')),
120
+ buildCommand: text('buildCommand', 'bun run tauri build'),
121
+ prepareCommand: text('prepareCommand', 'bun install --frozen-lockfile'),
122
+ distribution: raw.distribution,
123
+ exportExclude: Array.isArray(raw.exportExclude) ? raw.exportExclude.map(String) : [],
124
+ manifestValidator: validator && { module: at(validator.module), export: validator.export, hint: validator.hint },
125
+ };
126
+ }
127
+
128
+ function keyPath(config, env) {
129
+ const dir = (config.keysDirEnv && env[config.keysDirEnv]) || config.keysDir;
130
+ return join(home(dir), config.keyFile);
131
+ }
132
+
133
+ /** The shape every update manifest must have (also when the app adds its own validator). */
134
+ export function checkManifest(manifest) {
135
+ if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(manifest.version ?? '')) fail(`manifest: bad version ${manifest.version}`);
136
+ if (typeof manifest.notes !== 'string' || typeof manifest.pubDate !== 'string') fail('manifest: notes and pubDate must be strings');
137
+ const platforms = Object.entries(manifest.platforms ?? {});
138
+ if (!platforms.length) fail('manifest: no platforms');
139
+ for (const [key, entry] of platforms) {
140
+ if (!/^(windows|darwin|linux)-(x86_64|aarch64|i686|armv7)$/.test(key)) fail(`manifest: unknown platform ${key}`);
141
+ if (!/^https:\/\/\S+$/.test(entry?.url ?? '')) fail(`manifest: ${key} url must be https`);
142
+ if (typeof entry.signature !== 'string' || !entry.signature.trim()) fail(`manifest: ${key} has no signature`);
143
+ }
144
+ return manifest;
145
+ }
146
+
147
+ async function validate(config, manifest) {
148
+ checkManifest(manifest);
149
+ if (!config.manifestValidator) return manifest;
150
+ const { module, export: name, hint } = config.manifestValidator;
151
+ const loaded = await import(pathToFileURL(module).href).catch(() => fail(hint || `cannot load ${module}`));
152
+ const schema = loaded[name];
153
+ if (!schema || typeof schema.parse !== 'function') fail(`${module} has no ${name}.parse`);
154
+ return schema.parse(manifest);
155
+ }
156
+
157
+ function readVersion(config) {
158
+ const version = JSON.parse(readFileSync(join(config.root, 'package.json'), 'utf8')).version;
159
+ const conf = JSON.parse(readFileSync(join(config.tauriDir, 'tauri.conf.json'), 'utf8'));
160
+ const cargo = /^version\s*=\s*"([^"]+)"/m.exec(readFileSync(join(config.tauriDir, 'Cargo.toml'), 'utf8'))?.[1];
161
+ const desktop = JSON.parse(readFileSync(join(config.desktopDir, 'package.json'), 'utf8')).version;
162
+ const rel = path => relative(config.root, path).replaceAll('\\', '/');
163
+ for (const [name, value] of [
164
+ [rel(join(config.tauriDir, 'tauri.conf.json')), conf.version],
165
+ [rel(join(config.tauriDir, 'Cargo.toml')), cargo],
166
+ [rel(join(config.desktopDir, 'package.json')), desktop],
167
+ ]) {
168
+ if (value !== version) fail(`${name} has version ${value}, root package.json has ${version}. Sync them first.`);
169
+ }
170
+ const dist = typeof conf.build?.frontendDist === 'string' && !/^https?:/.test(conf.build.frontendDist) ? resolve(config.tauriDir, conf.build.frontendDist) : undefined;
171
+ const binary = conf.mainBinaryName ?? /^name\s*=\s*"([^"]+)"/m.exec(readFileSync(join(config.tauriDir, 'Cargo.toml'), 'utf8'))?.[1];
172
+ return { version, productName: conf.productName, binary, dist };
173
+ }
174
+
175
+ /** The optional release check (cli/releasecheck.mjs) over every artifact that exists. */
176
+ function gate(config, paths, env, log) {
177
+ runReleaseCheck(paths.filter(path => path && existsSync(path)), { env, log, label: 'release: check' });
178
+ }
179
+
180
+ function option(args, name) {
181
+ const i = args.indexOf(name);
182
+ return i >= 0 ? args[i + 1] : undefined;
183
+ }
184
+
185
+ const pubDate = () => new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
186
+
187
+ /**
188
+ * Distribution manifests (winget, Chocolatey, Homebrew, AUR) for the installers now in
189
+ * <outDir>/upload, written to <outDir>/distribution/<version>. Needs "distribution" in the config
190
+ * and the public download URL (--download-base, WAYBETTER_DOWNLOAD_BASE or distribution.downloadBase):
191
+ * without it nothing is written, because that URL is not ours to guess.
192
+ */
193
+ export function writeDistribution(config, version, args, { env = process.env, log = console.log } = {}) {
194
+ const d = config.distribution;
195
+ if (!d) return undefined;
196
+ const base = option(args, '--download-base') ?? env.WAYBETTER_DOWNLOAD_BASE ?? d.downloadBase;
197
+ if (!base) {
198
+ log('manifests: skipped: the public download URL is not known yet (pass --download-base <url>, or set WAYBETTER_DOWNLOAD_BASE); run the release step again or `waybetter manifests` once it is');
199
+ return undefined;
200
+ }
201
+ const upload = join(config.outDir, 'upload');
202
+ const found = name => (existsSync(join(upload, name)) ? { file: join(upload, name) } : undefined);
203
+ const exe = found(`${config.artifact}_${version}_x64-setup.exe`);
204
+ const dmg = found(`${config.artifact}_${version}_universal.dmg`);
205
+ const deb = found(`${config.artifact}_${version}_amd64.deb`);
206
+ const appImage = found(`${config.artifact}_${version}_amd64.AppImage`);
207
+ const spec = resolveSpec({
208
+ ...d,
209
+ name: d.name ?? config.product,
210
+ version,
211
+ windows: exe && { ...d.windows, ...exe },
212
+ macos: dmg && { ...d.macos, ...dmg },
213
+ linux: (deb || appImage) && { ...d.linux, ...(deb && { deb }), ...(appImage && { appImage }) },
214
+ }, { baseDir: config.root, downloadBase: base });
215
+ const out = join(config.outDir, 'distribution', version);
216
+ const { written, skipped } = writeManifests(spec, out, { only: CHANNELS });
217
+ log(`manifests: ${written.length} file(s) in ${relative(config.root, out).replaceAll('\\', '/')}${skipped.length ? ` (${skipped.join(', ')}: no installer for that platform yet)` : ''}`);
218
+ return { out, written, skipped };
219
+ }
220
+
221
+ /** `waybetter release windows`. */
222
+ export async function releaseWindows(config, args, { env = process.env, log = console.log } = {}) {
223
+ const { version, productName, binary, dist } = readVersion(config);
224
+ log(`release: ${config.product} ${version}`);
225
+
226
+ // Signed build (updater artifacts need the minisign private key; its password is empty).
227
+ const targetDir = env.CARGO_TARGET_DIR ? resolve(env.CARGO_TARGET_DIR) : join(config.tauriDir, 'target');
228
+ const bundleDir = join(targetDir, 'release', 'bundle', 'nsis');
229
+ if (!args.includes('--skip-build')) {
230
+ const key = keyPath(config, env);
231
+ if (!existsSync(key)) fail(`signing key not found at ${key}`);
232
+ // A fixed command string from the app's own config (no user input), so the shell is safe.
233
+ const result = spawnSync(config.buildCommand, {
234
+ cwd: config.desktopDir,
235
+ stdio: 'inherit',
236
+ shell: true,
237
+ env: { ...env, ...pathFreeBuildEnv({ root: config.root, env }).env, TAURI_SIGNING_PRIVATE_KEY: readFileSync(key, 'utf8').trim(), TAURI_SIGNING_PRIVATE_KEY_PASSWORD: '' },
238
+ });
239
+ if (result.status !== 0) fail(`tauri build failed (exit ${result.status})`);
240
+ }
241
+
242
+ // The NSIS installer is also the updater payload (createUpdaterArtifacts, v2 format).
243
+ if (!existsSync(bundleDir)) fail(`no NSIS bundle folder at ${bundleDir}`);
244
+ // Exactly the current productName: the folder may still hold installers built under an older name.
245
+ const installer = readdirSync(bundleDir).find(name => name === `${productName}_${version}_x64-setup.exe`);
246
+ if (!installer) fail(`no x64 setup.exe for ${version} in ${bundleDir}`);
247
+ const sigPath = join(bundleDir, `${installer}.sig`);
248
+ if (!existsSync(sigPath)) fail(`missing ${installer}.sig (was TAURI_SIGNING_PRIVATE_KEY set?)`);
249
+ // Before anything is copied or written: the installer (opened), and what went into it.
250
+ gate(config, [join(bundleDir, installer), sigPath, binary && join(targetDir, 'release', `${binary}.exe`), dist], env, log);
251
+
252
+ const uploadDir = join(config.outDir, 'upload');
253
+ mkdirSync(join(config.outDir, 'native'), { recursive: true });
254
+ mkdirSync(uploadDir, { recursive: true });
255
+ // Versioned, space-free names: immutable on the CDN and safe in URLs.
256
+ const fileName = `${config.artifact}_${version}_x64-setup.exe`;
257
+ copyFileSync(join(bundleDir, installer), join(uploadDir, fileName));
258
+ copyFileSync(sigPath, join(uploadDir, `${fileName}.sig`));
259
+
260
+ const cdnBase = (env.CDN_BASE ?? config.cdnBase).replace(/\/+$/, '');
261
+ const manifestPath = join(config.outDir, 'native', 'latest.json');
262
+ // macOS and Linux entries of the same version are kept.
263
+ let others = {};
264
+ try {
265
+ const previous = JSON.parse(readFileSync(manifestPath, 'utf8'));
266
+ if (previous.version === version) others = Object.fromEntries(Object.entries(previous.platforms ?? {}).filter(([key]) => key !== 'windows-x86_64'));
267
+ } catch { /* no previous manifest */ }
268
+ const manifest = await validate(config, {
269
+ version,
270
+ notes: option(args, '--notes') ?? '',
271
+ pubDate: pubDate(),
272
+ platforms: { ...others, 'windows-x86_64': { url: `${cdnBase}/${fileName}`, signature: readFileSync(sigPath, 'utf8').trim() } },
273
+ });
274
+ writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
275
+ log(`release: wrote ${manifestPath}`);
276
+
277
+ // Installer first, manifest last, so clients never see a manifest pointing at a missing file.
278
+ const target = env.DEPLOY_TARGET ?? '<user>@<host>';
279
+ const cdnDir = env.CDN_DIR ?? `<cdn folder served at ${cdnBase.replace(/^https:\/\//, '')}>`;
280
+ const releasesDir = env.RELEASES_DIR ?? '<API RELEASES_DIR>';
281
+ const rel = path => relative(config.root, path).replaceAll('\\', '/');
282
+ log(`
283
+ Nothing was uploaded. Run these steps yourself, in this order:
284
+
285
+ 1. Upload the installer and its signature to the CDN:
286
+ scp "${rel(join(uploadDir, fileName))}" "${rel(join(uploadDir, `${fileName}.sig`))}" ${target}:${cdnDir}/
287
+
288
+ 2. Check it is reachable before publishing the manifest:
289
+ curl -sSfI ${cdnBase}/${fileName}
290
+
291
+ 3. Publish the manifest (the API hot-reloads it by mtime; no restart needed):
292
+ scp "${rel(manifestPath)}" ${target}:${releasesDir}/native/latest.json.tmp
293
+ ssh ${target} "mv ${releasesDir}/native/latest.json.tmp ${releasesDir}/native/latest.json"
294
+
295
+ 4. Verify the update endpoint answers an older client:
296
+ curl -sS ${config.apiBase}/v1/updates/windows/x86_64/0.0.0
297
+ `);
298
+ writeDistribution(config, version, args, { env, log });
299
+ return { version, manifestPath, files: [fileName, `${fileName}.sig`] };
300
+ }
301
+
302
+ /** Signs a copy in the upload folder (the signature's trusted comment names the file and binds the version). */
303
+ function signFile(config, file, version, env) {
304
+ const key = keyPath(config, env);
305
+ if (!existsSync(key)) fail(`signing key not found at ${key}`);
306
+ const exe = process.platform === 'win32' ? 'tauri.exe' : 'tauri';
307
+ const tauri = [join(config.desktopDir, 'node_modules', '.bin', exe), join(config.root, 'node_modules', '.bin', exe)].find(existsSync);
308
+ if (!tauri) fail('Tauri CLI not installed (bun install)');
309
+ const signed = spawnSync(tauri, ['signer', 'sign', '-f', key, '-p', '', '--app-version', version, file], {
310
+ stdio: ['ignore', 'ignore', 'inherit'], // stdout would echo the signature; the .sig file holds it
311
+ });
312
+ if (signed.status !== 0) fail(`tauri signer sign failed (exit ${signed.status})`);
313
+ const sigPath = `${file}.sig`;
314
+ if (!existsSync(sigPath)) fail(`signer wrote no ${sigPath}`);
315
+ return sigPath;
316
+ }
317
+
318
+ /** `waybetter release macos`: adds a universal macOS build (built unsigned on the Mac) to the release. */
319
+ export async function releaseMacos(config, args, { env = process.env, log = console.log } = {}) {
320
+ let version = JSON.parse(readFileSync(join(config.root, 'package.json'), 'utf8')).version;
321
+ let dmg = option(args, '--dmg');
322
+ let updater = option(args, '--updater');
323
+ const target = option(args, '--remote') ?? (dmg ? undefined : env.WAYBETTER_MAC_SSH);
324
+ if (target) {
325
+ const built = buildMacRemote({ config, target, key: option(args, '--ssh-key') ?? env.WAYBETTER_MAC_SSH_KEY, remoteDir: option(args, '--remote-dir'), ref: option(args, '--commit'), env, log });
326
+ scanBuilt(config, [built.dmg, built.updater], { env, log });
327
+ if (option(args, '--commit')) version = built.version;
328
+ else if (built.version !== version) fail(`the committed version is ${built.version} but the working tree says ${version}: commit or sync first`);
329
+ if (args.includes('--build-only')) {
330
+ log(`release-macos: built ${built.sha.slice(0, 12)} in ${relative(config.root, built.dir).replaceAll('\\', '/')} (scanned, not signed)`);
331
+ return { version, dir: built.dir, files: [built.dmg, built.updater] };
332
+ }
333
+ dmg = built.dmg;
334
+ updater = built.updater;
335
+ }
336
+ const arch = option(args, '--arch') ?? 'universal';
337
+ if (!dmg || !updater) fail('usage: --dmg <file.dmg> --updater <file.app.tar.gz> [--arch universal]');
338
+ if (arch !== 'universal') fail('only universal builds are supported (one file serves both darwin arches)');
339
+ for (const file of [dmg, updater]) if (!existsSync(file)) fail(`not found: ${file}`);
340
+ if (!updater.endsWith('.app.tar.gz')) fail('--updater must be the .app.tar.gz Tauri wrote');
341
+ gate(config, [resolve(dmg), resolve(updater)], env, log);
342
+
343
+ const uploadDir = join(config.outDir, 'upload');
344
+ mkdirSync(uploadDir, { recursive: true });
345
+ const dmgName = `${config.artifact}_${version}_${arch}.dmg`;
346
+ const updaterName = `${config.artifact}_${version}_${arch}.app.tar.gz`;
347
+ copyFileSync(dmg, join(uploadDir, dmgName));
348
+ copyFileSync(updater, join(uploadDir, updaterName));
349
+
350
+ const sigPath = signFile(config, join(uploadDir, updaterName), version, env);
351
+
352
+ const manifestPath = join(config.outDir, 'native', 'latest.json');
353
+ if (!existsSync(manifestPath)) fail(`no ${relative(config.root, manifestPath)}: run \`waybetter release windows\` first`);
354
+ const current = JSON.parse(readFileSync(manifestPath, 'utf8'));
355
+ if (current.version !== version) fail(`latest.json is ${current.version}, this build is ${version}`);
356
+ const cdnBase = (env.CDN_BASE ?? config.cdnBase).replace(/\/+$/, '');
357
+ const entry = { url: `${cdnBase}/${updaterName}`, signature: readFileSync(sigPath, 'utf8').trim() };
358
+ const manifest = await validate(config, { ...current, platforms: { ...current.platforms, 'darwin-aarch64': entry, 'darwin-x86_64': entry } });
359
+ writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
360
+ log(`release-macos: ${dmgName}, ${updaterName} (+ .sig) in ${relative(config.root, uploadDir).replaceAll('\\', '/')}; latest.json now has ${Object.keys(manifest.platforms).join(', ')}`);
361
+ log(`
362
+ Nothing was uploaded. Upload the dmg, the updater bundle and its .sig to the CDN next to the
363
+ Windows installer (same target and folder as \`waybetter release windows\` prints), check
364
+ curl -sSfI ${cdnBase}/${updaterName}
365
+ then publish latest.json the same way (tmp file, then mv), and verify
366
+ curl -sS ${config.apiBase}/v1/updates/darwin/aarch64/0.0.0
367
+ curl -sS ${config.apiBase}/v1/updates/darwin/x86_64/0.0.0
368
+ `);
369
+ writeDistribution(config, version, args, { env, log });
370
+ return { version, manifestPath, files: [dmgName, updaterName, `${updaterName}.sig`] };
371
+ }
372
+
373
+ /** `waybetter release linux`: adds the AppImage (signed here: it is the update payload) and the .deb. */
374
+ export async function releaseLinux(config, args, { env = process.env, log = console.log } = {}) {
375
+ let version = JSON.parse(readFileSync(join(config.root, 'package.json'), 'utf8')).version;
376
+ let appimage = option(args, '--appimage');
377
+ let deb = option(args, '--deb');
378
+ if (args.includes('--wsl')) {
379
+ const next = args[args.indexOf('--wsl') + 1];
380
+ const distro = next && !next.startsWith('--') ? next : env.WAYBETTER_WSL_DISTRO;
381
+ const built = buildLinuxWsl({ config, distro, remoteDir: option(args, '--remote-dir'), ref: option(args, '--commit'), env, log });
382
+ scanBuilt(config, [built.appimage, built.deb], { env, log });
383
+ if (option(args, '--commit')) version = built.version;
384
+ else if (built.version !== version) fail(`the committed version is ${built.version} but the working tree says ${version}: commit or sync first`);
385
+ if (args.includes('--build-only')) {
386
+ log(`release-linux: built ${built.sha.slice(0, 12)} in ${relative(config.root, built.dir).replaceAll('\\', '/')} (scanned, not signed)`);
387
+ return { version, dir: built.dir, files: [built.appimage, built.deb] };
388
+ }
389
+ appimage = built.appimage;
390
+ deb = built.deb;
391
+ }
392
+ if (!appimage || !deb) fail('usage: --appimage <file.AppImage> --deb <file.deb> (or --wsl)');
393
+ for (const file of [appimage, deb]) if (!existsSync(file)) fail(`not found: ${file}`);
394
+ if (!appimage.endsWith('.AppImage')) fail('--appimage must be the .AppImage Tauri wrote');
395
+ if (!deb.endsWith('.deb')) fail('--deb must be the .deb Tauri wrote');
396
+ gate(config, [resolve(appimage), resolve(deb)], env, log);
397
+
398
+ const uploadDir = join(config.outDir, 'upload');
399
+ mkdirSync(uploadDir, { recursive: true });
400
+ const appimageName = `${config.artifact}_${version}_amd64.AppImage`;
401
+ const debName = `${config.artifact}_${version}_amd64.deb`;
402
+ copyFileSync(appimage, join(uploadDir, appimageName));
403
+ copyFileSync(deb, join(uploadDir, debName));
404
+ const sigPath = signFile(config, join(uploadDir, appimageName), version, env);
405
+
406
+ const manifestPath = join(config.outDir, 'native', 'latest.json');
407
+ if (!existsSync(manifestPath)) fail(`no ${relative(config.root, manifestPath)}: run \`waybetter release windows\` first`);
408
+ const current = JSON.parse(readFileSync(manifestPath, 'utf8'));
409
+ if (current.version !== version) fail(`latest.json is ${current.version}, this build is ${version}`);
410
+ const cdnBase = (env.CDN_BASE ?? config.cdnBase).replace(/\/+$/, '');
411
+ const entry = { url: `${cdnBase}/${appimageName}`, signature: readFileSync(sigPath, 'utf8').trim() };
412
+ const manifest = await validate(config, { ...current, platforms: { ...current.platforms, 'linux-x86_64': entry } });
413
+ writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
414
+ log(`release-linux: ${appimageName} (+ .sig), ${debName} in ${relative(config.root, uploadDir).replaceAll('\\', '/')}; latest.json now has ${Object.keys(manifest.platforms).join(', ')}`);
415
+ log(`
416
+ Nothing was uploaded. Upload the AppImage, its .sig and the .deb to the CDN next to the Windows
417
+ installer (same target and folder as \`waybetter release windows\` prints), check
418
+ curl -sSfI ${cdnBase}/${appimageName}
419
+ then publish latest.json the same way (tmp file, then mv), and verify
420
+ curl -sS ${config.apiBase}/v1/updates/linux/x86_64/0.0.0
421
+ `);
422
+ writeDistribution(config, version, args, { env, log });
423
+ return { version, manifestPath, files: [appimageName, `${appimageName}.sig`, debName] };
424
+ }
425
+
426
+ /** `waybetter release <windows|macos|linux> ...` from the command line (or an app's wrapper script). */
427
+ export async function releaseCommand(args, { cwd = process.cwd(), env = process.env, log = console.log } = {}) {
428
+ const [platform, ...rest] = args;
429
+ if (platform !== 'windows' && platform !== 'macos' && platform !== 'linux') {
430
+ log(RELEASE_USAGE);
431
+ if (platform && platform !== '--help' && platform !== '-h') fail(`unknown release target ${platform}`);
432
+ return undefined;
433
+ }
434
+ const config = loadReleaseConfig(cwd, option(rest, '--config'));
435
+ const release = { windows: releaseWindows, macos: releaseMacos, linux: releaseLinux }[platform];
436
+ return release(config, rest, { env, log });
437
+ }
@@ -0,0 +1,15 @@
1
+ // An optional, owner-supplied check run on every artifact before a release copies, signs or writes
2
+ // anything: WAYBETTER_RELEASE_CHECK names a command (run through the shell) that gets the artifact
3
+ // paths as arguments. A non-zero exit stops the release. Unset, nothing runs.
4
+ import { spawnSync } from 'node:child_process';
5
+
6
+ export const RELEASE_CHECK_ENV = 'WAYBETTER_RELEASE_CHECK';
7
+
8
+ export function runReleaseCheck(paths, { env = process.env, log = console.log, label = 'release check' } = {}) {
9
+ const command = env[RELEASE_CHECK_ENV];
10
+ if (!command || !paths.length) return;
11
+ const quoted = paths.map(path => `'${String(path).replaceAll("'", "'\\''")}'`).join(' ');
12
+ log(`${label}: ${paths.length} file(s)`);
13
+ const result = spawnSync(`${command} ${quoted}`, { shell: true, stdio: 'inherit', env });
14
+ if (result.status !== 0) throw new Error(`${label} failed (exit ${result.status ?? result.signal})`);
15
+ }