@velor/remote-mouse 6.4.8

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 (316) hide show
  1. package/.artifacts/screenshots/remote-mobile-config.png +0 -0
  2. package/.artifacts/screenshots/remote-mobile-home.png +0 -0
  3. package/.artifacts/screenshots/remote-mobile-preferences.png +0 -0
  4. package/.artifacts/screenshots/remote-mobile-server-info.png +0 -0
  5. package/.artifacts/screenshots/remote-mobile-vlc.png +0 -0
  6. package/.env.example +93 -0
  7. package/README.md +370 -0
  8. package/bin/remote-mouse.js +19 -0
  9. package/client/core/dom.js +148 -0
  10. package/client/core/init-socket-io.js +117 -0
  11. package/client/core/socket-emit.js +6 -0
  12. package/client/core/window-events.js +23 -0
  13. package/client/i18n/apply-page-translations.js +18 -0
  14. package/client/i18n/constants.js +3 -0
  15. package/client/i18n/core.js +40 -0
  16. package/client/i18n/locale-registry.js +77 -0
  17. package/client/i18n/locales/de.js +227 -0
  18. package/client/i18n/locales/en.js +389 -0
  19. package/client/i18n/locales/es.js +228 -0
  20. package/client/i18n/locales/fr.js +389 -0
  21. package/client/i18n/locales/it.js +227 -0
  22. package/client/i18n/locales/ja.js +227 -0
  23. package/client/i18n/locales/pt.js +227 -0
  24. package/client/i18n/locales/ru.js +240 -0
  25. package/client/i18n/locales/zh.js +227 -0
  26. package/client/preferences/constants.js +15 -0
  27. package/client/preferences/effects.js +24 -0
  28. package/client/preferences/load.js +19 -0
  29. package/client/preferences/render.js +26 -0
  30. package/client/preferences/rows.js +78 -0
  31. package/client/preferences/state.js +29 -0
  32. package/client/preview/create-preview-frame-receiver.js +13 -0
  33. package/client/preview/draw.js +77 -0
  34. package/client/preview/parse-preview-frame.js +39 -0
  35. package/client/preview/preview-stream.js +152 -0
  36. package/client/services/app-state/appStateKeys.js +30 -0
  37. package/client/services/app-state/createAppStateService.js +216 -0
  38. package/client/services/app-state/createPersistStoreService.js +122 -0
  39. package/client/services/app-state/createStateStoreService.js +64 -0
  40. package/client/services/app-state/localStorageBinding.js +26 -0
  41. package/client/services/app-state/normalizers.js +74 -0
  42. package/client/services/app-state/resolveEffectiveStateValue.js +58 -0
  43. package/client/services/app-state/stateDefinitions.js +107 -0
  44. package/client/services/backend/createBackendService.js +55 -0
  45. package/client/services/config/ConfigView.js +45 -0
  46. package/client/services/config/createClientConfigService.js +122 -0
  47. package/client/services/config/defaultClientConfig.js +22 -0
  48. package/client/services/createServicesContainer.js +48 -0
  49. package/client/services/createServicesRegistry.js +26 -0
  50. package/client/services/i18n/createI18nService.js +86 -0
  51. package/client/services/notifications/createNotificationService.js +56 -0
  52. package/client/services/pubsub/createPubSubService.js +20 -0
  53. package/client/services/remotes/createRemotesService.js +20 -0
  54. package/client/services/transport/createSocketIoTransportService.js +50 -0
  55. package/client/touch/bindTouchPassthrough.js +94 -0
  56. package/client/touch/createTouchList.js +18 -0
  57. package/client/touch/dispatchSyntheticTouch.js +20 -0
  58. package/client/touch/gesture-zone.js +28 -0
  59. package/client/touch/throttle.js +46 -0
  60. package/client/touch/touch-handlers.js +193 -0
  61. package/client/touch/touchpad.js +231 -0
  62. package/client/ui/config/page.js +840 -0
  63. package/client/ui/main/applyRemoteVisibilityState.js +60 -0
  64. package/client/ui/main/bind-client-notifications.js +3 -0
  65. package/client/ui/main/bindings/bindAccordion.js +121 -0
  66. package/client/ui/main/bindings/bindActionButtons.js +13 -0
  67. package/client/ui/main/bindings/bindAdminDrawer.js +137 -0
  68. package/client/ui/main/bindings/bindAdminRemoteButtons.js +77 -0
  69. package/client/ui/main/bindings/bindAdminVersion.js +27 -0
  70. package/client/ui/main/bindings/bindBrowserRemoteButtons.js +119 -0
  71. package/client/ui/main/bindings/bindRemoteAccordion.js +23 -0
  72. package/client/ui/main/bindings/bindSamsungRemoteButtons.js +320 -0
  73. package/client/ui/main/bindings/bindSystemRemoteButtons.js +41 -0
  74. package/client/ui/main/bindings/bindVlcRemoteButtons.js +64 -0
  75. package/client/ui/main/canvas-ui.js +33 -0
  76. package/client/ui/main/connection-overlay.js +57 -0
  77. package/client/ui/main/init-ui.js +54 -0
  78. package/client/ui/main/keyboard-panel.js +271 -0
  79. package/client/ui/main/mouse-buttons.js +94 -0
  80. package/client/ui/main/page.js +21 -0
  81. package/client/ui/notifications/show-toast.js +48 -0
  82. package/client/ui/preferences/bindPreferenceSwitchers.js +49 -0
  83. package/client/ui/preferences/page.js +61 -0
  84. package/client/ui/preferences/switchers.js +200 -0
  85. package/index.js +9 -0
  86. package/package.json +41 -0
  87. package/public/admin-config.css +447 -0
  88. package/public/admin-config.html +63 -0
  89. package/public/apple-touch-icon.png +0 -0
  90. package/public/brave-icon.svg +13 -0
  91. package/public/favicon.svg +30 -0
  92. package/public/icon-192.png +0 -0
  93. package/public/icon-512.png +0 -0
  94. package/public/index.html +246 -0
  95. package/public/manifest.webmanifest +45 -0
  96. package/public/preferences.html +55 -0
  97. package/public/server-info.html +574 -0
  98. package/public/styles.css +1042 -0
  99. package/public/sw.js +103 -0
  100. package/scripts/codex-commit.sh +112 -0
  101. package/scripts/generate-mobile-screenshots.mjs +244 -0
  102. package/scripts/install-linux.sh +633 -0
  103. package/scripts/install-windows.ps1 +369 -0
  104. package/server/application/createApplicationLifecycle.js +15 -0
  105. package/server/application/logger.js +216 -0
  106. package/server/application/shutdown.js +81 -0
  107. package/server/application/start.js +95 -0
  108. package/server/application/state.js +19 -0
  109. package/server/connection/api/admin-actions.router.js +65 -0
  110. package/server/connection/api/admin-configs.router.js +165 -0
  111. package/server/connection/api/admin-remotes.router.js +61 -0
  112. package/server/connection/api/admin-subs.router.js +49 -0
  113. package/server/connection/api/client.router.js +15 -0
  114. package/server/connection/api/configs.js +96 -0
  115. package/server/connection/api/qr-page.handler.js +17 -0
  116. package/server/connection/api/remotes.router.js +30 -0
  117. package/server/connection/api/server-info.router.js +149 -0
  118. package/server/connection/api/session.middleware.js +93 -0
  119. package/server/connection/api/unauthorized-response.js +73 -0
  120. package/server/connection/socket/createConnectionRegistrar.js +23 -0
  121. package/server/connection/socket/createSocketSessionAuthMiddleware.js +49 -0
  122. package/server/connection/socket/socket-action-responder.js +12 -0
  123. package/server/connection/socket/socket.timestamp-middleware.js +51 -0
  124. package/server/index.js +12 -0
  125. package/server/init/bootstrapApi.js +87 -0
  126. package/server/init/bootstrapSocket.js +79 -0
  127. package/server/init/createAdminApiRouter.js +22 -0
  128. package/server/init/createAdminUiRouter.js +21 -0
  129. package/server/init/createSocketActionRegistrars.js +52 -0
  130. package/server/init/observers/startConfigObserver.js +51 -0
  131. package/server/init/observers/startDisplaySizeObserver.js +55 -0
  132. package/server/init/observers/startNotificationObserver.js +49 -0
  133. package/server/init/observers/startQrOverlayHoverObserver.js +89 -0
  134. package/server/init/observers/startQrOverlayRefreshObserver.js +53 -0
  135. package/server/os/darwin/app.js +45 -0
  136. package/server/os/darwin/applescript.js +51 -0
  137. package/server/os/darwin/cliSocket.js +53 -0
  138. package/server/os/darwin/url.js +9 -0
  139. package/server/os/darwin/window.js +10 -0
  140. package/server/os/linux/app.js +120 -0
  141. package/server/os/linux/cliSocket.js +53 -0
  142. package/server/os/linux/process.js +69 -0
  143. package/server/os/linux/screen.js +58 -0
  144. package/server/os/linux/systemd.js +139 -0
  145. package/server/os/linux/url.js +17 -0
  146. package/server/os/linux/windows.js +144 -0
  147. package/server/os/win32/app.js +66 -0
  148. package/server/os/win32/cliSocket.js +15 -0
  149. package/server/os/win32/powershell.js +70 -0
  150. package/server/os/win32/process.js +20 -0
  151. package/server/os/win32/service.js +95 -0
  152. package/server/os/win32/url.js +9 -0
  153. package/server/os/win32/window.js +10 -0
  154. package/server/remotes/admin/createAdminEventGuardMiddleware.js +29 -0
  155. package/server/remotes/admin/createForceUpdateCheckAction.js +39 -0
  156. package/server/remotes/admin/createInstallUpdateAction.js +64 -0
  157. package/server/remotes/admin/createOpenQrBrowserAction.js +63 -0
  158. package/server/remotes/admin/createOpenServerInfoBrowserAction.js +58 -0
  159. package/server/remotes/admin/createRestartServiceAction.js +20 -0
  160. package/server/remotes/admin/createRotateEntryTokenAction.js +43 -0
  161. package/server/remotes/admin/createToggleQrOverlayAction.js +38 -0
  162. package/server/remotes/admin/index.js +32 -0
  163. package/server/remotes/admin/notifyIfRestarted.js +102 -0
  164. package/server/remotes/admin/registrar.js +94 -0
  165. package/server/remotes/browser/actions/createFocusOrLaunchBrowserAction.js +22 -0
  166. package/server/remotes/browser/actions/openUrlOnHost.js +3 -0
  167. package/server/remotes/browser/browserCatalog.js +70 -0
  168. package/server/remotes/browser/index.js +15 -0
  169. package/server/remotes/browser/listBrowsersOnHost.js +23 -0
  170. package/server/remotes/browser/registrar.js +29 -0
  171. package/server/remotes/browser/spec.js +18 -0
  172. package/server/remotes/browser/state.js +5 -0
  173. package/server/remotes/input/registrar.js +39 -0
  174. package/server/remotes/preview/bgraToRgbaBuffer.js +20 -0
  175. package/server/remotes/preview/captureAroundCursor.js +19 -0
  176. package/server/remotes/preview/createPreviewStreamer.js +85 -0
  177. package/server/remotes/preview/registrar.js +34 -0
  178. package/server/remotes/samsung/createSamsungCommandService.js +203 -0
  179. package/server/remotes/samsung/createSamsungRemote.js +26 -0
  180. package/server/remotes/samsung/createSamsungRemoteGetter.js +46 -0
  181. package/server/remotes/samsung/createSamsungTvGetter.js +102 -0
  182. package/server/remotes/samsung/device-config.js +122 -0
  183. package/server/remotes/samsung/registrar.js +59 -0
  184. package/server/remotes/samsung/utils.js +56 -0
  185. package/server/remotes/vlc/index.js +39 -0
  186. package/server/remotes/vlc/registrar.js +94 -0
  187. package/server/remotes/vlc/spec.js +15 -0
  188. package/server/remotes/vlc/state.js +5 -0
  189. package/server/remotes/window/index.js +6 -0
  190. package/server/remotes/window/registrar.js +28 -0
  191. package/server/services/application/createApplicationDaemonService.js +144 -0
  192. package/server/services/application/getDaemonServiceAdapter.js +56 -0
  193. package/server/services/application/utils.js +29 -0
  194. package/server/services/config/bootstrapConfig.js +38 -0
  195. package/server/services/config/configPaths.js +42 -0
  196. package/server/services/config/configSchema.js +297 -0
  197. package/server/services/config/configService.js +89 -0
  198. package/server/services/config/defaultConfig.js +137 -0
  199. package/server/services/config/envConfig.js +49 -0
  200. package/server/services/config/index.js +9 -0
  201. package/server/services/config/logConfig.js +54 -0
  202. package/server/services/config/system-config.js +44 -0
  203. package/server/services/createServicesContainer.js +94 -0
  204. package/server/services/createServicesRegistry.js +48 -0
  205. package/server/services/input/createInputController.js +17 -0
  206. package/server/services/input/createKeyboardController.js +146 -0
  207. package/server/services/input/createMouseController.js +182 -0
  208. package/server/services/notifier/createClientNotifier.js +23 -0
  209. package/server/services/notifier/createHostNotifier.js +41 -0
  210. package/server/services/notifier/createNotifier.js +13 -0
  211. package/server/services/notifier/createNotifierComposite.js +122 -0
  212. package/server/services/notifier/handleOpenQrBrowserEvent.js +40 -0
  213. package/server/services/notifier/handleOpenServerInfoBrowserEvent.js +40 -0
  214. package/server/services/notifier/handleRestartServiceEvent.js +37 -0
  215. package/server/services/notifier/handleRotateEntryTokenEvent.js +42 -0
  216. package/server/services/notifier/handleSessionEvent.js +24 -0
  217. package/server/services/notifier/handleToggleQrOverlayEvent.js +21 -0
  218. package/server/services/notifier/host-notifier/createLinuxHostNotifier.js +23 -0
  219. package/server/services/notifier/host-notifier/createNodeNotifierHostNotifier.js +24 -0
  220. package/server/services/notifier/host-notifier/index.js +11 -0
  221. package/server/services/notifier/mapper/handleForceUpdateCheckEvent.js +24 -0
  222. package/server/services/notifier/mapper/handleInstallUpdateEvent.js +53 -0
  223. package/server/services/notifier/mapper/handleSocketEvent.js +40 -0
  224. package/server/services/notifier/mapper/handleUpdateManagerEvent.js +24 -0
  225. package/server/services/notifier/mapper/notify.js +7 -0
  226. package/server/services/os/index.js +23 -0
  227. package/server/services/os/platforms/createFallbackAdapter.js +31 -0
  228. package/server/services/os/platforms/darwin/app.js +6 -0
  229. package/server/services/os/platforms/darwin/index.js +21 -0
  230. package/server/services/os/platforms/darwin/scripts.js +4 -0
  231. package/server/services/os/platforms/darwin/url.js +1 -0
  232. package/server/services/os/platforms/darwin/window.js +4 -0
  233. package/server/services/os/platforms/linux/app.js +6 -0
  234. package/server/services/os/platforms/linux/index.js +33 -0
  235. package/server/services/os/platforms/linux/url.js +1 -0
  236. package/server/services/os/platforms/linux/windows.js +11 -0
  237. package/server/services/os/platforms/win32/app.js +6 -0
  238. package/server/services/os/platforms/win32/index.js +21 -0
  239. package/server/services/os/platforms/win32/overlay.js +6 -0
  240. package/server/services/os/platforms/win32/powershell.js +4 -0
  241. package/server/services/os/platforms/win32/url.js +1 -0
  242. package/server/services/os/platforms/win32/window.js +4 -0
  243. package/server/services/os/shared.js +2 -0
  244. package/server/services/overlay/createNoopOverlay.js +13 -0
  245. package/server/services/overlay/createQrOverlay.js +27 -0
  246. package/server/services/overlay/createQrOverlayWin32.js +158 -0
  247. package/server/services/overlay/createQrOverlayYad.js +178 -0
  248. package/server/services/overlay/renderQrPage.js +82 -0
  249. package/server/services/persistence/createConfigDao.js +106 -0
  250. package/server/services/persistence/createDatabaseProvider.js +23 -0
  251. package/server/services/persistence/createEntryTokenDao.js +140 -0
  252. package/server/services/persistence/createRestartLogDao.js +210 -0
  253. package/server/services/persistence/index.js +19 -0
  254. package/server/services/pubsub/createEventStore.js +54 -0
  255. package/server/services/pubsub/createPubSub.js +89 -0
  256. package/server/services/pubsub/createServiceEvents.js +29 -0
  257. package/server/services/pubsub/serviceEventConstants.js +39 -0
  258. package/server/services/remotes/createRemotes.js +25 -0
  259. package/server/services/server/createHttpsServer.js +12 -0
  260. package/server/services/server/createServer.js +66 -0
  261. package/server/services/sse/createSseService.js +96 -0
  262. package/server/services/sse/utils.js +7 -0
  263. package/server/services/system/createSystemService.js +170 -0
  264. package/server/services/system/getNetworkInfo.js +18 -0
  265. package/server/services/system/getScreenInfo.js +32 -0
  266. package/server/services/system/listNetworkInterfaces.js +27 -0
  267. package/server/services/task-manager/createTaskManager.js +68 -0
  268. package/server/services/task-runner/createTaskRunner.js +114 -0
  269. package/server/services/token-manager/createTokenManager.js +244 -0
  270. package/server/services/token-manager/token-format.js +7 -0
  271. package/server/services/token-manager/token-store-utils.js +8 -0
  272. package/server/services/update-manager/CommandUpdateSource.js +70 -0
  273. package/server/services/update-manager/NpmUpdateSource.js +34 -0
  274. package/server/services/update-manager/buildNpmGlobalUpdateCommand.js +15 -0
  275. package/server/services/update-manager/chooseUpdateCheckSource.js +20 -0
  276. package/server/services/update-manager/chooseUpdateInstallSource.js +5 -0
  277. package/server/services/update-manager/createUpdateManager.js +109 -0
  278. package/server/services/update-manager/resolveInstallUpdateCommand.js +42 -0
  279. package/server/term/cli/executeLocalServiceCommand.js +42 -0
  280. package/server/term/cli/getCliSocketPath.js +5 -0
  281. package/server/term/cli/parseCliArgs.js +110 -0
  282. package/server/term/cli/printCliResult.js +18 -0
  283. package/server/term/cli/runCliCmd.js +50 -0
  284. package/server/term/cli/sendCliCommand.js +76 -0
  285. package/server/term/cliSocket.js +29 -0
  286. package/server/term/srv/commands/configCommand.js +84 -0
  287. package/server/term/srv/commands/helpCommand.js +6 -0
  288. package/server/term/srv/commands/infoCommand.js +7 -0
  289. package/server/term/srv/commands/openQrCommand.js +7 -0
  290. package/server/term/srv/commands/samsungDetectCommand.js +52 -0
  291. package/server/term/srv/commands/serviceCommand.js +25 -0
  292. package/server/term/srv/commands/systemConfigCommand.js +7 -0
  293. package/server/term/srv/commands/tasksCommand.js +24 -0
  294. package/server/term/srv/commands/tokensCommand.js +15 -0
  295. package/server/term/srv/executeCliCommand.js +44 -0
  296. package/server/term/srv/executeCliRequest.js +38 -0
  297. package/server/term/srv/startCliServer.js +140 -0
  298. package/server/utils/createRandomToken.js +11 -0
  299. package/server/utils/env.js +155 -0
  300. package/server/utils/git.js +13 -0
  301. package/server/utils/http.js +7 -0
  302. package/server/utils/network.js +45 -0
  303. package/server/utils/paths.js +10 -0
  304. package/server/utils/process.js +57 -0
  305. package/server/utils/robot.js +11 -0
  306. package/server/utils/semver.js +33 -0
  307. package/server/utils/truncateText.js +7 -0
  308. package/utils/createLazy.js +13 -0
  309. package/utils/functional.js +48 -0
  310. package/utils/math.js +26 -0
  311. package/utils/notificationSettings.js +61 -0
  312. package/utils/object.utils.js +79 -0
  313. package/utils/predicates.js +17 -0
  314. package/utils/remoteCommands.js +40 -0
  315. package/utils/sync.js +3 -0
  316. package/velor-remote-mouse-6.4.8.tgz +0 -0
