waybetter 0.1.1 → 0.6.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 (515) hide show
  1. package/README.md +140 -6
  2. package/bin/waybetter.mjs +46 -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/privacy.mjs +768 -0
  9. package/cli/release.mjs +444 -0
  10. package/cli/remote.mjs +260 -0
  11. package/cli/store.mjs +326 -0
  12. package/cli/strings.mjs +121 -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 +59 -0
  74. package/dist/runtime/stringPackTranslate.js +264 -0
  75. package/dist/runtime/stringPackTranslate.js.map +1 -0
  76. package/dist/runtime/stringPacks.d.ts +200 -0
  77. package/dist/runtime/stringPacks.js +474 -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/themeChoice.d.ts +52 -0
  89. package/dist/runtime/themeChoice.js +69 -0
  90. package/dist/runtime/themeChoice.js.map +1 -0
  91. package/dist/runtime/themeComponents.d.ts +435 -0
  92. package/dist/runtime/themeComponents.js +463 -0
  93. package/dist/runtime/themeComponents.js.map +1 -0
  94. package/dist/runtime/themeDecor.d.ts +73 -0
  95. package/dist/runtime/themeDecor.js +131 -0
  96. package/dist/runtime/themeDecor.js.map +1 -0
  97. package/dist/runtime/themeDoctor.d.ts +11 -0
  98. package/dist/runtime/themeDoctor.js +51 -0
  99. package/dist/runtime/themeDoctor.js.map +1 -0
  100. package/dist/runtime/themeIcons.d.ts +130 -0
  101. package/dist/runtime/themeIcons.js +263 -0
  102. package/dist/runtime/themeIcons.js.map +1 -0
  103. package/dist/runtime/themeRuntime.d.ts +100 -0
  104. package/dist/runtime/themeRuntime.js +497 -0
  105. package/dist/runtime/themeRuntime.js.map +1 -0
  106. package/dist/runtime/themeSchema.d.ts +10 -0
  107. package/dist/runtime/themeSchema.js +150 -0
  108. package/dist/runtime/themeSchema.js.map +1 -0
  109. package/dist/runtime/themeSpec.d.ts +259 -0
  110. package/dist/runtime/themeSpec.js +439 -0
  111. package/dist/runtime/themeSpec.js.map +1 -0
  112. package/dist/runtime/themeTokens.d.ts +12 -0
  113. package/dist/runtime/themeTokens.js +14 -6
  114. package/dist/runtime/themeTokens.js.map +1 -1
  115. package/dist/runtime/themeVariants.d.ts +30 -0
  116. package/dist/runtime/themeVariants.js +53 -0
  117. package/dist/runtime/themeVariants.js.map +1 -0
  118. package/dist/runtime/ui.d.ts +192 -0
  119. package/dist/runtime/ui.js +926 -0
  120. package/dist/runtime/ui.js.map +1 -0
  121. package/dist/shell/InstallDialog.d.ts +40 -0
  122. package/dist/shell/InstallDialog.js +170 -0
  123. package/dist/shell/InstallDialog.js.map +1 -0
  124. package/dist/shell/StoreView.d.ts +66 -0
  125. package/dist/shell/StoreView.js +103 -0
  126. package/dist/shell/StoreView.js.map +1 -0
  127. package/dist/shell/addressModel.js.map +1 -1
  128. package/dist/shell/chrome.js.map +1 -1
  129. package/dist/shell/deckModel.d.ts +117 -0
  130. package/dist/shell/deckModel.js +267 -0
  131. package/dist/shell/deckModel.js.map +1 -0
  132. package/dist/shell/frame/AccountSwitcher.d.ts +42 -0
  133. package/dist/shell/frame/AccountSwitcher.js +243 -0
  134. package/dist/shell/frame/AccountSwitcher.js.map +1 -0
  135. package/dist/shell/frame/AddColumnDialog.d.ts +8 -0
  136. package/dist/shell/frame/AddColumnDialog.js +81 -0
  137. package/dist/shell/frame/AddColumnDialog.js.map +1 -0
  138. package/dist/shell/frame/AppMenu.d.ts +21 -0
  139. package/dist/shell/frame/AppMenu.js +642 -0
  140. package/dist/shell/frame/AppMenu.js.map +1 -0
  141. package/dist/shell/frame/CommandPalette.d.ts +7 -0
  142. package/dist/shell/frame/CommandPalette.js +118 -0
  143. package/dist/shell/frame/CommandPalette.js.map +1 -0
  144. package/dist/shell/frame/DeckView.d.ts +13 -0
  145. package/dist/shell/frame/DeckView.js +287 -0
  146. package/dist/shell/frame/DeckView.js.map +1 -0
  147. package/dist/shell/frame/FindBar.d.ts +10 -0
  148. package/dist/shell/frame/FindBar.js +108 -0
  149. package/dist/shell/frame/FindBar.js.map +1 -0
  150. package/dist/shell/frame/MediaPanel.d.ts +8 -0
  151. package/dist/shell/frame/MediaPanel.js +76 -0
  152. package/dist/shell/frame/MediaPanel.js.map +1 -0
  153. package/dist/shell/frame/NewTabPage.d.ts +9 -0
  154. package/dist/shell/frame/NewTabPage.js +71 -0
  155. package/dist/shell/frame/NewTabPage.js.map +1 -0
  156. package/dist/shell/frame/PaneTheme.d.ts +16 -0
  157. package/dist/shell/frame/PaneTheme.js +67 -0
  158. package/dist/shell/frame/PaneTheme.js.map +1 -0
  159. package/dist/shell/frame/ReportDialog.d.ts +3 -0
  160. package/dist/shell/frame/ReportDialog.js +95 -0
  161. package/dist/shell/frame/ReportDialog.js.map +1 -0
  162. package/dist/shell/frame/Shell.d.ts +8 -0
  163. package/dist/shell/frame/Shell.js +1131 -0
  164. package/dist/shell/frame/Shell.js.map +1 -0
  165. package/dist/shell/frame/Titlebar.d.ts +16 -0
  166. package/dist/shell/frame/Titlebar.js +77 -0
  167. package/dist/shell/frame/Titlebar.js.map +1 -0
  168. package/dist/shell/frame/TitlebarExtras.d.ts +4 -0
  169. package/dist/shell/frame/TitlebarExtras.js +202 -0
  170. package/dist/shell/frame/TitlebarExtras.js.map +1 -0
  171. package/dist/shell/frame/WebPanel.d.ts +4 -0
  172. package/dist/shell/frame/WebPanel.js +182 -0
  173. package/dist/shell/frame/WebPanel.js.map +1 -0
  174. package/dist/shell/frame/accountModel.d.ts +49 -0
  175. package/dist/shell/frame/accountModel.js +67 -0
  176. package/dist/shell/frame/accountModel.js.map +1 -0
  177. package/dist/shell/frame/accountSwitcher.css +91 -0
  178. package/dist/shell/frame/appI18n.d.ts +44 -0
  179. package/dist/shell/frame/appI18n.js +64 -0
  180. package/dist/shell/frame/appI18n.js.map +1 -0
  181. package/dist/shell/frame/appMenu.css +121 -0
  182. package/dist/shell/frame/backupModel.d.ts +38 -0
  183. package/dist/shell/frame/backupModel.js +192 -0
  184. package/dist/shell/frame/backupModel.js.map +1 -0
  185. package/dist/shell/frame/boot.d.ts +8 -0
  186. package/dist/shell/frame/boot.js +35 -0
  187. package/dist/shell/frame/boot.js.map +1 -0
  188. package/dist/shell/frame/brand.d.ts +1 -0
  189. package/dist/shell/frame/brand.js +4 -0
  190. package/dist/shell/frame/brand.js.map +1 -0
  191. package/dist/shell/frame/bridge.d.ts +35 -0
  192. package/dist/shell/frame/bridge.js +70 -0
  193. package/dist/shell/frame/bridge.js.map +1 -0
  194. package/dist/shell/frame/chromeTheme.d.ts +29 -0
  195. package/dist/shell/frame/chromeTheme.js +81 -0
  196. package/dist/shell/frame/chromeTheme.js.map +1 -0
  197. package/dist/shell/frame/deck.css +209 -0
  198. package/dist/shell/frame/deckStore.d.ts +89 -0
  199. package/dist/shell/frame/deckStore.js +239 -0
  200. package/dist/shell/frame/deckStore.js.map +1 -0
  201. package/dist/shell/frame/devHost.d.ts +35 -0
  202. package/dist/shell/frame/devHost.js +80 -0
  203. package/dist/shell/frame/devHost.js.map +1 -0
  204. package/dist/shell/frame/devModel.d.ts +7 -0
  205. package/dist/shell/frame/devModel.js +17 -0
  206. package/dist/shell/frame/devModel.js.map +1 -0
  207. package/dist/shell/frame/diag.d.ts +7 -0
  208. package/dist/shell/frame/diag.js +39 -0
  209. package/dist/shell/frame/diag.js.map +1 -0
  210. package/dist/shell/frame/findBar.css +14 -0
  211. package/dist/shell/frame/frameMessages.d.ts +248 -0
  212. package/dist/shell/frame/frameMessages.js +252 -0
  213. package/dist/shell/frame/frameMessages.js.map +1 -0
  214. package/dist/shell/frame/hooks.d.ts +39 -0
  215. package/dist/shell/frame/hooks.js +97 -0
  216. package/dist/shell/frame/hooks.js.map +1 -0
  217. package/dist/shell/frame/i18n.d.ts +27 -0
  218. package/dist/shell/frame/i18n.js +66 -0
  219. package/dist/shell/frame/i18n.js.map +1 -0
  220. package/dist/shell/frame/iconPack.d.ts +11 -0
  221. package/dist/shell/frame/iconPack.js +45 -0
  222. package/dist/shell/frame/iconPack.js.map +1 -0
  223. package/dist/shell/frame/icons.d.ts +71 -0
  224. package/dist/shell/frame/icons.js +75 -0
  225. package/dist/shell/frame/icons.js.map +1 -0
  226. package/dist/shell/frame/index.d.ts +34 -0
  227. package/dist/shell/frame/index.js +43 -0
  228. package/dist/shell/frame/index.js.map +1 -0
  229. package/dist/shell/frame/language.d.ts +58 -0
  230. package/dist/shell/frame/language.js +165 -0
  231. package/dist/shell/frame/language.js.map +1 -0
  232. package/dist/shell/frame/mediaModel.d.ts +34 -0
  233. package/dist/shell/frame/mediaModel.js +53 -0
  234. package/dist/shell/frame/mediaModel.js.map +1 -0
  235. package/dist/shell/frame/menuMessages.en.json +54 -0
  236. package/dist/shell/frame/menuModel.d.ts +277 -0
  237. package/dist/shell/frame/menuModel.js +293 -0
  238. package/dist/shell/frame/menuModel.js.map +1 -0
  239. package/dist/shell/frame/paletteModel.d.ts +139 -0
  240. package/dist/shell/frame/paletteModel.js +112 -0
  241. package/dist/shell/frame/paletteModel.js.map +1 -0
  242. package/dist/shell/frame/paneTheme.css +9 -0
  243. package/dist/shell/frame/pluginCommandStore.d.ts +23 -0
  244. package/dist/shell/frame/pluginCommandStore.js +70 -0
  245. package/dist/shell/frame/pluginCommandStore.js.map +1 -0
  246. package/dist/shell/frame/reportModel.d.ts +52 -0
  247. package/dist/shell/frame/reportModel.js +105 -0
  248. package/dist/shell/frame/reportModel.js.map +1 -0
  249. package/dist/shell/frame/safeStore.d.ts +7 -0
  250. package/dist/shell/frame/safeStore.js +40 -0
  251. package/dist/shell/frame/safeStore.js.map +1 -0
  252. package/dist/shell/frame/searchInput.d.ts +2 -0
  253. package/dist/shell/frame/searchInput.js +11 -0
  254. package/dist/shell/frame/searchInput.js.map +1 -0
  255. package/dist/shell/frame/shell.css +629 -0
  256. package/dist/shell/frame/site.d.ts +206 -0
  257. package/dist/shell/frame/site.js +22 -0
  258. package/dist/shell/frame/site.js.map +1 -0
  259. package/dist/shell/frame/state.d.ts +99 -0
  260. package/dist/shell/frame/state.js +284 -0
  261. package/dist/shell/frame/state.js.map +1 -0
  262. package/dist/shell/frame/syncGate.d.ts +10 -0
  263. package/dist/shell/frame/syncGate.js +36 -0
  264. package/dist/shell/frame/syncGate.js.map +1 -0
  265. package/dist/shell/frame/syncHost.d.ts +35 -0
  266. package/dist/shell/frame/syncHost.js +85 -0
  267. package/dist/shell/frame/syncHost.js.map +1 -0
  268. package/dist/shell/frame/tabStill.d.ts +2 -0
  269. package/dist/shell/frame/tabStill.js +62 -0
  270. package/dist/shell/frame/tabStill.js.map +1 -0
  271. package/dist/shell/frame/themeScopes.d.ts +29 -0
  272. package/dist/shell/frame/themeScopes.js +61 -0
  273. package/dist/shell/frame/themeScopes.js.map +1 -0
  274. package/dist/shell/frame/themeStore.d.ts +99 -0
  275. package/dist/shell/frame/themeStore.js +252 -0
  276. package/dist/shell/frame/themeStore.js.map +1 -0
  277. package/dist/shell/frame/windowBinding.d.ts +2 -0
  278. package/dist/shell/frame/windowBinding.js +7 -0
  279. package/dist/shell/frame/windowBinding.js.map +1 -0
  280. package/dist/shell/frame/workspaceModel.d.ts +82 -0
  281. package/dist/shell/frame/workspaceModel.js +250 -0
  282. package/dist/shell/frame/workspaceModel.js.map +1 -0
  283. package/dist/shell/frame/workspaces.css +84 -0
  284. package/dist/shell/frame/workspaces.d.ts +22 -0
  285. package/dist/shell/frame/workspaces.js +125 -0
  286. package/dist/shell/frame/workspaces.js.map +1 -0
  287. package/dist/shell/frame/zoomStore.d.ts +10 -0
  288. package/dist/shell/frame/zoomStore.js +65 -0
  289. package/dist/shell/frame/zoomStore.js.map +1 -0
  290. package/dist/shell/installController.d.ts +122 -0
  291. package/dist/shell/installController.js +146 -0
  292. package/dist/shell/installController.js.map +1 -0
  293. package/dist/shell/installerMessages.d.ts +30 -0
  294. package/dist/shell/installerMessages.js +36 -0
  295. package/dist/shell/installerMessages.js.map +1 -0
  296. package/dist/shell/linkDrop.js.map +1 -1
  297. package/dist/shell/messages.d.ts +16 -0
  298. package/dist/shell/messages.js +27 -0
  299. package/dist/shell/messages.js.map +1 -0
  300. package/dist/shell/palette.js.map +1 -1
  301. package/dist/shell/paneModel.d.ts +22 -0
  302. package/dist/shell/paneModel.js +24 -1
  303. package/dist/shell/paneModel.js.map +1 -1
  304. package/dist/shell/panel/Appearance.d.ts +8 -0
  305. package/dist/shell/panel/Appearance.js +256 -0
  306. package/dist/shell/panel/Appearance.js.map +1 -0
  307. package/dist/shell/panel/BackupPanel.d.ts +5 -0
  308. package/dist/shell/panel/BackupPanel.js +198 -0
  309. package/dist/shell/panel/BackupPanel.js.map +1 -0
  310. package/dist/shell/panel/DeveloperPanel.d.ts +4 -0
  311. package/dist/shell/panel/DeveloperPanel.js +51 -0
  312. package/dist/shell/panel/DeveloperPanel.js.map +1 -0
  313. package/dist/shell/panel/FeatureToggles.d.ts +13 -0
  314. package/dist/shell/panel/FeatureToggles.js +42 -0
  315. package/dist/shell/panel/FeatureToggles.js.map +1 -0
  316. package/dist/shell/panel/Home.d.ts +3 -0
  317. package/dist/shell/panel/Home.js +23 -0
  318. package/dist/shell/panel/Home.js.map +1 -0
  319. package/dist/shell/panel/IconPackInstall.d.ts +15 -0
  320. package/dist/shell/panel/IconPackInstall.js +41 -0
  321. package/dist/shell/panel/IconPackInstall.js.map +1 -0
  322. package/dist/shell/panel/LanguageSettings.d.ts +1 -0
  323. package/dist/shell/panel/LanguageSettings.js +54 -0
  324. package/dist/shell/panel/LanguageSettings.js.map +1 -0
  325. package/dist/shell/panel/MakePanel.d.ts +3 -0
  326. package/dist/shell/panel/MakePanel.js +237 -0
  327. package/dist/shell/panel/MakePanel.js.map +1 -0
  328. package/dist/shell/panel/MarkdownDoc.d.ts +6 -0
  329. package/dist/shell/panel/MarkdownDoc.js +35 -0
  330. package/dist/shell/panel/MarkdownDoc.js.map +1 -0
  331. package/dist/shell/panel/Modes.d.ts +40 -0
  332. package/dist/shell/panel/Modes.js +270 -0
  333. package/dist/shell/panel/Modes.js.map +1 -0
  334. package/dist/shell/panel/NavIcon.d.ts +4 -0
  335. package/dist/shell/panel/NavIcon.js +6 -0
  336. package/dist/shell/panel/NavIcon.js.map +1 -0
  337. package/dist/shell/panel/Panel.d.ts +7 -0
  338. package/dist/shell/panel/Panel.js +139 -0
  339. package/dist/shell/panel/Panel.js.map +1 -0
  340. package/dist/shell/panel/PluginFeatures.d.ts +24 -0
  341. package/dist/shell/panel/PluginFeatures.js +165 -0
  342. package/dist/shell/panel/PluginFeatures.js.map +1 -0
  343. package/dist/shell/panel/Plugins.d.ts +33 -0
  344. package/dist/shell/panel/Plugins.js +112 -0
  345. package/dist/shell/panel/Plugins.js.map +1 -0
  346. package/dist/shell/panel/PowerSettings.d.ts +4 -0
  347. package/dist/shell/panel/PowerSettings.js +52 -0
  348. package/dist/shell/panel/PowerSettings.js.map +1 -0
  349. package/dist/shell/panel/Settings.d.ts +23 -0
  350. package/dist/shell/panel/Settings.js +116 -0
  351. package/dist/shell/panel/Settings.js.map +1 -0
  352. package/dist/shell/panel/ShareSetup.d.ts +8 -0
  353. package/dist/shell/panel/ShareSetup.js +130 -0
  354. package/dist/shell/panel/ShareSetup.js.map +1 -0
  355. package/dist/shell/panel/StoreSection.d.ts +6 -0
  356. package/dist/shell/panel/StoreSection.js +48 -0
  357. package/dist/shell/panel/StoreSection.js.map +1 -0
  358. package/dist/shell/panel/StringPacks.d.ts +11 -0
  359. package/dist/shell/panel/StringPacks.js +106 -0
  360. package/dist/shell/panel/StringPacks.js.map +1 -0
  361. package/dist/shell/panel/ThemeBuilder.d.ts +5 -0
  362. package/dist/shell/panel/ThemeBuilder.js +205 -0
  363. package/dist/shell/panel/ThemeBuilder.js.map +1 -0
  364. package/dist/shell/panel/backup.css +34 -0
  365. package/dist/shell/panel/builder.css +232 -0
  366. package/dist/shell/panel/builderModel.d.ts +55 -0
  367. package/dist/shell/panel/builderModel.js +95 -0
  368. package/dist/shell/panel/builderModel.js.map +1 -0
  369. package/dist/shell/panel/compare.d.ts +10 -0
  370. package/dist/shell/panel/compare.js +51 -0
  371. package/dist/shell/panel/compare.js.map +1 -0
  372. package/dist/shell/panel/controls.d.ts +135 -0
  373. package/dist/shell/panel/controls.js +213 -0
  374. package/dist/shell/panel/controls.js.map +1 -0
  375. package/dist/shell/panel/featureModel.d.ts +69 -0
  376. package/dist/shell/panel/featureModel.js +79 -0
  377. package/dist/shell/panel/featureModel.js.map +1 -0
  378. package/dist/shell/panel/fonts/FontBrowser.d.ts +10 -0
  379. package/dist/shell/panel/fonts/FontBrowser.js +189 -0
  380. package/dist/shell/panel/fonts/FontBrowser.js.map +1 -0
  381. package/dist/shell/panel/fonts/FontRoles.d.ts +20 -0
  382. package/dist/shell/panel/fonts/FontRoles.js +77 -0
  383. package/dist/shell/panel/fonts/FontRoles.js.map +1 -0
  384. package/dist/shell/panel/fonts/catalog.d.ts +37 -0
  385. package/dist/shell/panel/fonts/catalog.js +68 -0
  386. package/dist/shell/panel/fonts/catalog.js.map +1 -0
  387. package/dist/shell/panel/fonts/googleFontsCatalog.json +1 -0
  388. package/dist/shell/panel/index.d.ts +20 -0
  389. package/dist/shell/panel/index.js +34 -0
  390. package/dist/shell/panel/index.js.map +1 -0
  391. package/dist/shell/panel/languageModel.d.ts +5 -0
  392. package/dist/shell/panel/languageModel.js +7 -0
  393. package/dist/shell/panel/languageModel.js.map +1 -0
  394. package/dist/shell/panel/make.css +72 -0
  395. package/dist/shell/panel/makeModel.d.ts +32 -0
  396. package/dist/shell/panel/makeModel.js +84 -0
  397. package/dist/shell/panel/makeModel.js.map +1 -0
  398. package/dist/shell/panel/markdown.d.ts +46 -0
  399. package/dist/shell/panel/markdown.js +100 -0
  400. package/dist/shell/panel/markdown.js.map +1 -0
  401. package/dist/shell/panel/nav.d.ts +12 -0
  402. package/dist/shell/panel/nav.js +50 -0
  403. package/dist/shell/panel/nav.js.map +1 -0
  404. package/dist/shell/panel/panel.css +401 -0
  405. package/dist/shell/panel/panelMessages.d.ts +763 -0
  406. package/dist/shell/panel/panelMessages.js +767 -0
  407. package/dist/shell/panel/panelMessages.js.map +1 -0
  408. package/dist/shell/panel/plugins.css +59 -0
  409. package/dist/shell/panel/setupModel.d.ts +87 -0
  410. package/dist/shell/panel/setupModel.js +152 -0
  411. package/dist/shell/panel/setupModel.js.map +1 -0
  412. package/dist/shell/panel/site.d.ts +259 -0
  413. package/dist/shell/panel/site.js +25 -0
  414. package/dist/shell/panel/site.js.map +1 -0
  415. package/dist/shell/panel/strings.css +7 -0
  416. package/dist/shell/panel/themes.d.ts +10 -0
  417. package/dist/shell/panel/themes.js +8 -0
  418. package/dist/shell/panel/themes.js.map +1 -0
  419. package/dist/shell/profileModel.d.ts +3 -2
  420. package/dist/shell/profileModel.js +7 -5
  421. package/dist/shell/profileModel.js.map +1 -1
  422. package/dist/shell/store.css +230 -0
  423. package/dist/shell/storeMessages.d.ts +169 -0
  424. package/dist/shell/storeMessages.js +172 -0
  425. package/dist/shell/storeMessages.js.map +1 -0
  426. package/dist/shell/storeModel.d.ts +181 -0
  427. package/dist/shell/storeModel.js +133 -0
  428. package/dist/shell/storeModel.js.map +1 -0
  429. package/dist/shell/stringPacksModel.d.ts +44 -0
  430. package/dist/shell/stringPacksModel.js +94 -0
  431. package/dist/shell/stringPacksModel.js.map +1 -0
  432. package/dist/shell/updateModel.d.ts +2 -1
  433. package/dist/shell/updateModel.js +5 -4
  434. package/dist/shell/updateModel.js.map +1 -1
  435. package/dist/shell/windowControls.d.ts +4 -0
  436. package/dist/shell/windowControls.js +5 -0
  437. package/dist/shell/windowControls.js.map +1 -1
  438. package/i18n-config.schema.json +29 -0
  439. package/i18n-meta.schema.json +26 -0
  440. package/i18n.schema.json +42 -0
  441. package/icons.schema.json +646 -0
  442. package/languages.schema.json +23 -0
  443. package/locales/ar-x-fm.json +11 -0
  444. package/locales/ar.json +1281 -0
  445. package/locales/bg.json +1280 -0
  446. package/locales/bn.json +1280 -0
  447. package/locales/ca.json +1280 -0
  448. package/locales/cs.json +1280 -0
  449. package/locales/da.json +1280 -0
  450. package/locales/de.json +1280 -0
  451. package/locales/el.json +1280 -0
  452. package/locales/en-GB.json +27 -0
  453. package/locales/en.json +1280 -0
  454. package/locales/en.meta.json +51 -0
  455. package/locales/es.json +1280 -0
  456. package/locales/eu.json +1280 -0
  457. package/locales/fa.json +1281 -0
  458. package/locales/fi.json +1280 -0
  459. package/locales/fil.json +1280 -0
  460. package/locales/fr.json +1280 -0
  461. package/locales/ga.json +1280 -0
  462. package/locales/gl.json +1280 -0
  463. package/locales/gu.json +1280 -0
  464. package/locales/ha.json +1280 -0
  465. package/locales/he.json +1281 -0
  466. package/locales/hi.json +1280 -0
  467. package/locales/hr.json +1280 -0
  468. package/locales/hu.json +1279 -0
  469. package/locales/id.json +1280 -0
  470. package/locales/ig.json +1280 -0
  471. package/locales/it.json +1280 -0
  472. package/locales/ja.json +1280 -0
  473. package/locales/kn.json +1280 -0
  474. package/locales/ko.json +1280 -0
  475. package/locales/mr.json +1280 -0
  476. package/locales/ms.json +1280 -0
  477. package/locales/nb.json +1280 -0
  478. package/locales/nl.json +1280 -0
  479. package/locales/pl.json +1280 -0
  480. package/locales/pt.json +1280 -0
  481. package/locales/ro.json +1280 -0
  482. package/locales/ru.json +1280 -0
  483. package/locales/sk.json +1280 -0
  484. package/locales/sr.json +1280 -0
  485. package/locales/sv.json +1280 -0
  486. package/locales/ta.json +1280 -0
  487. package/locales/th.json +1280 -0
  488. package/locales/tr.json +1280 -0
  489. package/locales/uk.json +1280 -0
  490. package/locales/ur.json +1281 -0
  491. package/locales/vi.json +1280 -0
  492. package/locales/yo.json +1280 -0
  493. package/locales/zh-Hans.json +1280 -0
  494. package/locales/zh-Hant.json +1280 -0
  495. package/package.json +139 -5
  496. package/store-catalog.schema.json +65 -0
  497. package/theme.schema.json +4659 -0
  498. package/windows/installer.nsi +926 -0
  499. package/windows/languages/Basque.nsh +28 -0
  500. package/windows/languages/Catalan.nsh +28 -0
  501. package/windows/languages/Croatian.nsh +28 -0
  502. package/windows/languages/Czech.nsh +28 -0
  503. package/windows/languages/Danish.nsh +28 -0
  504. package/windows/languages/Finnish.nsh +28 -0
  505. package/windows/languages/Galician.nsh +28 -0
  506. package/windows/languages/Greek.nsh +28 -0
  507. package/windows/languages/Hungarian.nsh +28 -0
  508. package/windows/languages/Indonesian.nsh +28 -0
  509. package/windows/languages/Irish.nsh +28 -0
  510. package/windows/languages/Malay.nsh +28 -0
  511. package/windows/languages/Polish.nsh +28 -0
  512. package/windows/languages/Romanian.nsh +28 -0
  513. package/windows/languages/Serbian.nsh +28 -0
  514. package/windows/languages/Slovak.nsh +28 -0
  515. package/windows/languages/Thai.nsh +28 -0
