@ohmykreee/dsh-remote-control 0.0.0-stage → 1.0.2

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 (373) hide show
  1. package/AGENTS.md +556 -0
  2. package/INSTALLATION.md +310 -0
  3. package/LICENSE +21 -0
  4. package/README.md +195 -2
  5. package/client.js +3 -0
  6. package/components.json +20 -0
  7. package/cordis.patch.yml +3 -0
  8. package/docs/README.en.md +196 -0
  9. package/docs/screenshots/en/overview.png +0 -0
  10. package/docs/screenshots/en/question.png +0 -0
  11. package/docs/screenshots/zh/overview.png +0 -0
  12. package/docs/screenshots/zh/question.png +0 -0
  13. package/icon.svg +24 -0
  14. package/index.js +2 -0
  15. package/lib/account.js +1 -0
  16. package/lib/app-mapping.js +1 -0
  17. package/lib/i18n.js +1 -0
  18. package/lib/media-enrich.js +1 -0
  19. package/lib/notifications.js +1 -0
  20. package/lib/performance.js +1 -0
  21. package/lib/platform/index.js +1 -0
  22. package/lib/probe-adapter.js +1 -0
  23. package/lib/probe-daemon.js +1 -0
  24. package/lib/probe.js +1 -0
  25. package/lib/qr.js +1 -0
  26. package/lib/runtime.js +1 -0
  27. package/lib/service.js +1 -0
  28. package/lib/sessions.js +1 -0
  29. package/lib/settings.js +1 -0
  30. package/lib/types.js +1 -0
  31. package/lib/util.js +1 -0
  32. package/lib/weather.js +1 -0
  33. package/lib/ws.js +1 -0
  34. package/locale/en.json +6 -0
  35. package/locale/zh.json +6 -0
  36. package/package.json +118 -4
  37. package/scripts/browser-shot.mjs +217 -0
  38. package/scripts/build-dsh.mjs +228 -0
  39. package/scripts/build-rust.mjs +319 -0
  40. package/scripts/build-web.mjs +17 -0
  41. package/scripts/check-npm-package.mjs +322 -0
  42. package/scripts/mock-preview.py +574 -0
  43. package/scripts/screenshot-compose.py +89 -0
  44. package/scripts/screenshot-device.sh +75 -0
  45. package/src/dsh/client/api.ts +68 -0
  46. package/src/dsh/client/i18n.ts +573 -0
  47. package/src/dsh/client/icons.ts +56 -0
  48. package/src/dsh/client/index.ts +95 -0
  49. package/src/dsh/client/logic.ts +310 -0
  50. package/src/dsh/client/panel.ts +483 -0
  51. package/src/dsh/client/sections/apps.ts +40 -0
  52. package/src/dsh/client/sections/balance.ts +38 -0
  53. package/src/dsh/client/sections/connection.ts +97 -0
  54. package/src/dsh/client/sections/notifications.ts +43 -0
  55. package/src/dsh/client/sections/pomodoro.ts +184 -0
  56. package/src/dsh/client/sections/preferences.ts +138 -0
  57. package/src/dsh/client/sections/system.ts +120 -0
  58. package/src/dsh/client/sections/weather.ts +276 -0
  59. package/src/dsh/client/styles.ts +1119 -0
  60. package/src/dsh/client/types.ts +366 -0
  61. package/src/dsh/client/ui.ts +142 -0
  62. package/src/dsh/index.ts +108 -0
  63. package/src/dsh/lib/account.ts +520 -0
  64. package/src/dsh/lib/app-mapping.ts +366 -0
  65. package/src/dsh/lib/i18n.ts +82 -0
  66. package/src/dsh/lib/media-enrich.ts +202 -0
  67. package/src/dsh/lib/notifications.ts +322 -0
  68. package/src/dsh/lib/performance.ts +279 -0
  69. package/src/dsh/lib/platform/index.ts +43 -0
  70. package/src/dsh/lib/probe-adapter.ts +275 -0
  71. package/src/dsh/lib/probe-daemon.ts +359 -0
  72. package/src/dsh/lib/probe.ts +395 -0
  73. package/src/dsh/lib/qr.ts +42 -0
  74. package/src/dsh/lib/runtime.ts +126 -0
  75. package/src/dsh/lib/service.ts +1645 -0
  76. package/src/dsh/lib/sessions.ts +907 -0
  77. package/src/dsh/lib/settings.ts +468 -0
  78. package/src/dsh/lib/types.ts +231 -0
  79. package/src/dsh/lib/util.ts +115 -0
  80. package/src/dsh/lib/weather.ts +532 -0
  81. package/src/dsh/lib/ws.ts +328 -0
  82. package/src/dsh/types/qrcode-generator.d.ts +16 -0
  83. package/src/rust/Cargo.lock +1431 -0
  84. package/src/rust/Cargo.toml +68 -0
  85. package/src/rust/src/cli.rs +233 -0
  86. package/src/rust/src/daemon.rs +140 -0
  87. package/src/rust/src/location/linux.rs +118 -0
  88. package/src/rust/src/location/macos.rs +26 -0
  89. package/src/rust/src/location/mod.rs +170 -0
  90. package/src/rust/src/location/windows.rs +205 -0
  91. package/src/rust/src/main.rs +42 -0
  92. package/src/rust/src/media/catalog.rs +454 -0
  93. package/src/rust/src/media/linux.rs +350 -0
  94. package/src/rust/src/media/macos/accessibility.rs +59 -0
  95. package/src/rust/src/media/macos.rs +366 -0
  96. package/src/rust/src/media/mod.rs +298 -0
  97. package/src/rust/src/media/vendor/apple_music.rs +90 -0
  98. package/src/rust/src/media/vendor/common.rs +186 -0
  99. package/src/rust/src/media/vendor/kugou.rs +52 -0
  100. package/src/rust/src/media/vendor/kuwo.rs +49 -0
  101. package/src/rust/src/media/vendor/mod.rs +75 -0
  102. package/src/rust/src/media/vendor/netease.rs +1715 -0
  103. package/src/rust/src/media/vendor/qishui.rs +36 -0
  104. package/src/rust/src/media/vendor/qqmusic.rs +33 -0
  105. package/src/rust/src/media/vendor/spotify.rs +46 -0
  106. package/src/rust/src/media/vendor/wesing.rs +39 -0
  107. package/src/rust/src/media/vendor/youtube_music.rs +49 -0
  108. package/src/rust/src/media/windows/accessibility.rs +85 -0
  109. package/src/rust/src/media/windows/audio.rs +116 -0
  110. package/src/rust/src/media/windows/private.rs +291 -0
  111. package/src/rust/src/media/windows.rs +775 -0
  112. package/src/rust/src/notifications/linux.rs +276 -0
  113. package/src/rust/src/notifications/macos.rs +382 -0
  114. package/src/rust/src/notifications/mod.rs +244 -0
  115. package/src/rust/src/notifications/windows.rs +565 -0
  116. package/src/rust/src/perf/common.rs +109 -0
  117. package/src/rust/src/perf/linux.rs +282 -0
  118. package/src/rust/src/perf/macos.rs +28 -0
  119. package/src/rust/src/perf/mod.rs +157 -0
  120. package/src/rust/src/perf/windows.rs +981 -0
  121. package/src/rust/src/util.rs +360 -0
  122. package/src/rust/src/volume/linux.rs +195 -0
  123. package/src/rust/src/volume/macos.rs +54 -0
  124. package/src/rust/src/volume/mod.rs +116 -0
  125. package/src/rust/src/volume/windows.rs +75 -0
  126. package/src/rust/tests/cli.rs +79 -0
  127. package/src/rust/tests/daemon.rs +107 -0
  128. package/src/svelte/App.svelte +385 -0
  129. package/src/svelte/index.html +18 -0
  130. package/src/svelte/lib/billing.svelte.ts +228 -0
  131. package/src/svelte/lib/components/BalanceCard.svelte +173 -0
  132. package/src/svelte/lib/components/ClockCard.svelte +183 -0
  133. package/src/svelte/lib/components/CountdownCard.svelte +261 -0
  134. package/src/svelte/lib/components/CpuMemoryCard.svelte +238 -0
  135. package/src/svelte/lib/components/EmptyState.svelte +34 -0
  136. package/src/svelte/lib/components/GpuCard.svelte +245 -0
  137. package/src/svelte/lib/components/HomePage.svelte +34 -0
  138. package/src/svelte/lib/components/MusicControls.svelte +256 -0
  139. package/src/svelte/lib/components/MusicCover.svelte +88 -0
  140. package/src/svelte/lib/components/MusicPage.svelte +116 -0
  141. package/src/svelte/lib/components/NotificationsCard.svelte +109 -0
  142. package/src/svelte/lib/components/Panel.svelte +22 -0
  143. package/src/svelte/lib/components/PerformancePage.svelte +55 -0
  144. package/src/svelte/lib/components/PomodoroCard.svelte +250 -0
  145. package/src/svelte/lib/components/QuestionSheet.svelte +354 -0
  146. package/src/svelte/lib/components/RadialGauge.svelte +99 -0
  147. package/src/svelte/lib/components/Rail.svelte +217 -0
  148. package/src/svelte/lib/components/SectionHeader.svelte +40 -0
  149. package/src/svelte/lib/components/SeekBar.svelte +421 -0
  150. package/src/svelte/lib/components/SessionList.svelte +364 -0
  151. package/src/svelte/lib/components/SessionStats.svelte +98 -0
  152. package/src/svelte/lib/components/SessionsPage.svelte +61 -0
  153. package/src/svelte/lib/components/SpendCard.svelte +105 -0
  154. package/src/svelte/lib/components/ThermalCard.svelte +249 -0
  155. package/src/svelte/lib/components/Toast.svelte +32 -0
  156. package/src/svelte/lib/components/WeatherIcon.svelte +40 -0
  157. package/src/svelte/lib/components/WeatherPanel.svelte +420 -0
  158. package/src/svelte/lib/components/ui/alert/alert-action.svelte +20 -0
  159. package/src/svelte/lib/components/ui/alert/alert-description.svelte +23 -0
  160. package/src/svelte/lib/components/ui/alert/alert-title.svelte +23 -0
  161. package/src/svelte/lib/components/ui/alert/alert.svelte +43 -0
  162. package/src/svelte/lib/components/ui/alert/index.ts +17 -0
  163. package/src/svelte/lib/components/ui/avatar/avatar-badge.svelte +26 -0
  164. package/src/svelte/lib/components/ui/avatar/avatar-fallback.svelte +20 -0
  165. package/src/svelte/lib/components/ui/avatar/avatar-group-count.svelte +23 -0
  166. package/src/svelte/lib/components/ui/avatar/avatar-group.svelte +23 -0
  167. package/src/svelte/lib/components/ui/avatar/avatar-image.svelte +17 -0
  168. package/src/svelte/lib/components/ui/avatar/avatar.svelte +26 -0
  169. package/src/svelte/lib/components/ui/avatar/index.ts +22 -0
  170. package/src/svelte/lib/components/ui/badge/badge.svelte +49 -0
  171. package/src/svelte/lib/components/ui/badge/index.ts +2 -0
  172. package/src/svelte/lib/components/ui/button/button.svelte +82 -0
  173. package/src/svelte/lib/components/ui/button/index.ts +17 -0
  174. package/src/svelte/lib/components/ui/card/card-action.svelte +23 -0
  175. package/src/svelte/lib/components/ui/card/card-content.svelte +20 -0
  176. package/src/svelte/lib/components/ui/card/card-description.svelte +20 -0
  177. package/src/svelte/lib/components/ui/card/card-footer.svelte +20 -0
  178. package/src/svelte/lib/components/ui/card/card-header.svelte +23 -0
  179. package/src/svelte/lib/components/ui/card/card-title.svelte +20 -0
  180. package/src/svelte/lib/components/ui/card/card.svelte +22 -0
  181. package/src/svelte/lib/components/ui/card/index.ts +25 -0
  182. package/src/svelte/lib/components/ui/dialog/dialog-close.svelte +11 -0
  183. package/src/svelte/lib/components/ui/dialog/dialog-content.svelte +48 -0
  184. package/src/svelte/lib/components/ui/dialog/dialog-description.svelte +17 -0
  185. package/src/svelte/lib/components/ui/dialog/dialog-footer.svelte +32 -0
  186. package/src/svelte/lib/components/ui/dialog/dialog-header.svelte +20 -0
  187. package/src/svelte/lib/components/ui/dialog/dialog-overlay.svelte +17 -0
  188. package/src/svelte/lib/components/ui/dialog/dialog-portal.svelte +7 -0
  189. package/src/svelte/lib/components/ui/dialog/dialog-title.svelte +17 -0
  190. package/src/svelte/lib/components/ui/dialog/dialog-trigger.svelte +11 -0
  191. package/src/svelte/lib/components/ui/dialog/dialog.svelte +7 -0
  192. package/src/svelte/lib/components/ui/dialog/index.ts +34 -0
  193. package/src/svelte/lib/components/ui/empty/empty-content.svelte +23 -0
  194. package/src/svelte/lib/components/ui/empty/empty-description.svelte +23 -0
  195. package/src/svelte/lib/components/ui/empty/empty-header.svelte +20 -0
  196. package/src/svelte/lib/components/ui/empty/empty-media.svelte +41 -0
  197. package/src/svelte/lib/components/ui/empty/empty-title.svelte +20 -0
  198. package/src/svelte/lib/components/ui/empty/empty.svelte +23 -0
  199. package/src/svelte/lib/components/ui/empty/index.ts +22 -0
  200. package/src/svelte/lib/components/ui/input/index.ts +7 -0
  201. package/src/svelte/lib/components/ui/input/input.svelte +48 -0
  202. package/src/svelte/lib/components/ui/progress/index.ts +7 -0
  203. package/src/svelte/lib/components/ui/progress/progress.svelte +27 -0
  204. package/src/svelte/lib/components/ui/scroll-area/index.ts +10 -0
  205. package/src/svelte/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte +30 -0
  206. package/src/svelte/lib/components/ui/scroll-area/scroll-area.svelte +43 -0
  207. package/src/svelte/lib/components/ui/separator/index.ts +7 -0
  208. package/src/svelte/lib/components/ui/separator/separator.svelte +21 -0
  209. package/src/svelte/lib/components/ui/sheet/index.ts +34 -0
  210. package/src/svelte/lib/components/ui/sheet/sheet-close.svelte +7 -0
  211. package/src/svelte/lib/components/ui/sheet/sheet-content.svelte +55 -0
  212. package/src/svelte/lib/components/ui/sheet/sheet-description.svelte +17 -0
  213. package/src/svelte/lib/components/ui/sheet/sheet-footer.svelte +20 -0
  214. package/src/svelte/lib/components/ui/sheet/sheet-header.svelte +20 -0
  215. package/src/svelte/lib/components/ui/sheet/sheet-overlay.svelte +20 -0
  216. package/src/svelte/lib/components/ui/sheet/sheet-portal.svelte +7 -0
  217. package/src/svelte/lib/components/ui/sheet/sheet-title.svelte +17 -0
  218. package/src/svelte/lib/components/ui/sheet/sheet-trigger.svelte +7 -0
  219. package/src/svelte/lib/components/ui/sheet/sheet.svelte +7 -0
  220. package/src/svelte/lib/components/ui/skeleton/index.ts +7 -0
  221. package/src/svelte/lib/components/ui/skeleton/skeleton.svelte +17 -0
  222. package/src/svelte/lib/components/ui/slider/index.ts +7 -0
  223. package/src/svelte/lib/components/ui/slider/slider.svelte +52 -0
  224. package/src/svelte/lib/components/ui/tooltip/index.ts +19 -0
  225. package/src/svelte/lib/components/ui/tooltip/tooltip-content.svelte +51 -0
  226. package/src/svelte/lib/components/ui/tooltip/tooltip-portal.svelte +7 -0
  227. package/src/svelte/lib/components/ui/tooltip/tooltip-provider.svelte +7 -0
  228. package/src/svelte/lib/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  229. package/src/svelte/lib/components/ui/tooltip/tooltip.svelte +7 -0
  230. package/src/svelte/lib/countdown.svelte.ts +252 -0
  231. package/src/svelte/lib/format.ts +199 -0
  232. package/src/svelte/lib/i18n.svelte.ts +583 -0
  233. package/src/svelte/lib/media.ts +32 -0
  234. package/src/svelte/lib/pages.ts +18 -0
  235. package/src/svelte/lib/pomodoro.svelte.ts +223 -0
  236. package/src/svelte/lib/session-tree.ts +80 -0
  237. package/src/svelte/lib/state.svelte.ts +359 -0
  238. package/src/svelte/lib/timer-alarm.svelte.ts +319 -0
  239. package/src/svelte/lib/types.ts +306 -0
  240. package/src/svelte/lib/utils.ts +8 -0
  241. package/src/svelte/lib/weather.ts +84 -0
  242. package/src/svelte/lib/ws.ts +104 -0
  243. package/src/svelte/main.ts +13 -0
  244. package/src/svelte/styles/global.css +315 -0
  245. package/src/svelte/vite-env.d.ts +12 -0
  246. package/static/fonts/LICENSE.txt +287 -0
  247. package/static/icon.svg +24 -0
  248. package/static/manifest.webmanifest +18 -0
  249. package/svelte.config.js +5 -0
  250. package/tsconfig.dsh-client.json +18 -0
  251. package/tsconfig.dsh.json +21 -0
  252. package/tsconfig.json +20 -0
  253. package/vite.config.js +31 -0
  254. package/web/assets/index-DLdSfnJ3.css +1 -0
  255. package/web/assets/index-YNE8X0Uy.js +6 -0
  256. package/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  257. package/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  258. package/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  259. package/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  260. package/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  261. package/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  262. package/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  263. package/web/assets/jetbrains-mono-cyrillic-ext-wght-normal-EocZY2iu.woff2 +0 -0
  264. package/web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  265. package/web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  266. package/web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  267. package/web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  268. package/web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  269. package/web/assets/noto-sans-sc-100-wght-normal-DluiXYzi.woff2 +0 -0
  270. package/web/assets/noto-sans-sc-101-wght-normal-CPkZHnw0.woff2 +0 -0
  271. package/web/assets/noto-sans-sc-102-wght-normal-gzIulUH6.woff2 +0 -0
  272. package/web/assets/noto-sans-sc-103-wght-normal-CJfSBxFo.woff2 +0 -0
  273. package/web/assets/noto-sans-sc-104-wght-normal-B3QMglgE.woff2 +0 -0
  274. package/web/assets/noto-sans-sc-105-wght-normal-xXh_OMfk.woff2 +0 -0
  275. package/web/assets/noto-sans-sc-106-wght-normal-B9n3jMjP.woff2 +0 -0
  276. package/web/assets/noto-sans-sc-107-wght-normal-D7fvVprN.woff2 +0 -0
  277. package/web/assets/noto-sans-sc-108-wght-normal-J0_LhxVo.woff2 +0 -0
  278. package/web/assets/noto-sans-sc-109-wght-normal-Dsp-De_0.woff2 +0 -0
  279. package/web/assets/noto-sans-sc-110-wght-normal-DE_6NUrb.woff2 +0 -0
  280. package/web/assets/noto-sans-sc-111-wght-normal-C4S-TlTn.woff2 +0 -0
  281. package/web/assets/noto-sans-sc-112-wght-normal-BcFuP3w6.woff2 +0 -0
  282. package/web/assets/noto-sans-sc-113-wght-normal-Dk932kmj.woff2 +0 -0
  283. package/web/assets/noto-sans-sc-114-wght-normal-CO_5Xo-i.woff2 +0 -0
  284. package/web/assets/noto-sans-sc-115-wght-normal-BWy07H14.woff2 +0 -0
  285. package/web/assets/noto-sans-sc-116-wght-normal-B4HVAfHo.woff2 +0 -0
  286. package/web/assets/noto-sans-sc-117-wght-normal-siZzFqgK.woff2 +0 -0
  287. package/web/assets/noto-sans-sc-118-wght-normal-xhBB7f6V.woff2 +0 -0
  288. package/web/assets/noto-sans-sc-119-wght-normal-Ck_g2FGz.woff2 +0 -0
  289. package/web/assets/noto-sans-sc-21-wght-normal-D0x9-yBt.woff2 +0 -0
  290. package/web/assets/noto-sans-sc-22-wght-normal-BBUVTShg.woff2 +0 -0
  291. package/web/assets/noto-sans-sc-23-wght-normal-Du1oYWkE.woff2 +0 -0
  292. package/web/assets/noto-sans-sc-24-wght-normal-CmWjJ0gt.woff2 +0 -0
  293. package/web/assets/noto-sans-sc-25-wght-normal-BFHiqilg.woff2 +0 -0
  294. package/web/assets/noto-sans-sc-26-wght-normal-C0sF2Z2f.woff2 +0 -0
  295. package/web/assets/noto-sans-sc-27-wght-normal-COFdrquJ.woff2 +0 -0
  296. package/web/assets/noto-sans-sc-28-wght-normal-DMgdNu1o.woff2 +0 -0
  297. package/web/assets/noto-sans-sc-29-wght-normal-Cmq8em30.woff2 +0 -0
  298. package/web/assets/noto-sans-sc-30-wght-normal-CZWqZ3yU.woff2 +0 -0
  299. package/web/assets/noto-sans-sc-31-wght-normal-Wfi_lutW.woff2 +0 -0
  300. package/web/assets/noto-sans-sc-32-wght-normal-BRJQ4PY5.woff2 +0 -0
  301. package/web/assets/noto-sans-sc-33-wght-normal-CUVQXNAJ.woff2 +0 -0
  302. package/web/assets/noto-sans-sc-34-wght-normal-Bspba0wC.woff2 +0 -0
  303. package/web/assets/noto-sans-sc-35-wght-normal-K8fX_YPG.woff2 +0 -0
  304. package/web/assets/noto-sans-sc-36-wght-normal-CkITyjoT.woff2 +0 -0
  305. package/web/assets/noto-sans-sc-37-wght-normal-WCZ2zfEe.woff2 +0 -0
  306. package/web/assets/noto-sans-sc-38-wght-normal-DeM7CUce.woff2 +0 -0
  307. package/web/assets/noto-sans-sc-39-wght-normal-BMZNLWQU.woff2 +0 -0
  308. package/web/assets/noto-sans-sc-4-wght-normal-AR5bdDjz.woff2 +0 -0
  309. package/web/assets/noto-sans-sc-40-wght-normal-BQ5xpS5j.woff2 +0 -0
  310. package/web/assets/noto-sans-sc-41-wght-normal-Hthm7FFi.woff2 +0 -0
  311. package/web/assets/noto-sans-sc-42-wght-normal-eaS2gKds.woff2 +0 -0
  312. package/web/assets/noto-sans-sc-43-wght-normal-o-T53XXV.woff2 +0 -0
  313. package/web/assets/noto-sans-sc-44-wght-normal-BJH5J4Ez.woff2 +0 -0
  314. package/web/assets/noto-sans-sc-45-wght-normal-BKuxSCOJ.woff2 +0 -0
  315. package/web/assets/noto-sans-sc-46-wght-normal-BR_5Mu6e.woff2 +0 -0
  316. package/web/assets/noto-sans-sc-47-wght-normal-CyY7gKNX.woff2 +0 -0
  317. package/web/assets/noto-sans-sc-48-wght-normal-BNMfTR6k.woff2 +0 -0
  318. package/web/assets/noto-sans-sc-49-wght-normal-DX-0y7wg.woff2 +0 -0
  319. package/web/assets/noto-sans-sc-5-wght-normal-CfWugllB.woff2 +0 -0
  320. package/web/assets/noto-sans-sc-50-wght-normal-DAOGW-Dr.woff2 +0 -0
  321. package/web/assets/noto-sans-sc-51-wght-normal-BlFLOjcP.woff2 +0 -0
  322. package/web/assets/noto-sans-sc-52-wght-normal-OZjrybnw.woff2 +0 -0
  323. package/web/assets/noto-sans-sc-53-wght-normal-CwyWNT6x.woff2 +0 -0
  324. package/web/assets/noto-sans-sc-54-wght-normal-DM0nRe18.woff2 +0 -0
  325. package/web/assets/noto-sans-sc-55-wght-normal-DBK2wUOR.woff2 +0 -0
  326. package/web/assets/noto-sans-sc-56-wght-normal-C-VKK1LS.woff2 +0 -0
  327. package/web/assets/noto-sans-sc-57-wght-normal-Cdbfh5kq.woff2 +0 -0
  328. package/web/assets/noto-sans-sc-58-wght-normal-CflMKARZ.woff2 +0 -0
  329. package/web/assets/noto-sans-sc-59-wght-normal-BS4Kwzxx.woff2 +0 -0
  330. package/web/assets/noto-sans-sc-6-wght-normal-ChnZIQfQ.woff2 +0 -0
  331. package/web/assets/noto-sans-sc-60-wght-normal-B7QOYsXJ.woff2 +0 -0
  332. package/web/assets/noto-sans-sc-61-wght-normal-C8JjQS7w.woff2 +0 -0
  333. package/web/assets/noto-sans-sc-62-wght-normal-bS4wq1Gg.woff2 +0 -0
  334. package/web/assets/noto-sans-sc-63-wght-normal-BJr8P-OB.woff2 +0 -0
  335. package/web/assets/noto-sans-sc-64-wght-normal-DVB11t7j.woff2 +0 -0
  336. package/web/assets/noto-sans-sc-65-wght-normal-DMPCXBvK.woff2 +0 -0
  337. package/web/assets/noto-sans-sc-66-wght-normal-BobaG10V.woff2 +0 -0
  338. package/web/assets/noto-sans-sc-67-wght-normal-Dzk7WhCR.woff2 +0 -0
  339. package/web/assets/noto-sans-sc-68-wght-normal-DGbCD9xu.woff2 +0 -0
  340. package/web/assets/noto-sans-sc-69-wght-normal-Ctrv1EqA.woff2 +0 -0
  341. package/web/assets/noto-sans-sc-70-wght-normal-RgTO941D.woff2 +0 -0
  342. package/web/assets/noto-sans-sc-71-wght-normal-D9sG-CWv.woff2 +0 -0
  343. package/web/assets/noto-sans-sc-72-wght-normal-C4oWy3ul.woff2 +0 -0
  344. package/web/assets/noto-sans-sc-73-wght-normal-B1ZoOTgM.woff2 +0 -0
  345. package/web/assets/noto-sans-sc-74-wght-normal-F7dH_rZJ.woff2 +0 -0
  346. package/web/assets/noto-sans-sc-75-wght-normal-Cp2wp4si.woff2 +0 -0
  347. package/web/assets/noto-sans-sc-76-wght-normal-B494D7xS.woff2 +0 -0
  348. package/web/assets/noto-sans-sc-77-wght-normal-B3MVY9Ax.woff2 +0 -0
  349. package/web/assets/noto-sans-sc-78-wght-normal-5jX7iNMC.woff2 +0 -0
  350. package/web/assets/noto-sans-sc-79-wght-normal-BIoZy8fr.woff2 +0 -0
  351. package/web/assets/noto-sans-sc-80-wght-normal-Bje1Fxy1.woff2 +0 -0
  352. package/web/assets/noto-sans-sc-81-wght-normal-B2NN7Qi3.woff2 +0 -0
  353. package/web/assets/noto-sans-sc-82-wght-normal-CUggNZi4.woff2 +0 -0
  354. package/web/assets/noto-sans-sc-83-wght-normal-99rD8YO-.woff2 +0 -0
  355. package/web/assets/noto-sans-sc-84-wght-normal-zMBmUocm.woff2 +0 -0
  356. package/web/assets/noto-sans-sc-85-wght-normal-CjI3qdxG.woff2 +0 -0
  357. package/web/assets/noto-sans-sc-86-wght-normal-BHY8TVEH.woff2 +0 -0
  358. package/web/assets/noto-sans-sc-87-wght-normal-DioZSHnU.woff2 +0 -0
  359. package/web/assets/noto-sans-sc-88-wght-normal-BXYxwf2t.woff2 +0 -0
  360. package/web/assets/noto-sans-sc-89-wght-normal-ClMFrFaL.woff2 +0 -0
  361. package/web/assets/noto-sans-sc-90-wght-normal-BnOlPreP.woff2 +0 -0
  362. package/web/assets/noto-sans-sc-91-wght-normal-DTr9RQcS.woff2 +0 -0
  363. package/web/assets/noto-sans-sc-97-wght-normal-9u6Aiav-.woff2 +0 -0
  364. package/web/assets/noto-sans-sc-98-wght-normal-BR-H2C0V.woff2 +0 -0
  365. package/web/assets/noto-sans-sc-99-wght-normal-BI6XPoxp.woff2 +0 -0
  366. package/web/assets/noto-sans-sc-cyrillic-wght-normal-BGmsQlw-.woff2 +0 -0
  367. package/web/assets/noto-sans-sc-latin-ext-wght-normal-DuJTpTg_.woff2 +0 -0
  368. package/web/assets/noto-sans-sc-latin-wght-normal-DDW8mKAR.woff2 +0 -0
  369. package/web/assets/noto-sans-sc-vietnamese-wght-normal-Bi3ATJ76.woff2 +0 -0
  370. package/web/fonts/LICENSE.txt +287 -0
  371. package/web/icon.svg +24 -0
  372. package/web/index.html +19 -0
  373. package/web/manifest.webmanifest +18 -0
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Compile the TypeScript source under `src/dsh` into the plugin's native
4
+ * runtime layout:
5
+ *
6
+ * src/dsh/index.ts -> <root>/index.js
7
+ * src/dsh/lib/**\/*.ts -> <root>/lib/**\/*.js
8
+ * src/dsh/client/index.ts -> <root>/client.js (all client modules bundled)
9
+ *
10
+ * The client half is split into ordinary TypeScript modules (types, i18n,
11
+ * API/state helpers, primitives, sections, panel) and concatenated here into
12
+ * one module table. `client.js` is wrapped in the DSH browser module-loading
13
+ * contract: a classic script that registers a lazy factory with
14
+ * `window.__ModuleLoader__`, whose id is the package name and whose `require`
15
+ * provides the shared `react` module.
16
+ * The Host half is emitted as native ESM, matching `"type": "module"`.
17
+ *
18
+ * The emitted files are local build artifacts. They are gitignored and were
19
+ * removed from git with `git rm`: run `pnpm build` (whose first step this
20
+ * script is) before loading the plugin. Terser minifies the Host ESM output
21
+ * and the client factory after compilation.
22
+ */
23
+
24
+ import {
25
+ cpSync,
26
+ existsSync,
27
+ mkdirSync,
28
+ readFileSync,
29
+ readdirSync,
30
+ rmSync,
31
+ statSync,
32
+ writeFileSync,
33
+ } from 'node:fs';
34
+ import path from 'node:path';
35
+ import { fileURLToPath } from 'node:url';
36
+ import ts from 'typescript';
37
+ import { minify } from 'terser';
38
+
39
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
40
+ const buildDir = path.join(root, '.build');
41
+ const hostTsconfig = 'tsconfig.dsh.json';
42
+ const clientTsconfig = 'tsconfig.dsh-client.json';
43
+ const outputFiles = ['index.js', 'client.js'];
44
+ const outputDirs = ['lib'];
45
+ const CLIENT_ENTRY = 'client/index.js';
46
+
47
+ const GENERATED = '/** Generated by scripts/build-dsh.mjs from src/dsh — do not edit. */';
48
+
49
+ function formatDiagnostics(diagnostics) {
50
+ return ts.formatDiagnosticsWithColorAndContext(diagnostics, {
51
+ getCanonicalFileName: (fileName) => fileName,
52
+ getCurrentDirectory: () => root,
53
+ getNewLine: () => '\n',
54
+ });
55
+ }
56
+
57
+ function compile(configName) {
58
+ const configPath = path.join(root, configName);
59
+ if (!existsSync(configPath)) throw new Error(`missing TypeScript config: ${configName}`);
60
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
61
+ if (configFile.error) {
62
+ console.error(formatDiagnostics([configFile.error]));
63
+ process.exit(1);
64
+ }
65
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, root, undefined, configPath);
66
+ if (parsed.errors.length > 0) {
67
+ console.error(formatDiagnostics(parsed.errors));
68
+ process.exit(1);
69
+ }
70
+ const program = ts.createProgram({ rootNames: parsed.fileNames, options: parsed.options });
71
+ const emitted = program.emit();
72
+ const diagnostics = ts.getPreEmitDiagnostics(program).concat(emitted.diagnostics);
73
+ if (diagnostics.length > 0) {
74
+ console.error(formatDiagnostics(diagnostics));
75
+ process.exit(1);
76
+ }
77
+ }
78
+
79
+ function clean() {
80
+ rmSync(buildDir, { recursive: true, force: true });
81
+ for (const file of outputFiles) rmSync(path.join(root, file), { force: true });
82
+ for (const dir of outputDirs) rmSync(path.join(root, dir), { recursive: true, force: true });
83
+ }
84
+
85
+ function prependGenerated(file) {
86
+ const body = readFileSync(file, 'utf8');
87
+ writeFileSync(file, `${GENERATED}\n${body}`, 'utf8');
88
+ }
89
+
90
+ function prependBanner(file, banner) {
91
+ const body = readFileSync(file, 'utf8');
92
+ writeFileSync(file, `${banner}\n${body}`, 'utf8');
93
+ }
94
+
95
+ /** Recursively list JavaScript files as absolute paths. */
96
+ function listJavaScript(directory) {
97
+ const files = [];
98
+ for (const entry of readdirSync(directory)) {
99
+ const absolute = path.join(directory, entry);
100
+ if (statSync(absolute).isDirectory()) files.push(...listJavaScript(absolute));
101
+ else if (entry.endsWith('.js')) files.push(absolute);
102
+ }
103
+ return files.sort();
104
+ }
105
+
106
+ /** Minify one generated file; host files are ESM, client.js is a classic script. */
107
+ async function minifyJavaScript(file, module) {
108
+ const source = readFileSync(file, 'utf8');
109
+ const result = await minify(source, {
110
+ ecma: 2022,
111
+ module,
112
+ compress: { passes: 2 },
113
+ mangle: true,
114
+ format: { comments: false },
115
+ });
116
+ if (!result.code) throw new Error(`terser produced no output for ${file}`);
117
+ writeFileSync(file, `${result.code}\n`, 'utf8');
118
+ }
119
+
120
+ /** Recursively list the compiled client modules, using `/`-separated ids. */
121
+ function listClientModules(directory, prefix = '') {
122
+ const files = [];
123
+ for (const entry of readdirSync(directory)) {
124
+ const absolute = path.join(directory, entry);
125
+ const id = prefix ? `${prefix}/${entry}` : entry;
126
+ if (statSync(absolute).isDirectory()) files.push(...listClientModules(absolute, id));
127
+ else if (entry.endsWith('.js')) files.push(id);
128
+ }
129
+ return files.sort();
130
+ }
131
+
132
+ /**
133
+ * Wrap the CommonJS client modules in the DSH loader factory contract.
134
+ *
135
+ * The client half is split into ordinary TypeScript modules for maintenance,
136
+ * but DSH still expects one classic script. A tiny module table (with relative
137
+ * `require` resolution) lets tsc keep its normal per-file CommonJS output while
138
+ * the shipped artifact stays a single `client.js`; `react` and other bare
139
+ * specifiers still resolve through the loader's shared `require`.
140
+ */
141
+ function writeClientBundle() {
142
+ const clientRoot = path.join(buildDir, 'client');
143
+ const entryPath = path.join(clientRoot, ...CLIENT_ENTRY.split('/'));
144
+ if (!existsSync(entryPath)) throw new Error(`client compiler produced no entry: ${entryPath}`);
145
+ const modules = listClientModules(clientRoot);
146
+ if (!modules.includes(CLIENT_ENTRY)) {
147
+ throw new Error(`client entry ${CLIENT_ENTRY} was not emitted (found: ${modules.join(', ')})`);
148
+ }
149
+
150
+ const factoryModules = modules.map((id) => {
151
+ const body = readFileSync(path.join(clientRoot, ...id.split('/')), 'utf8');
152
+ return `${JSON.stringify(id)}: function (module, exports, require) {\n${body}\n}`;
153
+ });
154
+
155
+ // DSH registers the browser factory under the package name, so the id is read
156
+ // from the manifest instead of being spelled out here.
157
+ const packageName = JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8')).name;
158
+
159
+ const wrapped = [
160
+ "window.__ModuleLoader__.load({",
161
+ ` id: ${JSON.stringify(packageName)},`,
162
+ ' factory(require) {',
163
+ ' var __modules = {',
164
+ factoryModules.join(',\n'),
165
+ ' };',
166
+ ' var __cache = Object.create(null);',
167
+ ' function __normalize(from, request) {',
168
+ " var parts = from ? from.split('/') : [];",
169
+ ' parts.pop();',
170
+ " for (var segment of request.split('/')) {",
171
+ " if (!segment || segment === '.') continue;",
172
+ " if (segment === '..') parts.pop();",
173
+ ' else parts.push(segment);',
174
+ ' }',
175
+ " return parts.join('/');",
176
+ ' }',
177
+ ' function __resolve(from, request) {',
178
+ ' var target = __normalize(from, request);',
179
+ ' if (__modules[target]) return target;',
180
+ " if (__modules[target + '.js']) return target + '.js';",
181
+ " if (__modules[target + '/index.js']) return target + '/index.js';",
182
+ " throw new Error('Cannot find module \"' + request + '\" from \"' + (from || '<entry>') + '\"');",
183
+ ' }',
184
+ ' function __require(from, request) {',
185
+ " if (request.charAt(0) !== '.') return require(request);",
186
+ ' var id = __resolve(from, request);',
187
+ ' var cached = __cache[id];',
188
+ ' if (cached) return cached.exports;',
189
+ ' var module = { exports: {} };',
190
+ ' __cache[id] = module;',
191
+ ' __modules[id](module, module.exports, function (next) { return __require(id, next); });',
192
+ ' return module.exports;',
193
+ ' }',
194
+ ` return __require('', ${JSON.stringify(`./${CLIENT_ENTRY}`)});`,
195
+ ' },',
196
+ '});',
197
+ '',
198
+ ].join('\n');
199
+ writeFileSync(path.join(root, 'client.js'), wrapped, 'utf8');
200
+ return modules.length;
201
+ }
202
+
203
+ console.log('> compiling src/dsh (host, ESM)');
204
+ clean();
205
+ compile(hostTsconfig);
206
+ console.log('> compiling src/dsh/client/index.ts (browser, CommonJS modules)');
207
+ compile(clientTsconfig);
208
+
209
+ mkdirSync(path.join(root, 'lib'), { recursive: true });
210
+ cpSync(path.join(buildDir, 'host', 'index.js'), path.join(root, 'index.js'));
211
+ cpSync(path.join(buildDir, 'host', 'lib'), path.join(root, 'lib'), { recursive: true });
212
+ const clientModuleCount = writeClientBundle();
213
+
214
+ console.log('> minifying index.js, client.js, and lib/');
215
+ for (const file of [
216
+ path.join(root, 'index.js'),
217
+ path.join(root, 'client.js'),
218
+ ...listJavaScript(path.join(root, 'lib')),
219
+ ]) {
220
+ await minifyJavaScript(file, file !== path.join(root, 'client.js'));
221
+ }
222
+ prependGenerated(path.join(root, 'index.js'));
223
+ prependBanner(
224
+ path.join(root, 'client.js'),
225
+ `${GENERATED}\n/* ${clientModuleCount} client modules bundled from src/dsh/client. */`,
226
+ );
227
+
228
+ console.log('> wrote index.js, client.js, lib/');
@@ -0,0 +1,319 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build the `dsh-probe` Rust sidecar and copy it to
4
+ * `native/bin/<platform>-<arch>/dsh-probe[.exe]`.
5
+ *
6
+ * The Rust source lives in `src/rust`; the binary is intentionally gitignored:
7
+ * it is a local build artifact, not part of the repository or the npm package.
8
+ *
9
+ * Usage:
10
+ * node scripts/build-rust.mjs release build (recommended)
11
+ * node scripts/build-rust.mjs --debug debug build
12
+ * node scripts/build-rust.mjs --target x86_64-unknown-linux-gnu
13
+ * node scripts/build-rust.mjs --skip-build only copy an existing artifact
14
+ * node scripts/build-rust.mjs --optional warn and succeed when Rust is
15
+ * unavailable
16
+ */
17
+
18
+ import { execFileSync } from 'node:child_process';
19
+ import {
20
+ chmodSync,
21
+ copyFileSync,
22
+ existsSync,
23
+ mkdirSync,
24
+ rmSync,
25
+ statSync,
26
+ unlinkSync,
27
+ writeFileSync,
28
+ } from 'node:fs';
29
+ import path from 'node:path';
30
+ import { fileURLToPath } from 'node:url';
31
+
32
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
33
+ const manifest = path.join(root, 'src', 'rust', 'Cargo.toml');
34
+ const archNames = { x64: 'x64', arm64: 'arm64', ia32: 'ia32', arm: 'arm' };
35
+
36
+ const args = process.argv.slice(2);
37
+ const debug = args.includes('--debug');
38
+ const skipBuild = args.includes('--skip-build');
39
+ const optional = args.includes('--optional');
40
+ const targetIndex = args.indexOf('--target');
41
+ const target = targetIndex >= 0 ? args[targetIndex + 1] : null;
42
+ if (targetIndex >= 0 && !target) {
43
+ console.error('--target requires a Rust target triple');
44
+ process.exit(2);
45
+ }
46
+
47
+ function targetTripleParts(triple) {
48
+ if (!triple) return { platform: process.platform, arch: process.arch };
49
+ const lower = triple.toLowerCase();
50
+ let platform;
51
+ if (lower.includes('windows')) platform = 'win32';
52
+ else if (lower.includes('linux')) platform = 'linux';
53
+ else if (lower.includes('darwin') || lower.includes('apple')) platform = 'darwin';
54
+ else {
55
+ console.error(`Unsupported --target triple (expected windows/linux/darwin): ${triple}`);
56
+ process.exit(2);
57
+ }
58
+ let arch;
59
+ if (lower.startsWith('x86_64') || lower.startsWith('amd64')) arch = 'x64';
60
+ else if (lower.startsWith('aarch64') || lower.startsWith('arm64')) arch = 'arm64';
61
+ else if (lower.startsWith('i686') || lower.startsWith('i386')) arch = 'ia32';
62
+ else if (lower.startsWith('armv7') || lower.startsWith('arm')) arch = 'arm';
63
+ else arch = process.arch;
64
+ return { platform, arch: archNames[arch] || arch };
65
+ }
66
+
67
+ const effective = targetTripleParts(target);
68
+ const binaryName = effective.platform === 'win32' ? 'dsh-probe.exe' : 'dsh-probe';
69
+ const platformDir = `${effective.platform}-${effective.arch}`;
70
+ const outputDir = path.join(root, 'native', 'bin', platformDir);
71
+ const output = path.join(outputDir, binaryName);
72
+
73
+ function bail(message, code = 1) {
74
+ if (optional) {
75
+ console.warn(`${message}\nSkipping the optional Rust probe build; the console will report the probe as unavailable.`);
76
+ process.exit(0);
77
+ }
78
+ console.error(message);
79
+ process.exit(code);
80
+ }
81
+
82
+ /**
83
+ * Visual Studio's C++ tools are required for the bundled SQLite build. A normal
84
+ * terminal does not have `cl.exe`'s environment, so locate `vcvars64.bat` and
85
+ * run cargo through it. `DSH_RC_VCVARS` can override the path.
86
+ */
87
+ function findVcvars() {
88
+ if (process.platform !== 'win32') return null;
89
+ const override = String(process.env.DSH_RC_VCVARS || '').trim();
90
+ if (override && existsSync(override)) return override;
91
+ if (process.env.VCINSTALLDIR) {
92
+ const candidate = path.join(process.env.VCINSTALLDIR, 'Auxiliary', 'Build', 'vcvars64.bat');
93
+ if (existsSync(candidate)) return candidate;
94
+ }
95
+ const vswhere = path.join(
96
+ process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)',
97
+ 'Microsoft Visual Studio',
98
+ 'Installer',
99
+ 'vswhere.exe',
100
+ );
101
+ if (!existsSync(vswhere)) return null;
102
+ try {
103
+ const found = execFileSync(
104
+ vswhere,
105
+ [
106
+ '-latest',
107
+ '-products',
108
+ '*',
109
+ '-requires',
110
+ 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
111
+ '-find',
112
+ 'VC\\Auxiliary\\Build\\vcvars64.bat',
113
+ ],
114
+ { encoding: 'utf8', timeout: 15_000 },
115
+ )
116
+ .trim()
117
+ .split(/\r?\n/)[0];
118
+ return found && existsSync(found) ? found : null;
119
+ } catch {
120
+ return null;
121
+ }
122
+ }
123
+
124
+ function quoteArg(value) {
125
+ const text = String(value);
126
+ return /\s/.test(text) ? `"${text}"` : text;
127
+ }
128
+
129
+ function runCargo(buildArgs) {
130
+ const vcvars = findVcvars();
131
+ if (vcvars) {
132
+ console.log(`> MSVC environment: ${vcvars}`);
133
+ // A temporary .cmd file avoids cmd.exe quoting problems with paths that
134
+ // contain spaces (the Visual Studio installation path usually does).
135
+ const script = path.join(root, `.build-rust-${process.pid}.cmd`);
136
+ const lines = [
137
+ '@echo off',
138
+ `call ${quoteArg(vcvars)} >nul`,
139
+ `if errorlevel 1 exit /b 1`,
140
+ [quoteArg(cargo), ...buildArgs.map(quoteArg)].join(' '),
141
+ ];
142
+ try {
143
+ writeFileSync(script, `${lines.join('\r\n')}\r\n`, 'utf8');
144
+ execFileSync(process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', script], {
145
+ cwd: root,
146
+ stdio: 'inherit',
147
+ });
148
+ } finally {
149
+ try {
150
+ unlinkSync(script);
151
+ } catch {
152
+ /* best effort */
153
+ }
154
+ }
155
+ return;
156
+ }
157
+ console.log(`> ${cargo} ${buildArgs.join(' ')}`);
158
+ execFileSync(cargo, buildArgs, { cwd: root, stdio: 'inherit' });
159
+ }
160
+
161
+ if (/^(1|true|yes|on)$/i.test(process.env.DSH_RC_SKIP_RUST_BUILD || '')) {
162
+ console.log('Skipping dsh-probe build (DSH_RC_SKIP_RUST_BUILD is set)');
163
+ process.exit(0);
164
+ }
165
+
166
+ if (!existsSync(manifest)) {
167
+ bail(`Cargo manifest not found: ${manifest}`);
168
+ }
169
+
170
+ /**
171
+ * Windows process integrity guard.
172
+ *
173
+ * Windows refuses location access to Low-integrity processes. A workspace that
174
+ * was once created by a sandboxed process can carry a `Low` mandatory label on
175
+ * the project directory; every build artifact inherits it, so `dsh-probe.exe`
176
+ * would run at Low integrity and WinRT geolocation always answers "denied"
177
+ * even when the privacy settings allow desktop apps.
178
+ *
179
+ * Raising a *file* from Low to Medium needs `SeRelabelPrivilege` (admin), but
180
+ * raising a directory to the caller's own level does not, and recreating a
181
+ * generated child directory makes it inherit the parent's Medium label. This
182
+ * repair only runs when a Low label is actually present, so normal checkouts
183
+ * keep their ACLs untouched.
184
+ */
185
+ function runIcacls(args) {
186
+ try {
187
+ execFileSync('icacls', args, { stdio: 'ignore', windowsHide: true, timeout: 20_000 });
188
+ return true;
189
+ } catch {
190
+ return false;
191
+ }
192
+ }
193
+
194
+ function hasLowLabel(target) {
195
+ try {
196
+ const output = execFileSync('icacls', [target], {
197
+ encoding: 'utf8',
198
+ windowsHide: true,
199
+ timeout: 20_000,
200
+ });
201
+ return /Low Mandatory Level/i.test(output);
202
+ } catch {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ function ensureMediumIntegrity(directory) {
208
+ if (process.platform !== 'win32') return;
209
+ const segments = path.relative(root, directory).split(path.sep).filter(Boolean);
210
+ const targets = [root, ...segments.map((_, index) => path.join(root, ...segments.slice(0, index + 1)))];
211
+ if (!targets.some((target) => existsSync(target) && hasLowLabel(target))) return;
212
+
213
+ console.log('> repairing Low integrity labels on the probe build directory');
214
+ if (hasLowLabel(root)) {
215
+ runIcacls([root, '/setintegritylevel', '(OI)(CI)Medium']);
216
+ if (hasLowLabel(root)) {
217
+ console.warn(
218
+ [
219
+ 'The workspace directory is still Low integrity after the repair attempt.',
220
+ 'Windows needs SeRelabelPrivilege to raise a directory inherited from a parent,',
221
+ 'so run the build from a normal (non-sandboxed) terminal, or follow the',
222
+ '"Windows low-integrity workspace" guide in INSTALLATION.md.',
223
+ ].join('\n'),
224
+ );
225
+ return;
226
+ }
227
+ }
228
+ let current = root;
229
+ for (const segment of segments) {
230
+ current = path.join(current, segment);
231
+ if (!existsSync(current)) {
232
+ mkdirSync(current, { recursive: true });
233
+ continue;
234
+ }
235
+ runIcacls([current, '/setintegritylevel', '(OI)(CI)Medium']);
236
+ if (!hasLowLabel(current)) continue;
237
+ // Generated directories under native/ can be recreated; the child then
238
+ // inherits the parent's Medium label instead of the stale Low one.
239
+ if (current === path.join(root, 'native') || current.startsWith(`${path.join(root, 'native')}${path.sep}`)) {
240
+ rmSync(current, { recursive: true, force: true });
241
+ mkdirSync(current, { recursive: true });
242
+ if (hasLowLabel(current)) {
243
+ console.warn(`Could not raise the integrity label of ${path.relative(root, current)}; location may be denied.`);
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+ function installBinary(sourceFile, targetFile) {
250
+ const deadline = Date.now() + 20_000;
251
+ let lastError = null;
252
+ for (;;) {
253
+ try {
254
+ if (existsSync(targetFile)) rmSync(targetFile, { force: true });
255
+ copyFileSync(sourceFile, targetFile);
256
+ return;
257
+ } catch (error) {
258
+ lastError = error;
259
+ const code = error?.code;
260
+ // Windows locks running executables; the console polls the probe every
261
+ // couple of seconds, so wait for a poll gap instead of failing the build.
262
+ if (code !== 'EBUSY' && code !== 'EPERM' && code !== 'EACCES') throw error;
263
+ if (Date.now() >= deadline) break;
264
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 200);
265
+ }
266
+ }
267
+ throw new Error(
268
+ `could not replace ${path.relative(root, targetFile)} because it is running (${lastError?.message || lastError}); stop the remote console or retry in a moment`,
269
+ );
270
+ }
271
+
272
+ const profile = debug ? 'debug' : 'release';
273
+ const cargo = process.env.CARGO || 'cargo';
274
+
275
+ if (!skipBuild) {
276
+ const buildArgs = ['build', `--${profile}`, '--manifest-path', manifest];
277
+ if (target) buildArgs.push('--target', target);
278
+ try {
279
+ runCargo(buildArgs);
280
+ } catch (error) {
281
+ bail(
282
+ [
283
+ 'Rust build failed.',
284
+ 'Install the Rust toolchain first: https://rustup.rs',
285
+ 'Windows: install "Desktop development with C++" in Visual Studio Build Tools.',
286
+ 'Linux: install gcc (or clang) and glibc development headers.',
287
+ `Reason: ${error?.message || error}`,
288
+ ].join('\n'),
289
+ error?.status || 1,
290
+ );
291
+ }
292
+ }
293
+
294
+ const targetDir = path.join(root, 'src', 'rust', 'target');
295
+ const source = target
296
+ ? path.join(targetDir, target, profile, binaryName)
297
+ : path.join(targetDir, profile, binaryName);
298
+ if (!existsSync(source)) {
299
+ bail(`Built binary not found: ${source}\nRun without --skip-build, or pass the matching --target triple.`);
300
+ }
301
+
302
+ try {
303
+ mkdirSync(outputDir, { recursive: true });
304
+ ensureMediumIntegrity(outputDir);
305
+ installBinary(source, output);
306
+ if (effective.platform !== 'win32') chmodSync(output, 0o755);
307
+ } catch (error) {
308
+ bail(`Could not install the Rust probe: ${error?.message || error}`);
309
+ }
310
+
311
+ const size = statSync(output).size;
312
+ console.log(`\nCopied ${path.relative(root, source)} -> ${path.relative(root, output)} (${(size / 1024).toFixed(0)} KiB)`);
313
+
314
+ try {
315
+ const version = execFileSync(output, ['version'], { encoding: 'utf8', timeout: 15_000 }).trim();
316
+ console.log(`Smoke check: ${version}`);
317
+ } catch (error) {
318
+ console.warn(`Warning: could not run the built probe: ${error.message}`);
319
+ }
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build the Svelte web console into `web/`.
4
+ *
5
+ * Vite is invoked programmatically rather than through `node_modules/.bin`, so
6
+ * this runs the same way from a plain checkout and from any wrapper script that
7
+ * has no bin shims on `PATH`.
8
+ */
9
+
10
+ import { build } from 'vite';
11
+
12
+ try {
13
+ await build();
14
+ } catch (error) {
15
+ console.error(error);
16
+ process.exit(1);
17
+ }