@@ -0,0 +1,574 @@
1
+ <!doctype html>
2
+ <html data-i18n-page-title="serverInfo.pageTitle">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Remote Mouse - Server Info</title>
7
+ <style>
8
+ :root {
9
+ color-scheme: dark;
10
+ --bg: #0f1419;
11
+ --panel: #1a242d;
12
+ --text: #e9f1f8;
13
+ --muted: #9ab0c4;
14
+ --line: rgba(255,255,255,.12);
15
+ --accent: #5fd3ff;
16
+ }
17
+ html[data-theme="light"] {
18
+ color-scheme: light;
19
+ --bg: #eef4f8;
20
+ --panel: #ffffff;
21
+ --text: #17303a;
22
+ --muted: #607b8a;
23
+ --line: rgba(23, 48, 58, .12);
24
+ --accent: #0a87b8;
25
+ }
26
+ * { box-sizing: border-box; }
27
+ body {
28
+ margin: 0;
29
+ font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
30
+ background: radial-gradient(circle at 10% 0, #1b2a35, var(--bg));
31
+ color: var(--text);
32
+ }
33
+ main { max-width: 1200px; margin: 0 auto; padding: 18px; display: grid; gap: 12px; }
34
+ h1 { margin: 0; font-size: 1.05rem; }
35
+ .meta { color: var(--muted); font-size: .9rem; display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
36
+ section {
37
+ border: 1px solid var(--line);
38
+ background: var(--panel);
39
+ border-radius: 12px;
40
+ padding: 12px;
41
+ }
42
+ h2 { margin: 0 0 10px; font-size: .95rem; color: var(--accent); }
43
+ .table-wrap { overflow-x: auto; }
44
+ table { width: 100%; border-collapse: collapse; font-size: .88rem; min-width: 540px; }
45
+ th, td { text-align: left; border-bottom: 1px solid var(--line); padding: 6px; }
46
+ pre {
47
+ margin: 0;
48
+ font-size: .8rem;
49
+ line-height: 1.35;
50
+ white-space: pre-wrap;
51
+ word-break: break-word;
52
+ max-height: 360px;
53
+ overflow: auto;
54
+ }
55
+ #logs { max-height: 440px; }
56
+ @media (max-width: 720px) {
57
+ main { padding: 12px; }
58
+ section { padding: 10px; }
59
+ h1 { font-size: 1rem; }
60
+ table { font-size: .82rem; }
61
+ pre { font-size: .76rem; max-height: 320px; }
62
+ }
63
+ </style>
64
+ </head>
65
+ <body>
66
+ <main>
67
+ <h1 data-i18n="serverInfo.heading">Remote Mouse - Server Info</h1>
68
+ <div class="meta">
69
+ <span id="version">Version: -</span>
70
+ <span id="now">Now: -</span>
71
+ <span id="online-since">Online since: -</span>
72
+ <span id="uptime">Uptime: -</span>
73
+ <span id="clients-count">Clients: 0</span>
74
+ <span id="daemon-state">Daemon: -</span>
75
+ <span id="admin-actions-state">Admin actions: -</span>
76
+ </div>
77
+
78
+ <section id="admin-actions-note" hidden>
79
+ <p id="admin-actions-note-text" style="margin:0; color: var(--muted);" data-i18n="serverInfo.adminActions.localConfigOnly">When admin actions are disabled, the Configuration page remains available for local browser preferences.</p>
80
+ </section>
81
+
82
+ <section>
83
+ <h2 data-i18n="serverInfo.section.clients">Clients connectes</h2>
84
+ <div class="table-wrap">
85
+ <table>
86
+ <thead>
87
+ <tr>
88
+ <th data-i18n="serverInfo.table.client.id">ID</th>
89
+ <th data-i18n="serverInfo.table.client.connectedAt">Connecte depuis</th>
90
+ <th data-i18n="serverInfo.table.client.address">Adresse</th>
91
+ <th data-i18n="serverInfo.table.client.transport">Transport</th>
92
+ </tr>
93
+ </thead>
94
+ <tbody id="clients-table"></tbody>
95
+ </table>
96
+ </div>
97
+ </section>
98
+
99
+ <section>
100
+ <h2 data-i18n="serverInfo.section.tasks">Taches planifiees</h2>
101
+ <div class="table-wrap">
102
+ <table>
103
+ <thead>
104
+ <tr>
105
+ <th data-i18n="serverInfo.table.task.name">Nom</th>
106
+ <th data-i18n="serverInfo.table.task.state">Etat</th>
107
+ <th data-i18n="serverInfo.table.task.dueAt">Echeance</th>
108
+ <th data-i18n="serverInfo.table.task.remaining">Dans</th>
109
+ </tr>
110
+ </thead>
111
+ <tbody id="tasks-table"></tbody>
112
+ </table>
113
+ </div>
114
+ </section>
115
+
116
+ <section>
117
+ <h2 data-i18n="serverInfo.section.tokens">Tokens</h2>
118
+ <div class="table-wrap">
119
+ <table>
120
+ <thead>
121
+ <tr>
122
+ <th data-i18n="serverInfo.table.token.state">Etat</th>
123
+ <th data-i18n="serverInfo.table.token.token">Token</th>
124
+ <th data-i18n="serverInfo.table.token.createdAt">Cree le</th>
125
+ <th data-i18n="serverInfo.table.token.expiresAt">Expire le</th>
126
+ </tr>
127
+ </thead>
128
+ <tbody id="tokens-table"></tbody>
129
+ </table>
130
+ </div>
131
+ </section>
132
+
133
+ <section>
134
+ <h2 data-i18n="serverInfo.section.lifecycle">Recent lifecycle events</h2>
135
+ <div class="table-wrap">
136
+ <table>
137
+ <thead>
138
+ <tr>
139
+ <th data-i18n="serverInfo.table.lifecycle.id">ID</th>
140
+ <th data-i18n="serverInfo.table.lifecycle.event">Event</th>
141
+ <th data-i18n="serverInfo.table.lifecycle.requestedAt">Requested</th>
142
+ <th data-i18n="serverInfo.table.lifecycle.detectedAt">Detected</th>
143
+ <th data-i18n="serverInfo.table.lifecycle.status">Status</th>
144
+ <th data-i18n="serverInfo.table.lifecycle.cause">Cause</th>
145
+ <th data-i18n="serverInfo.table.lifecycle.source">Source</th>
146
+ </tr>
147
+ </thead>
148
+ <tbody id="restarts-table"></tbody>
149
+ </table>
150
+ </div>
151
+ </section>
152
+
153
+ <section>
154
+ <h2 data-i18n="serverInfo.section.capabilities">Capabilities</h2>
155
+ <pre id="capabilities"></pre>
156
+ </section>
157
+
158
+ <section>
159
+ <h2 data-i18n="serverInfo.section.config">Configuration</h2>
160
+ <pre id="config"></pre>
161
+ </section>
162
+
163
+ <section>
164
+ <h2 data-i18n="serverInfo.section.sysConfig">Configuration systeme</h2>
165
+ <pre id="sys-config"></pre>
166
+ </section>
167
+
168
+ <section>
169
+ <h2 data-i18n="serverInfo.section.logs">Logs recents</h2>
170
+ <pre id="logs"></pre>
171
+ </section>
172
+ </main>
173
+
174
+ <script type="module">
175
+ import {createServicesRegistry} from '/client/services/createServicesRegistry.js';
176
+ import {initializeCoreServices} from '/client/services/createServicesContainer.js';
177
+
178
+ const services = createServicesRegistry();
179
+ await initializeCoreServices(services);
180
+ const i18n = services.getI18n();
181
+ i18n.translateRoot(document);
182
+
183
+ const versionEl = document.getElementById('version');
184
+ const nowEl = document.getElementById('now');
185
+ const onlineSinceEl = document.getElementById('online-since');
186
+ const uptimeEl = document.getElementById('uptime');
187
+ const clientsCountEl = document.getElementById('clients-count');
188
+ const daemonStateEl = document.getElementById('daemon-state');
189
+ const adminActionsStateEl = document.getElementById('admin-actions-state');
190
+ const adminActionsNoteEl = document.getElementById('admin-actions-note');
191
+ const clientsTable = document.getElementById('clients-table');
192
+ const tasksTable = document.getElementById('tasks-table');
193
+ const tokensTable = document.getElementById('tokens-table');
194
+ const restartsTable = document.getElementById('restarts-table');
195
+ const capabilitiesEl = document.getElementById('capabilities');
196
+ const configEl = document.getElementById('config');
197
+ const sysConfigEl = document.getElementById('sys-config');
198
+ const logsEl = document.getElementById('logs');
199
+ const LOG_BOTTOM_THRESHOLD_PX = 8;
200
+ const dateTimeFormatter = new Intl.DateTimeFormat(undefined, {
201
+ dateStyle: 'medium',
202
+ timeStyle: 'medium',
203
+ });
204
+ let logsAutoScroll = true;
205
+ let configStream = null;
206
+ let configSubscriptionId = '';
207
+ let pendingConfigPayload = null;
208
+ let applyingConfigPayload = false;
209
+
210
+ function t(key, params) {
211
+ return i18n.t(key, params);
212
+ }
213
+
214
+ function translateOr(key, fallback = '') {
215
+ const value = t(key);
216
+ return value === key ? fallback : value;
217
+ }
218
+
219
+ function isLogScrollAtBottom() {
220
+ return logsEl.scrollTop + logsEl.clientHeight >= logsEl.scrollHeight - LOG_BOTTOM_THRESHOLD_PX;
221
+ }
222
+
223
+ function formatDuration(totalSec) {
224
+ const s = Math.max(0, Number(totalSec) || 0);
225
+ const h = Math.floor(s / 3600);
226
+ const m = Math.floor((s % 3600) / 60);
227
+ const sec = s % 60;
228
+ return [
229
+ t('serverInfo.duration.hours', {value: h}),
230
+ t('serverInfo.duration.minutes', {value: m}),
231
+ t('serverInfo.duration.seconds', {value: sec}),
232
+ ].join(' ');
233
+ }
234
+
235
+ function formatDateTime(value) {
236
+ if (!value) {
237
+ return '-';
238
+ }
239
+
240
+ const date = new Date(value);
241
+ if (!Number.isFinite(date.getTime())) {
242
+ return '-';
243
+ }
244
+
245
+ return dateTimeFormatter.format(date);
246
+ }
247
+
248
+ function renderClients(clients) {
249
+ clientsTable.innerHTML = '';
250
+ if (!Array.isArray(clients) || clients.length === 0) {
251
+ const row = document.createElement('tr');
252
+ row.innerHTML = `<td colspan="4">${t('serverInfo.empty.clients')}</td>`;
253
+ clientsTable.appendChild(row);
254
+ return;
255
+ }
256
+
257
+ for (const client of clients) {
258
+ const row = document.createElement('tr');
259
+ row.innerHTML = `
260
+ <td>${client.id || ''}</td>
261
+ <td>${formatDateTime(client.connectedAt)}</td>
262
+ <td>${client.address || '-'}</td>
263
+ <td>${client.transport || '-'}</td>
264
+ `;
265
+ clientsTable.appendChild(row);
266
+ }
267
+ }
268
+
269
+ function formatRemaining(dueAt) {
270
+ if (!dueAt) {
271
+ return '-';
272
+ }
273
+
274
+ const diffMs = new Date(dueAt).getTime() - Date.now();
275
+ if (!Number.isFinite(diffMs)) {
276
+ return '-';
277
+ }
278
+
279
+ if (diffMs <= 0) {
280
+ return t('serverInfo.nowMoment');
281
+ }
282
+
283
+ return formatDuration(Math.ceil(diffMs / 1000));
284
+ }
285
+
286
+ function renderTasks(tasks) {
287
+ tasksTable.innerHTML = '';
288
+ if (!Array.isArray(tasks) || tasks.length === 0) {
289
+ const row = document.createElement('tr');
290
+ row.innerHTML = `<td colspan="4">${t('serverInfo.empty.tasks')}</td>`;
291
+ tasksTable.appendChild(row);
292
+ return;
293
+ }
294
+
295
+ for (const task of tasks) {
296
+ const row = document.createElement('tr');
297
+ row.innerHTML = `
298
+ <td>${task.name || task.id || ''}</td>
299
+ <td>${task.running ? t('serverInfo.task.running') : task.dueAt ? t('serverInfo.task.scheduled') : t('serverInfo.task.waiting')}</td>
300
+ <td>${formatDateTime(task.dueAt)}</td>
301
+ <td>${formatRemaining(task.dueAt)}</td>
302
+ `;
303
+ tasksTable.appendChild(row);
304
+ }
305
+ }
306
+
307
+ function renderTokens(tokens) {
308
+ tokensTable.innerHTML = '';
309
+ if (!Array.isArray(tokens) || tokens.length === 0) {
310
+ const row = document.createElement('tr');
311
+ row.innerHTML = `<td colspan="4">${t('serverInfo.empty.tokens')}</td>`;
312
+ tokensTable.appendChild(row);
313
+ return;
314
+ }
315
+
316
+ for (const tokenEntry of tokens) {
317
+ const row = document.createElement('tr');
318
+ row.innerHTML = `
319
+ <td>${tokenEntry.isCurrent ? t('serverInfo.token.active') : t('serverInfo.token.archived')}</td>
320
+ <td>${tokenEntry.token || t('serverInfo.token.masked')}</td>
321
+ <td>${formatDateTime(tokenEntry.createdAt)}</td>
322
+ <td>${formatDateTime(tokenEntry.expiresAt)}</td>
323
+ `;
324
+ tokensTable.appendChild(row);
325
+ }
326
+ }
327
+
328
+ function renderRestarts(restarts) {
329
+ restartsTable.innerHTML = '';
330
+ if (!Array.isArray(restarts) || restarts.length === 0) {
331
+ const row = document.createElement('tr');
332
+ row.innerHTML = `<td colspan="7">${t('serverInfo.empty.lifecycle')}</td>`;
333
+ restartsTable.appendChild(row);
334
+ return;
335
+ }
336
+
337
+ for (const restart of restarts) {
338
+ const row = document.createElement('tr');
339
+ row.innerHTML = `
340
+ <td>${restart.id ?? ''}</td>
341
+ <td>${restart.eventType || '-'}</td>
342
+ <td>${formatDateTime(restart.requestedAt)}</td>
343
+ <td>${formatDateTime(restart.detectedAt)}</td>
344
+ <td>${restart.status || '-'}</td>
345
+ <td>${restart.cause || '-'}</td>
346
+ <td>${restart.source || '-'}</td>
347
+ `;
348
+ restartsTable.appendChild(row);
349
+ }
350
+ }
351
+
352
+ function renderLogs(logs) {
353
+ const previousScrollTop = logsEl.scrollTop;
354
+ const shouldAutoScroll = logsAutoScroll;
355
+
356
+ if (!Array.isArray(logs) || logs.length === 0) {
357
+ logsEl.textContent = t('serverInfo.empty.logs');
358
+ if (shouldAutoScroll) {
359
+ logsEl.scrollTop = logsEl.scrollHeight;
360
+ } else {
361
+ logsEl.scrollTop = previousScrollTop;
362
+ }
363
+ return;
364
+ }
365
+ logsEl.textContent = logs.map((entry) => {
366
+ const prefix = `[${entry.at}] [${entry.level}] [${entry.scope}]`;
367
+ const msg = entry.message || '';
368
+ const data = entry.data ? ` ${JSON.stringify(entry.data)}` : '';
369
+ return `${prefix} ${msg}${data}`;
370
+ }).join('\n');
371
+ if (shouldAutoScroll) {
372
+ logsEl.scrollTop = logsEl.scrollHeight;
373
+ } else {
374
+ logsEl.scrollTop = previousScrollTop;
375
+ }
376
+ }
377
+
378
+ function renderCapabilities(system) {
379
+ if (!system || typeof system !== 'object') {
380
+ capabilitiesEl.textContent = t('serverInfo.empty.capabilities');
381
+ return;
382
+ }
383
+
384
+ const applications = Array.isArray(system.applications) && system.applications.length > 0
385
+ ? system.applications
386
+ .map((application) => {
387
+ const status = application.available
388
+ ? translateOr('serverInfo.capabilities.available', 'available')
389
+ : translateOr('serverInfo.capabilities.unavailable', 'unavailable');
390
+ const details = [application.command, application.app].filter(Boolean).join(' / ');
391
+ return `- ${application.name || application.id || '-'} [${status}]${details ? ` (${details})` : ''}`;
392
+ })
393
+ .join('\n')
394
+ : t('serverInfo.capabilities.none');
395
+ const applicationNameById = new Map(
396
+ (Array.isArray(system.applications) ? system.applications : [])
397
+ .map((application) => [application.id, application.name || application.id]),
398
+ );
399
+ const formatRemote = (remote) => {
400
+ const label = translateOr(remote.labelKey, remote.id || '-');
401
+ const status = remote.enabled
402
+ ? translateOr('serverInfo.capabilities.enabled', 'enabled')
403
+ : translateOr('serverInfo.capabilities.disabled', 'disabled');
404
+ const inactiveReasons = Array.isArray(remote.inactiveReasons) && remote.inactiveReasons.length > 0
405
+ ? `: ${remote.inactiveReasons.map((reason) => translateOr(`serverInfo.capabilities.reason.${reason}`, reason)).join(', ')}`
406
+ : '';
407
+ const applications = Array.isArray(remote.applicationIds) && remote.applicationIds.length > 0
408
+ ? ` -> ${remote.applicationIds.map((id) => applicationNameById.get(id) || id).join(', ')}`
409
+ : '';
410
+ return `- ${label} [${status}]${applications}${inactiveReasons}`;
411
+ };
412
+ const remotes = Array.isArray(system.remotes) && system.remotes.length > 0
413
+ ? system.remotes.map(formatRemote).join('\n')
414
+ : t('serverInfo.capabilities.none');
415
+ const allRemotes = Array.isArray(system.allRemotes) && system.allRemotes.length > 0
416
+ ? system.allRemotes.map(formatRemote).join('\n')
417
+ : t('serverInfo.capabilities.none');
418
+ const screen = system.screen && Number.isFinite(system.screen.width) && Number.isFinite(system.screen.height)
419
+ ? `${system.screen.width}x${system.screen.height}`
420
+ : t('serverInfo.capabilities.unavailable');
421
+ const interfaces = Array.isArray(system.network?.interfaces) && system.network.interfaces.length > 0
422
+ ? system.network.interfaces
423
+ .map((entry) => `${entry.name} ${entry.family} ${entry.address}${entry.internal ? ' [internal]' : ''}`)
424
+ .join('\n')
425
+ : t('serverInfo.capabilities.none');
426
+
427
+ capabilitiesEl.textContent = [
428
+ `${t('serverInfo.capabilities.platform')}: ${system.platform || '-'}`,
429
+ `${t('serverInfo.capabilities.hostname')}: ${system.hostname || system.network?.hostname || '-'}`,
430
+ `${t('serverInfo.capabilities.screen')}: ${screen}`,
431
+ `${translateOr('serverInfo.capabilities.applications', 'Applications')}:\n${applications}`,
432
+ `${translateOr('serverInfo.capabilities.remotes', 'Remotes')}:\n${remotes}`,
433
+ `${translateOr('serverInfo.capabilities.allRemotes', 'All remotes')}:\n${allRemotes}`,
434
+ `${t('serverInfo.capabilities.lanIp')}: ${system.network?.lanIp || '-'}`,
435
+ `${t('serverInfo.capabilities.publicUrl')}: ${system.network?.publicBaseUrl || '-'}`,
436
+ `${t('serverInfo.capabilities.localUrl')}: ${system.network?.localBaseUrl || '-'}`,
437
+ `${t('serverInfo.capabilities.interfaces')}:\n${interfaces}`,
438
+ ].join('\n');
439
+ }
440
+
441
+ function renderConfigSnapshot(snapshot) {
442
+ configEl.textContent = JSON.stringify(snapshot || {}, null, 2);
443
+ }
444
+
445
+ function renderSystemConfigSnapshot(snapshot) {
446
+ sysConfigEl.textContent = JSON.stringify(snapshot || {}, null, 2);
447
+ }
448
+
449
+ function flushPendingConfigPayload() {
450
+ if (applyingConfigPayload || !pendingConfigPayload) {
451
+ return;
452
+ }
453
+
454
+ applyingConfigPayload = true;
455
+ const payload = pendingConfigPayload;
456
+ pendingConfigPayload = null;
457
+
458
+ try {
459
+ renderConfigSnapshot(payload.config);
460
+ renderSystemConfigSnapshot(payload.sysConfig);
461
+ } finally {
462
+ applyingConfigPayload = false;
463
+ if (pendingConfigPayload) {
464
+ flushPendingConfigPayload();
465
+ }
466
+ }
467
+ }
468
+
469
+ function scheduleConfigPayload(payload) {
470
+ pendingConfigPayload = payload;
471
+ queueMicrotask(() => {
472
+ flushPendingConfigPayload();
473
+ });
474
+ }
475
+
476
+ async function refresh() {
477
+ try {
478
+ const response = await fetch('/api/admin/server-info/data', { cache: 'no-store' });
479
+ if (!response.ok) {
480
+ throw new Error(`HTTP ${response.status}`);
481
+ }
482
+ const data = await response.json();
483
+ versionEl.textContent = t('serverInfo.version', {value: String(data.version || t('common.unknown'))});
484
+ nowEl.textContent = t('serverInfo.now', {value: formatDateTime(data.now)});
485
+ onlineSinceEl.textContent = t('serverInfo.onlineSince', {value: formatDateTime(data.onlineSince)});
486
+ uptimeEl.textContent = t('serverInfo.uptime', {value: formatDuration(data.uptimeSec)});
487
+ clientsCountEl.textContent = t('serverInfo.clientsCount', {value: Number(data.clientsConnected) || 0});
488
+ daemonStateEl.textContent = t('serverInfo.daemon', {
489
+ value: t(data.daemon?.runningAsDaemon ? 'serverInfo.daemon.yes' : 'serverInfo.daemon.no'),
490
+ suffix: data.daemon?.installed ? ` ${t('serverInfo.daemon.installed')}` : '',
491
+ });
492
+ const adminActionsEnabled = Boolean(data?.sysConfig?.adminActionsEnabled);
493
+ adminActionsStateEl.textContent = t('serverInfo.adminActions', {
494
+ value: t(adminActionsEnabled ? 'serverInfo.adminActions.enabled' : 'serverInfo.adminActions.disabled'),
495
+ });
496
+ adminActionsNoteEl.hidden = adminActionsEnabled;
497
+ renderClients(data.clients || []);
498
+ renderTasks(data.tasks || []);
499
+ renderTokens(data.tokens || []);
500
+ renderRestarts(data.restarts || []);
501
+ renderCapabilities(data.system || null);
502
+ scheduleConfigPayload({
503
+ config: data.config,
504
+ sysConfig: data.sysConfig,
505
+ });
506
+ renderLogs(data.logs || []);
507
+ } catch (error) {
508
+ logsEl.textContent = t('serverInfo.loadError', {message: error?.message || error});
509
+ }
510
+ }
511
+
512
+ async function subscribeToConfigEvents() {
513
+ if (typeof window.EventSource !== 'function') {
514
+ return;
515
+ }
516
+
517
+ const response = await fetch('/api/admin/subs/configs', {
518
+ method: 'POST',
519
+ headers: {
520
+ 'Content-Type': 'application/json',
521
+ },
522
+ body: JSON.stringify({scope: 'config'}),
523
+ });
524
+ if (!response.ok) {
525
+ throw new Error(t('serverInfo.sseCreateError'));
526
+ }
527
+
528
+ const payload = await response.json();
529
+ configSubscriptionId = String(payload.id || '');
530
+ if (!configSubscriptionId || !payload.eventsUrl) {
531
+ throw new Error(t('serverInfo.sseInvalid'));
532
+ }
533
+
534
+ configStream?.close();
535
+ configStream = new EventSource(payload.eventsUrl);
536
+ configStream.addEventListener('config.changed', (event) => {
537
+ try {
538
+ scheduleConfigPayload(JSON.parse(event.data || '{}'));
539
+ } catch (_error) {
540
+ // Best effort.
541
+ }
542
+ });
543
+ }
544
+
545
+ function unsubscribeFromConfigEvents() {
546
+ if (!configSubscriptionId) {
547
+ return;
548
+ }
549
+
550
+ fetch(`/api/admin/subs/${encodeURIComponent(configSubscriptionId)}`, {
551
+ method: 'DELETE',
552
+ keepalive: true,
553
+ }).catch(() => {});
554
+ configSubscriptionId = '';
555
+ }
556
+
557
+ logsEl.addEventListener('scroll', () => {
558
+ logsAutoScroll = isLogScrollAtBottom();
559
+ }, { passive: true });
560
+
561
+ refresh();
562
+ setInterval(refresh, 2000);
563
+ subscribeToConfigEvents().catch(() => {});
564
+ i18n.onChange(() => {
565
+ i18n.translateRoot(document);
566
+ refresh();
567
+ });
568
+ window.addEventListener('beforeunload', () => {
569
+ configStream?.close();
570
+ unsubscribeFromConfigEvents();
571
+ });
572
+ </script>
573
+ </body>
574
+ </html>