package/README.md CHANGED
@@ -4,14 +4,31 @@ The framework behind the wayBetter apps: the apps you already use in a light nat
4
4
  window, extended in place the way BetterDiscord extends Discord. Websites and services that ship a
5
5
  heavy Electron client alike: every wayBetter app is the same shell, runtime and one small adapter.
6
6
 
7
+ This package is the TypeScript half and the command line. The native half is the Rust crate
8
+ `waybetter-host`, which is not on npm: an app takes it from the
9
+ [repository](https://git.crt.fyi/CRT/waybetter) as a git submodule or a path dependency. The
10
+ repository README explains how the three layers fit together and shows a minimal adapter;
11
+ `docs/ARCHITECTURE.md` there lists every module.
12
+
7
13
  - **`waybetter/runtime/*`**: the page runtime. One DOM-mutation/animation-frame hub, one
8
- fetch/XHR hub, a plugin API core, an OKLab theme color model, split-pane rail hiding, link
9
- routing and account change reporting.
14
+ fetch/XHR hub, a plugin API core with a themed UI kit (toasts, alerts, confirmations, prompts,
15
+ dialogs), a theme API, an OKLab theme color model, split-pane rail hiding, link routing and
16
+ account change reporting.
17
+ - **`waybetter/theme.schema.json`**: the JSON Schema of wayBetter theme files.
10
18
  - **`waybetter/shell/*`**: pure models for the app chrome around the pages: address bar chips,
11
19
  dock/split-pane rules, dragged links, account profiles, the update chip, command palette
12
20
  ranking and window controls. The Tauri window API is passed in by the caller, never imported.
13
-
14
- Plain ESM with `.d.ts` types. Zero dependencies.
21
+ And the wayBetter Store: the install screen and the Store view as React components (React is an
22
+ optional peer; everything else has no dependencies), their controller and models.
23
+ - **`waybetter/shell/frame`**: the whole shell of an app, `createShell(site, { native, i18n })`:
24
+ tabs in the titlebar, split panes, the smart address bar, the new-tab page, the command palette,
25
+ the account switcher, decks of site columns, workspaces, pane themes, overlays and the native
26
+ layout sync. The app describes its site (pages, address chips, palette items, column kinds, its
27
+ own panel tab); React, React DOM and dockview are optional peers, the Tauri API is passed in.
28
+ - **`waybetter store build|sign|verify`** and **`waybetter/store-catalog.schema.json`**: the tooling
29
+ and JSON Schema of the shared, signed wayBetter Store catalog.
30
+
31
+ Plain ESM with `.d.ts` types. Zero dependencies (the React parts use your React; the shell frame also dockview).
15
32
 
16
33
  ## Install
17
34
 
@@ -39,30 +56,147 @@ pieces. The source comments document each module's contract.
39
56
  **Runtime**
40
57
 
41
58
  - `accountReport`: reports the signed-in account seen in the page's own UI.
59
+ - `siteRuntime`: composes a runtime entry: `pageInvoke`, `createFeatureFlags` (flag-controlled parts, a deck column's overrides), `installSiteRuntime` (the runtime object under `window.wayBetter` and the app's names, the members native code calls, queued native deliveries, the palette command report).
60
+ - `pageStrings`: the page's language (English built in; native deliveries are checked as data).
61
+ - `panelButton`: the way into the app's panel from the page: the adapter's navigation entry, or a floating button.
62
+ - `commandReport`: reports plugin palette commands to the shell; developer-mode start errors.
63
+ - `column`: a site tab as a narrow deck column: hides the site's chrome, lets its content fill the width, per-column filters (keywords, `/regex/`, replies, reposts, media only) and an unread count from what the site rendered. Makes no requests.
42
64
  - `domHub`: one `MutationObserver` and one animation frame shared by every DOM feature.
43
65
  - `linkRouting`: routes clicks on the app's own links per the "links to app pages" setting.
44
66
  - `netHub`: one shared fetch/XHR hook for URL rewrites, gates and passive JSON taps.
45
67
  - `paneNav`: hides a redundant navigation rail when two panes show the same account.
46
- - `pluginApi`: small helpers shared by user JS plugins.
68
+ - `pluginApi`: small helpers shared by user JS plugins, including `ui` and `theme`.
47
69
  - `site`: the page-side composition root for an adapter.
70
+ - `themeApi`: the active theme as values (`ResolvedTheme`), `--wb-*` CSS variables, contrast helpers.
48
71
  - `themeTokens`: the OKLab color model themes are built on.
72
+ - `ui`: the plugin UI kit (see below).
49
73
 
50
74
  **Shell**
51
75
 
52
76
  - `addressModel`: `parseAddress(url, site)` for the address bar's breadcrumb chips.
53
77
  - `chrome`: layout constants for the custom titlebar and toolbar.
78
+ - `deckModel`: decks of site columns (TweetDeck-style): bounded model, paging layout (whole columns per page, parked off-page columns), focus moves, unread totals.
54
79
  - `linkDrop`: a dragged link dropped into the dock opens as a tab or split pane.
55
80
  - `palette`: command palette fuzzy scoring, ranking and selection movement.
56
81
  - `paneModel`: pane geometry: where a "beside" link opens, which panes keep the rail.
57
82
  - `profileModel`: the account profile model.
58
83
  - `updateModel`: the titlebar update chip model.
59
84
  - `windowControls`: native window calls for the titlebar, resize grips and caption buttons.
85
+ - `storeModel`, `storeMessages`: Store wire types, item states (install, update, changed locally, built in), permission badges, search; the English of every `wb.store.*`, `wb.install.*`, `wb.permission.*` message (translations in `waybetter/locales/*.json`).
86
+ - `installController`: the install screen's state (install links, dropped files, store items, confirm), given the app's native bridge and theme adapter.
87
+ - `InstallDialog` (`InstallHost`), `StoreView`, `store.css`: the install screen, the window drop target and the Store view, themed with `--wb-*` tokens. See docs/STORE.md in the repository.
88
+
89
+ **Shell frame** (`waybetter/shell/frame`, modules also as `waybetter/shell/frame/*`, styles as `waybetter/shell/frame/*.css`)
90
+
91
+ ```tsx
92
+ import { createShell, type ShellSite } from 'waybetter/shell/frame';
93
+ const Shell = createShell(site, { native: { invoke, listen, currentWindow: getCurrentWindow }, i18n });
94
+ createRoot(document.getElementById('root')!).render(<Shell/>);
95
+ ```
96
+
97
+ - `ShellSite` (`frame/site`): the site's names and pages, `address(url)` chips, slots for the app's panel tab, the new-tab page, palette items, deck column kinds, the media panel, themes (`createThemeStore`) and overlays, and the native `features` the app serves.
98
+ - `i18n`: the app's `createI18n` instance with `waybetter/locales/*.json` merged in; the frame's words are `wb.*` messages in 51 languages.
99
+ - `bootScript()` (`frame/boot`): the first-frame `boot.js` (the last theme's chrome colors before the modules load).
100
+ - `installPreviewMocks(handlers)`: native commands answered from memory, for development previews in a plain browser.
101
+ - `createLanguage(options)` (`frame/language`): which language the app speaks (follow the site, follow the system, or one language), switched live and handed to native code and site tabs (`i18n_set`); `createAppI18n(options)` (`frame/appI18n`): the app's i18n instance with typed keys, `useT`, dates and numbers.
102
+ - Everything else is exported for apps that build their own settings on it: the shared state (`shell`, `setOverlay`, `scheduleSync`), stores (decks, workspaces, sync, developer mode), models (palette, accounts, workspaces, backup, media) and hooks.
103
+
104
+ **Panel** (`waybetter/shell/panel`, modules also as `waybetter/shell/panel/*`, styles as `waybetter/shell/panel/*.css`)
105
+
106
+ ```tsx
107
+ import { createPanel, type PanelSite } from 'waybetter/shell/panel';
108
+ const Panel = createPanel({ brand: { name: 'wayBetter', logo }, home, themes, sections, make, languages });
109
+ const Shell = createShell({ ...site, panel: { id: 'app', title: 'wayBetter', component: Panel } }, options);
110
+ ```
111
+
112
+ - The app's own tab: home, Appearance and the Theme Builder (with the Google Fonts browser), plugins and custom CSS, the Store, Make, accounts, Power User, settings, backup and sync, developer mode, updates, and a search across every setting. Each section shows only when the app serves what it needs.
113
+ - `PanelSite` (`panel/site`): the brand and the home page's words, the app's own `sections` and their `order`, `themes` (the theme store and catalog, the preview component a theme document is drawn in, the site font), `make` (example plugins, an example theme, bundled docs), `store`, `languages`, and what its native side serves (`settings.alerts`, `backup`, `updates`).
114
+ - For the app's own sections: the panel's controls (`panel/controls`: `Section`, `Row`, `Toggle`, `Segmented`, `Select`, `Slider`, `ColorField`, `Button`, ...), `useFeatures` and `FeatureGroups` (`panel/FeatureToggles`: on/off rows over the host's `features_get/set`), `compareLines`.
115
+ - The panel's words are `wb.*` messages in 51 languages (`waybetter/locales/*.json`; translator notes in `waybetter/locales/en.meta.json`).
116
+
117
+ **Command line**
118
+
119
+ - `waybetter store build --config store.config.mjs`: builds an app's part of the shared store folder (its items only, validated with the apps' own rules).
120
+ - `waybetter store sign [--init] --key <private key>` / `waybetter store verify --pub <key file>`: Ed25519 signature over the exact catalog bytes; any listed public key verifies (rotation). The private key is never printed or copied.
121
+ - `waybetter strings check <pack> [--inventory <file>] [--verbose]`: validates a string pack (data that replaces the wrapped site's own UI strings: `waybetter/runtime/stringPacks`, `waybetter/runtime/stringPackHook`, `waybetter/runtime/textNet`) against the site's string inventory and prints its coverage; the inventories otherwise come from `waybetter.strings.json` in the app's root.
122
+ - `waybetter i18n check [--write] [--verbose] [locale…]`: checks an app's catalogs (and the framework's in the same languages) with the `waybetter/i18n/check` rules, bundled plugins' inline English and the generated files; `--write` regenerates `languages.json` and the native localization files (macOS, Linux). `waybetter i18n extract [--missing]`: keys the code looks up that English lacks, and English keys without a literal lookup. Both read `waybetter.i18n.json` in the app's root (`locales`, `sources`, `nativeSources`, `bundledPlugins`, `runtimeKeys`, `supported`, `native`; schema: `i18n-config.schema.json`). `supported` lists the languages in the supported tier; every other catalog gets `tier: "community"` in the generated `languages.json` (`languages.schema.json`), and an app resolves its automatic language choices only to supported ones (`createLanguage({ supported })`).
123
+ - `waybetter release windows|macos`: signed native releases and the update manifest (`waybetter.release.json`). The Windows build runs path-free (below) and every artifact must pass the privacy scan before anything is copied or signed.
124
+ - `waybetter build-env -- <command>`: runs a build (`tauri build`, `cargo build`) so the binary holds none of the machine's paths: the home folder, the workspace, `CARGO_HOME`, `RUSTUP_HOME` and `CARGO_TARGET_DIR` become `/home`, `/src`, `/cargo`, `/rustup` and `/target` (`--remap-path-prefix` appended to the flags already in `RUSTFLAGS`/`CARGO_ENCODED_RUSTFLAGS`, `/PDBALTPATH` on MSVC; for C and C++ a build script compiles, `-ffile-prefix-map` on gcc and clang and, on MSVC, `/d1trimfile:<root>` in `CL` and `/PDBALTPATH` in `LINK`, which reach the cc crate, CMake and MSBuild alike). Without a command it prints that environment (`--json`).
125
+ - `waybetter privacy-scan <paths…> [--terms <file>] [--tracked] [--history]`: searches files, binaries (UTF-8 and UTF-16), archives (zip, tar, gzip, zstd, .deb, DMG; NSIS installers, AppImages and xz with 7-Zip or the matching tool), git-tracked files and a repository's whole history for forbidden terms: the lines of a file kept outside every repository (`--terms`, `WAYBETTER_FORBIDDEN_TERMS`, or `"forbiddenTerms"` in `waybetter.release.json`) plus this machine's account name. A name is a hit as a whole word in any case; a name of three characters or fewer only in a path or as the capitalized word. Output shows file and line or offset with the term masked (`m***`); exit 1 on a hit, 2 when a container could not be opened. Reviewed false positives: `"privacyAllowlist"`, lines of `<file glob>: <regex over the context, the term written <term>>`.
126
+ - `windows/languages/<Language>.nsh`: the Windows installer's messages for the languages Tauri does not ship, next to the installer template (`windows/installer.nsi`).
127
+
128
+ ## Plugin UI kit (`runtime/ui`)
129
+
130
+ Plugins get it as `api.ui` (and `scope.ui`, which closes whatever it opened on `scope.dispose()`).
131
+ Everything is drawn in one Shadow DOM host, so the site's CSS cannot restyle it, and it takes its
132
+ colors, corners and font from the active theme (`api.theme`), live.
133
+
134
+ ```js
135
+ const ui = this.scope.ui;
136
+ ui.toast('Link copied'); // tones: neutral, info, success, warning, danger
137
+ ui.toast('Post hidden', { action: { label: 'Undo', onClick: undo } });
138
+ await ui.alert({ title: 'Saved', message: 'Kept on this device only.', tone: 'success' });
139
+ if (await ui.confirm({ title: 'Delete this note?', confirmLabel: 'Delete', danger: true })) remove();
140
+ const name = await ui.prompt({ title: 'Rename', value: 'Reading', validate: v => v.trim() ? null : 'Required' });
141
+ const dialog = ui.dialog({
142
+ title: 'Settings',
143
+ content: body => body.append(ui.h('label', { class: 'wb-check' }, ui.h('input', { type: 'checkbox' }), 'Hide trends')),
144
+ actions: [{ label: 'Cancel' }, { label: 'Save', tone: 'primary', default: true, onClick: save }],
145
+ });
146
+ ```
147
+
148
+ - `modal(options)` is the primitive under all of them; `dialog` is a `role="dialog"`, `alert` /
149
+ `confirm` are `role="alertdialog"`. All are `aria-modal`, labelled by their title and described
150
+ by their message.
151
+ - Focus moves in, Tab/Shift+Tab wrap inside, and focus returns to where it was. Esc dismisses;
152
+ Enter in a single-line field (Ctrl/Cmd+Enter in a textarea) runs the `default` action. A
153
+ destructive `confirm` starts on Cancel.
154
+ - Backdrop clicks dismiss alerts and confirmations only (a press that started in a field and ended
155
+ on the backdrop does not count). Keys typed in a dialog never reach the page's own shortcuts.
156
+ - Dialogs stack (lower ones become `inert`); toasts stack (four at most), pause while hovered or
157
+ focused and are a polite live region (`role="alert"` for danger).
158
+ - `prefers-reduced-motion` turns off the animations. Text is always set as text; `ui.h(tag,
159
+ props, ...children)` builds content without `innerHTML`, string handlers or `javascript:` URLs.
160
+ - Classes for content: `wb-field`, `wb-label`, `wb-hint`, `wb-check`, `wb-input`, `wb-mono`,
161
+ `wb-divider`, `wb-row`, `wb-muted`; per-dialog CSS goes in `css`.
162
+
163
+ `createUiKit(window, { theme })` builds a kit outside the plugin API; `theme` is a `ThemeApi` from
164
+ `createThemeApi(window, source)`, where `source` is the site's `{ current(), onChange() }`.
165
+
166
+ ## Themes
167
+
168
+ `api.theme.current()` returns the active theme resolved: `colors` (`bg`, `surface`, `elevated`,
169
+ `border`, `text`, `muted`, `accent`, `onAccent`, `inverse`, `onInverse`, `page`), `radius`,
170
+ `buttonRadius`, `font`, `mode` and `siteDefault` (true when the site's own colors show).
171
+ `api.theme.onChange(fn)` fires after it changes. The same values are CSS custom properties on
172
+ `:root` (`--wb-bg`, `--wb-text`, `--wb-accent`, `--wb-radius`, `--wb-font`, …), so plugin CSS can
173
+ use `var(--wb-accent)`.
174
+
175
+ Theme files are JSON; `theme.schema.json` describes every field and its limits (the app clamps
176
+ out-of-range values when it imports a file). Point a theme at it for editor completion and checks:
177
+
178
+ ```json
179
+ { "$schema": "https://unpkg.com/waybetter/theme.schema.json", "name": "Midnight Mint", "colors": { "bg": "#0b1110", "text": "#e8f3ef", "accent": "#3ddc97" } }
180
+ ```
181
+
182
+ or, in a project that installs the package, `"$schema": "./node_modules/waybetter/theme.schema.json"`.
183
+
184
+ ## Build your own
185
+
186
+ ```sh
187
+ npm create waybetter plugin # *.plugin.js (or --ts) using api.scope, storage, ui and theme
188
+ npm create waybetter theme # theme JSON with "$schema" pointing at theme.schema.json
189
+ npm create waybetter app myapp -- --site youtube.com # a new wayBetter app (Tauri 2 + waybetter-host)
190
+ ```
191
+
192
+ [`create-waybetter`](https://www.npmjs.com/package/create-waybetter) generates code against this
193
+ package's real API and schema; `--help` lists every option.
60
194
 
61
195
  ## Projects using wayBetter
62
196
 
63
197
  | Project | Target | What it is |
64
198
  | --- | --- | --- |
65
- | [wayBetter for X](https://waybetter.fyi/twttr/) | x.com (website) | Desktop app around the live X: tabs, split panes, real accounts side by side, themes, plugins, drafts and fixes for X's own bugs. The first wayBetter app. |
199
+ | [wayBetter for X](https://git.crt.fyi/CRT/waybetter-for-x) | x.com (website) | Desktop app around the live X: tabs, split panes, real accounts side by side, themes, plugins, drafts and fixes for X's own bugs. The first wayBetter app. |
66
200
 
67
201
  Built something on wayBetter? Add it to this list with a pull request: name and link, what it extends, one line on what it does.
68
202
 
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ // The `waybetter` command: `waybetter store build|sign|verify` (cli/store.mjs),
3
+ // `waybetter release windows|macos|linux` (cli/release.mjs), `waybetter manifests` (cli/manifests.mjs), `waybetter i18n check|extract`
4
+ // (cli/i18n.mjs), `waybetter privacy-scan` (cli/privacy.mjs) and `waybetter build-env`
5
+ // (cli/buildenv.mjs), `waybetter dev` (cli/dev.mjs: watchers + tauri dev), `waybetter strings check`
6
+ // (cli/strings.mjs).
7
+ import { readFileSync } from 'node:fs';
8
+ import { BUILD_ENV_USAGE, buildEnvCommand } from '../cli/buildenv.mjs';
9
+ import { DEV_USAGE, devCommand } from '../cli/dev.mjs';
10
+ import { MANIFESTS_USAGE, manifestsCommand } from '../cli/manifests.mjs';
11
+ import { I18N_USAGE, i18nCommand } from '../cli/i18n.mjs';
12
+ import { PRIVACY_USAGE, privacyCommand } from '../cli/privacy.mjs';
13
+ import { STORE_USAGE, storeCommand } from '../cli/store.mjs';
14
+ import { STRINGS_USAGE, stringsCommand } from '../cli/strings.mjs';
15
+ import { RELEASE_USAGE, releaseCommand } from '../cli/release.mjs';
16
+
17
+ const [area, ...rest] = process.argv.slice(2);
18
+ try {
19
+ if (area === 'store') {
20
+ for (const line of await storeCommand(rest)) console.log(line);
21
+ } else if (area === 'release') {
22
+ await releaseCommand(rest);
23
+ } else if (area === 'manifests') {
24
+ process.exitCode = manifestsCommand(rest);
25
+ } else if (area === 'i18n') {
26
+ process.exitCode = await i18nCommand(rest);
27
+ } else if (area === 'strings') {
28
+ process.exitCode = await stringsCommand(rest);
29
+ } else if (area === 'privacy-scan') {
30
+ process.exitCode = privacyCommand(rest);
31
+ } else if (area === 'build-env') {
32
+ process.exitCode = buildEnvCommand(rest);
33
+ } else if (area === 'dev') {
34
+ process.exitCode = await devCommand(rest);
35
+ } else if (area === '--version' || area === '-v') {
36
+ console.log(JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version);
37
+ } else {
38
+ console.log(`${STORE_USAGE}\n\n${RELEASE_USAGE}\n\n${MANIFESTS_USAGE}\n\n${I18N_USAGE}\n\n${STRINGS_USAGE}\n\n${PRIVACY_USAGE}\n\n${BUILD_ENV_USAGE}
39
+
40
+ ${DEV_USAGE}`);
41
+ if (area && area !== '--help' && area !== '-h') process.exitCode = 1;
42
+ }
43
+ } catch (error) {
44
+ console.error(`waybetter: ${error instanceof Error ? error.message : error}`);
45
+ process.exitCode = 1;
46
+ }
@@ -0,0 +1,105 @@
1
+ // `waybetter/build`: bundles an app's page runtime (or any script native code injects into site
2
+ // tabs) into one self-contained IIFE with esbuild, the way every wayBetter app ships it:
3
+ //
4
+ // import { buildRuntime } from 'waybetter/build';
5
+ // await buildRuntime({
6
+ // entry: 'src/inject/entry.tsx',
7
+ // outfile: 'src-tauri/x-runtime.js',
8
+ // catalog: 'locales/en.json', // the app's English catalog ({ "messages": { ... } })
9
+ // prefixes: ['x.', 'plugin.'], // only these strings are compiled in (others arrive natively)
10
+ // jsx: 'automatic', // any other esbuild option passes through
11
+ // });
12
+ //
13
+ // `watch: true` (an app's build script passes `watchRequested()`) keeps esbuild watching and
14
+ // rebuilding `outfile`; a failed rebuild leaves the last good file in place.
15
+ // - `?inline` CSS imports become strings (Vite semantics); other CSS side-effect imports are
16
+ // dropped, because injected UI adopts its stylesheet into a shadow root explicitly
17
+ // (`inlineCss: false` turns this off).
18
+ // - Imports of `catalog` load only the keys starting with one of `prefixes`: the runtime ships
19
+ // English for its own strings; the owner's language arrives natively (i18n_set).
20
+ // - esbuild is the app's own dependency (resolved from `cwd`, or pass `esbuild`).
21
+ import { readFile } from 'node:fs/promises';
22
+ import { createRequire } from 'node:module';
23
+ import path from 'node:path';
24
+
25
+ /** The CSS plugin: `?inline` imports as text, other CSS imports dropped. */
26
+ export const inlineCssPlugin = {
27
+ name: 'waybetter-css',
28
+ setup(api) {
29
+ api.onResolve({ filter: /\.css(\?inline)?$/ }, args => ({
30
+ path: path.resolve(args.resolveDir, args.path.replace(/\?inline$/, '')),
31
+ namespace: args.path.endsWith('?inline') ? 'css-inline' : 'css-drop',
32
+ }));
33
+ api.onLoad({ filter: /.*/, namespace: 'css-inline' }, async args => ({ contents: await readFile(args.path, 'utf8'), loader: 'text' }));
34
+ api.onLoad({ filter: /.*/, namespace: 'css-drop' }, () => ({ contents: '', loader: 'js' }));
35
+ },
36
+ };
37
+
38
+ /** The catalog plugin: `catalog` (absolute path) loads as `{ messages }` with only `prefixes` keys. */
39
+ export function catalogPlugin(catalog, prefixes) {
40
+ const target = path.resolve(catalog);
41
+ return {
42
+ name: 'waybetter-strings',
43
+ setup(api) {
44
+ api.onLoad({ filter: /\.json$/ }, async args => {
45
+ if (path.resolve(args.path) !== target) return undefined;
46
+ const { messages = {} } = JSON.parse(await readFile(args.path, 'utf8'));
47
+ const kept = Object.fromEntries(Object.entries(messages).filter(([key]) => prefixes.some(prefix => key.startsWith(prefix))));
48
+ return { contents: JSON.stringify({ messages: kept }), loader: 'json' };
49
+ });
50
+ },
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Builds `entry` into `outfile` (paths relative to `cwd`). Defaults: bundled IIFE, es2022,
56
+ * minified, no source map, no legal comments. Returns esbuild's result.
57
+ * @param {{ entry: string, outfile: string, watch?: boolean, catalog?: string, prefixes?: string[], cwd?: string,
58
+ * inlineCss?: boolean, esbuild?: { build: Function }, plugins?: object[], [option: string]: unknown }} options
59
+ */
60
+ export async function buildRuntime(options) {
61
+ const { entry, outfile, catalog, prefixes = [], cwd = process.cwd(), inlineCss = true, esbuild, plugins = [], watch = false, ...rest } = options;
62
+ if (!entry || !outfile) throw new Error('buildRuntime: entry and outfile are required');
63
+ if (catalog && !prefixes.length) throw new Error('buildRuntime: a catalog needs the key prefixes the runtime ships');
64
+ const bundler = esbuild ?? createRequire(path.join(path.resolve(cwd), 'package.json'))('esbuild');
65
+ const config = {
66
+ absWorkingDir: path.resolve(cwd),
67
+ entryPoints: [entry],
68
+ outfile,
69
+ bundle: true,
70
+ format: 'iife',
71
+ target: 'es2022',
72
+ minify: true,
73
+ sourcemap: false,
74
+ legalComments: 'none',
75
+ ...rest,
76
+ plugins: [
77
+ ...(inlineCss ? [inlineCssPlugin] : []),
78
+ ...(catalog ? [catalogPlugin(path.resolve(cwd, catalog), prefixes)] : []),
79
+ ...plugins,
80
+ ],
81
+ };
82
+ if (!watch) return bundler.build(config);
83
+ // Dev loop: rebuild `outfile` whenever a source changes (a debug host reloads its tabs when the
84
+ // file changes). The first build is done when this resolves; the returned context keeps watching.
85
+ const context = await bundler.context({
86
+ ...config,
87
+ plugins: [
88
+ ...config.plugins,
89
+ {
90
+ name: 'waybetter-watch-log',
91
+ setup(api) {
92
+ api.onEnd(result => {
93
+ const stamp = new Date().toTimeString().slice(0, 8);
94
+ console.log(result.errors.length ? `[${stamp}] ${outfile}: build failed, keeping the last good file` : `[${stamp}] rebuilt ${outfile}`);
95
+ });
96
+ },
97
+ },
98
+ ],
99
+ });
100
+ await context.watch();
101
+ return context;
102
+ }
103
+
104
+ /** True when the calling script was started with `--watch`. */
105
+ export const watchRequested = (argv = process.argv) => argv.includes('--watch');
@@ -0,0 +1,130 @@
1
+ // `waybetter build-env`: the environment of a path-free native build.
2
+ //
3
+ // A Rust binary embeds the absolute paths of its sources (panic locations, `file!()`, debug info):
4
+ // the Cargo registry, the rustup toolchain and the workspace, which on a developer's machine all
5
+ // hold the account name. This computes the flags that replace those roots with neutral ones
6
+ //
7
+ // <home> -> /home <workspace root> -> /src
8
+ // $CARGO_HOME -> /cargo $RUSTUP_HOME -> /rustup $CARGO_TARGET_DIR -> /target
9
+ //
10
+ // (`--remap-path-prefix`, added to CARGO_ENCODED_RUSTFLAGS after the flags RUSTFLAGS or
11
+ // CARGO_ENCODED_RUSTFLAGS already hold), keeps the PDB's name but not its folder on MSVC
12
+ // (`/PDBALTPATH:%_PDB%`) and gives C and C++ sources compiled by build scripts the same treatment:
13
+ // `-ffile-prefix-map` in CFLAGS/CXXFLAGS on gcc and clang; on MSVC `/d1trimfile:<root>` in the CL
14
+ // variable and `/PDBALTPATH:%_PDB%` in the LINK variable, which cl.exe and link.exe read themselves,
15
+ // so the cc crate, CMake and MSBuild are all covered (`__FILE__` in a library a build script
16
+ // compiles: there a root is cut off, not renamed, and the path stays relative).
17
+ //
18
+ // waybetter build-env -- tauri build run a command with that environment
19
+ // waybetter build-env [--json] show it
20
+ //
21
+ // `waybetter release windows` builds with it. It is not a proof: `waybetter privacy-scan` is.
22
+ import { spawnSync } from 'node:child_process';
23
+ import { existsSync } from 'node:fs';
24
+ import { homedir } from 'node:os';
25
+ import { dirname, join, posix, resolve, win32 } from 'node:path';
26
+
27
+ export const BUILD_ENV_USAGE = `Usage:
28
+ waybetter build-env -- <command...>
29
+ Runs the command (tauri build, cargo build, ...) so the binary holds no build path: the home
30
+ folder, the workspace, CARGO_HOME, RUSTUP_HOME and CARGO_TARGET_DIR become /home, /src,
31
+ /cargo, /rustup and /target. Flags already in RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS are kept.
32
+ C and C++ compiled by build scripts: -ffile-prefix-map (gcc, clang), /d1trimfile in CL (MSVC).
33
+ waybetter build-env [--json] [--root <dir>]
34
+ Prints that environment. The workspace root is --root, else the folder of the nearest
35
+ waybetter.release.json, else the git work tree, else the working directory.`;
36
+
37
+ const SEPARATOR = '\x1f';
38
+
39
+ /** The folder that stands for "the sources": config folder, else git work tree, else `cwd`. */
40
+ export function workspaceRoot(cwd) {
41
+ for (let dir = resolve(cwd); ; dir = dirname(dir)) {
42
+ if (existsSync(join(dir, 'waybetter.release.json'))) return dir;
43
+ if (dirname(dir) === dir) break;
44
+ }
45
+ const git = spawnSync('git', ['-C', cwd, 'rev-parse', '--show-toplevel'], { encoding: 'utf8', windowsHide: true });
46
+ return git.status === 0 && git.stdout.trim() ? resolve(git.stdout.trim()) : resolve(cwd);
47
+ }
48
+
49
+ /**
50
+ * The environment additions of a path-free build: `{ env, maps, notes }`. `env` holds only the
51
+ * variables to set (merge it over the process environment); `maps` lists [from, to].
52
+ */
53
+ export function pathFreeBuildEnv({ root, env = process.env, platform = process.platform, home = homedir(), msvc = platform === 'win32' && !/gnu/.test(env.CARGO_BUILD_TARGET ?? '') } = {}) {
54
+ const path = platform === 'win32' ? win32 : posix;
55
+ const at = value => (platform === 'win32' ? value.replace(/[\\/]+$/, '') : value.replace(/\/+$/, '') || '/');
56
+ // General first: when several prefixes match, rustc applies the last one given.
57
+ const roots = [
58
+ [home, '/home'],
59
+ [root, '/src'],
60
+ [env.CARGO_TARGET_DIR && path.resolve(env.CARGO_TARGET_DIR), '/target'],
61
+ [env.CARGO_HOME || (home && path.join(home, '.cargo')), '/cargo'],
62
+ [env.RUSTUP_HOME || (home && path.join(home, '.rustup')), '/rustup'],
63
+ ].filter(([from]) => from).map(([from, to]) => [at(from), to]);
64
+ const maps = [];
65
+ for (const [from, to] of roots) {
66
+ maps.push([from, to]);
67
+ // Paths Windows hands out in verbatim form (canonicalized by build scripts and cargo).
68
+ if (platform === 'win32' && /^[A-Za-z]:/.test(from)) maps.push([`\\\\?\\${from}`, to]);
69
+ }
70
+
71
+ const notes = [];
72
+ const flags = env.CARGO_ENCODED_RUSTFLAGS ? env.CARGO_ENCODED_RUSTFLAGS.split(SEPARATOR) : (env.RUSTFLAGS ?? '').split(/\s+/).filter(Boolean);
73
+ const add = flag => { if (!flags.includes(flag)) flags.push(flag); };
74
+ for (const [from, to] of maps) add(`--remap-path-prefix=${from}=${to}`);
75
+ if (msvc) add('-Clink-arg=/PDBALTPATH:%_PDB%');
76
+ const out = { CARGO_ENCODED_RUSTFLAGS: flags.join(SEPARATOR) };
77
+
78
+ if (msvc) {
79
+ // cl.exe takes the first /d1trimfile prefix that matches (any case, either slash), so the
80
+ // longest root goes first. Quoted, and closed with a slash: a backslash would escape the quote.
81
+ const trims = roots.map(([from]) => from).filter(from => !from.includes('"')).sort((a, b) => b.length - a.length).map(from => `"/d1trimfile:${from}/"`);
82
+ out.CL = [...new Set([env.CL, ...trims])].filter(Boolean).join(' ');
83
+ // C and C++ linked with debug info (a CMake RelWithDebInfo library) name their PDB the same way.
84
+ out.LINK = [...new Set([env.LINK, '/PDBALTPATH:%_PDB%'])].filter(Boolean).join(' ');
85
+ } else {
86
+ // gcc and clang (cc crate: sqlite, ring and other bundled C). A flag cannot hold a space there.
87
+ const prefixMaps = maps.filter(([from]) => !/\s/.test(from)).map(([from, to]) => `-ffile-prefix-map=${from}=${to}`);
88
+ if (prefixMaps.length < maps.length) notes.push('a build path contains a space: C sources keep it (CFLAGS cannot express it)');
89
+ for (const name of ['CFLAGS', 'CXXFLAGS']) {
90
+ const current = (env[name] ?? '').split(/\s+/).filter(Boolean);
91
+ out[name] = [...current, ...prefixMaps.filter(flag => !current.includes(flag))].join(' ');
92
+ }
93
+ }
94
+ for (const dir of [root && join(root, '.cargo'), env.CARGO_HOME || (home && join(home, '.cargo'))]) {
95
+ for (const name of ['config.toml', 'config']) {
96
+ if (dir && existsSync(join(dir, name)) && !env.RUSTFLAGS && !env.CARGO_ENCODED_RUSTFLAGS) {
97
+ notes.push(`${name} in ${dir === root ? '<workspace>' : '<cargo home>'}/.cargo: rustflags set there are replaced by the environment's; copy them into RUSTFLAGS if the build needs them`);
98
+ }
99
+ }
100
+ }
101
+ return { env: out, maps, notes };
102
+ }
103
+
104
+ const quote = arg => (/^[A-Za-z0-9_@%+=:,./\\-]+$/.test(arg) ? arg : `"${arg.replaceAll('"', '\\"')}"`);
105
+
106
+ /** `waybetter build-env ...`; returns the exit code. */
107
+ export function buildEnvCommand(argv, { cwd = process.cwd(), env = process.env, log = console.log } = {}) {
108
+ const split = argv.indexOf('--');
109
+ const own = split >= 0 ? argv.slice(0, split) : argv;
110
+ const command = split >= 0 ? argv.slice(split + 1) : [];
111
+ if (own.includes('--help') || own.includes('-h')) { log(BUILD_ENV_USAGE); return 0; }
112
+ const rootAt = own.indexOf('--root');
113
+ const root = rootAt >= 0 && own[rootAt + 1] ? resolve(cwd, own[rootAt + 1]) : workspaceRoot(cwd);
114
+ const result = pathFreeBuildEnv({ root, env });
115
+ if (command.length) {
116
+ for (const note of result.notes) console.error(`waybetter build-env: ${note}`);
117
+ // The caller's own command line, run through the shell so .cmd shims (bun, tauri) resolve.
118
+ const run = spawnSync(command.map(quote).join(' '), { cwd, stdio: 'inherit', shell: true, env: { ...env, ...result.env } });
119
+ return run.status ?? 1;
120
+ }
121
+ if (own.includes('--json')) {
122
+ log(JSON.stringify(result.env, null, 2));
123
+ return 0;
124
+ }
125
+ log('Path-free build environment (waybetter build-env -- <command> runs a command with it):');
126
+ for (const [name, value] of Object.entries(result.env)) log(` ${name}=${value.replaceAll(SEPARATOR, ' ')}`);
127
+ if (result.env.CARGO_ENCODED_RUSTFLAGS.includes(SEPARATOR)) log(' (CARGO_ENCODED_RUSTFLAGS separates its flags with the 0x1f character, shown as a space; --json has the exact value)');
128
+ for (const note of result.notes) log(` note: ${note}`);
129
+ return 0;
130
+ }
package/cli/dev.mjs ADDED
@@ -0,0 +1,97 @@
1
+ // `waybetter dev`: the dev loop in one command. Starts the app's build watchers, waits until each
2
+ // has built once, then runs `tauri dev`. In a debug build the host reads the page scripts from disk
3
+ // and rebuilds its tabs when a watcher rewrites one (`waybetter_host::page_script!`), and the
4
+ // shell hot-reloads through the frontend dev server (`beforeDevCommand`, e.g. vite).
5
+ //
6
+ // waybetter dev [--stable] [--watch "<command>"]... [-- <tauri dev args>]
7
+ //
8
+ // `--stable` adds `--no-watch`: Rust changes do not restart the app (restart it yourself); page
9
+ // script and shell changes still reload live. Every `--watch` command must keep running and print
10
+ // a line containing "watching" once its first build is done (`buildRuntime({ watch: true })`
11
+ // scripts print one); it is stopped with the app.
12
+ import { spawn, spawnSync } from 'node:child_process';
13
+ import { delimiter, join, resolve } from 'node:path';
14
+
15
+ export const DEV_USAGE = `Usage:
16
+ waybetter dev [--stable] [--watch "<command>"]... [-- <tauri dev args>]
17
+ Starts each --watch command (esbuild watchers), waits for its first build ("watching" on a
18
+ line of its output, at most 120 s), then runs \`tauri dev\`. --stable passes --no-watch so a
19
+ Rust file saved by someone else does not restart the app; Rust changes then need a manual
20
+ restart, page-script and shell changes reload live either way.`;
21
+
22
+ const READY = /watching/i;
23
+ const READY_TIMEOUT_MS = 120_000;
24
+
25
+ /** `waybetter dev` arguments: `{ stable, watch: string[], tauriArgs: string[] }`. */
26
+ export function parseDevArgs(args) {
27
+ const out = { stable: false, watch: [], tauriArgs: [] };
28
+ for (let index = 0; index < args.length; index += 1) {
29
+ const arg = args[index];
30
+ if (arg === '--') {
31
+ out.tauriArgs = args.slice(index + 1);
32
+ break;
33
+ }
34
+ if (arg === '--stable') out.stable = true;
35
+ else if (arg === '--watch') {
36
+ const command = args[(index += 1)];
37
+ if (!command) throw new Error('--watch needs a command');
38
+ out.watch.push(command);
39
+ } else throw new Error(`unknown argument: ${arg}`);
40
+ }
41
+ return out;
42
+ }
43
+
44
+ /** The `tauri dev` arguments. */
45
+ export function tauriDevArgs({ stable, tauriArgs }) {
46
+ return ['dev', ...(stable && !tauriArgs.includes('--no-watch') ? ['--no-watch'] : []), ...tauriArgs];
47
+ }
48
+
49
+ function stop(child) {
50
+ if (!child.pid || child.exitCode !== null) return;
51
+ if (process.platform === 'win32') spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], { stdio: 'ignore' });
52
+ else child.kill('SIGTERM');
53
+ }
54
+
55
+ export async function devCommand(args, cwd = process.cwd()) {
56
+ const options = parseDevArgs(args);
57
+ // Local tools (tauri, esbuild) the way an npm script finds them.
58
+ const env = { ...process.env, PATH: [join(cwd, 'node_modules', '.bin'), resolve(cwd, '..', 'node_modules', '.bin'), resolve(cwd, '..', '..', 'node_modules', '.bin'), process.env.PATH].join(delimiter) };
59
+ const children = [];
60
+ const stopAll = () => children.forEach(stop);
61
+ process.on('exit', stopAll);
62
+ for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, () => process.exit(130));
63
+
64
+ for (const command of options.watch) {
65
+ const child = spawn(command, { cwd, env, shell: true, stdio: ['ignore', 'pipe', 'inherit'] });
66
+ children.push(child);
67
+ await new Promise((done, fail) => {
68
+ const timer = setTimeout(() => fail(new Error(`watcher did not report "watching" in time: ${command}`)), READY_TIMEOUT_MS);
69
+ let ready = false;
70
+ child.stdout.on('data', chunk => {
71
+ process.stdout.write(chunk);
72
+ if (!ready && READY.test(String(chunk))) {
73
+ ready = true;
74
+ clearTimeout(timer);
75
+ done();
76
+ }
77
+ });
78
+ child.on('exit', code => {
79
+ clearTimeout(timer);
80
+ if (!ready) fail(new Error(`watcher exited (${code}) before its first build: ${command}`));
81
+ else console.error(`waybetter dev: a watcher stopped (${code}): ${command}`);
82
+ });
83
+ }).catch(error => {
84
+ stopAll();
85
+ throw error;
86
+ });
87
+ }
88
+
89
+ const tauri = spawn('tauri', tauriDevArgs(options), { cwd, env, shell: true, stdio: 'inherit' });
90
+ children.push(tauri);
91
+ return new Promise(done =>
92
+ tauri.on('exit', code => {
93
+ stopAll();
94
+ done(code ?? 0);
95
+ }),
96
+ );
97
+ }