@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,95 @@
1
+ import qrcodeTerminal from 'qrcode-terminal';
2
+ import {bootstrapApi} from '../init/bootstrapApi.js';
3
+ import {logStartupConfig} from '../services/config/logConfig.js';
4
+ import {bootstrapSocket} from '../init/bootstrapSocket.js';
5
+ import {startCliServer} from '../term/srv/startCliServer.js';
6
+ import {startConfigObserver} from '../init/observers/startConfigObserver.js';
7
+ import {startNotificationObserver} from '../init/observers/startNotificationObserver.js';
8
+ import {startDisplaySizeObserver} from '../init/observers/startDisplaySizeObserver.js';
9
+ import {startQrOverlayRefreshObserver} from '../init/observers/startQrOverlayRefreshObserver.js';
10
+ import {startQrOverlayHoverObserver} from '../init/observers/startQrOverlayHoverObserver.js';
11
+ import {notifyIfRestarted} from '../remotes/admin/notifyIfRestarted.js';
12
+ import {ensureApplicationLifecycleState} from './state.js';
13
+ import {createLogger} from './logger.js';
14
+
15
+ export function createApplicationStart(services) {
16
+ function logStartupUrls(urls) {
17
+ const entries = [
18
+ ['Entry', urls.entryUrl],
19
+ ['QR', urls.qrUrl],
20
+ ['Admin config', urls.adminConfigUrl],
21
+ ['Server info', urls.serverInfoUrl],
22
+ ['Health', urls.healthUrl]
23
+ ].filter(([, value]) => Boolean(value));
24
+
25
+ console.log('URLs:');
26
+ for (const [label, value] of entries) {
27
+ console.log(` ${label}: ${value}`);
28
+ }
29
+ }
30
+
31
+ return async function start() {
32
+ const log = createLogger('server');
33
+ const state = ensureApplicationLifecycleState(services);
34
+ const config = services.getConfig();
35
+ const systemConfig = services.getSystemConfig();
36
+
37
+ const httpServer = services.getServer().server;
38
+ const qrOverlay = services.getQrOverlay();
39
+ const taskManager = services.getTaskManager();
40
+ const tokenManager = services.getTokenManager();
41
+
42
+ state.stopConfigObserver = startConfigObserver(services);
43
+ state.stopNotificationObserver = startNotificationObserver(services);
44
+ state.stopDisplaySizeObserver = startDisplaySizeObserver(services);
45
+ state.stopQrOverlayRefreshObserver = startQrOverlayRefreshObserver(services);
46
+ state.stopQrOverlayHoverObserver = startQrOverlayHoverObserver(services);
47
+ notifyIfRestarted(services);
48
+
49
+ tokenManager.createToken();
50
+
51
+ bootstrapApi(services);
52
+ bootstrapSocket(services);
53
+
54
+ process.once('SIGINT', () => {
55
+ void state.shutdown?.('SIGINT');
56
+ });
57
+ process.once('SIGTERM', () => {
58
+ void state.shutdown?.('SIGTERM');
59
+ });
60
+
61
+ await new Promise((resolve) => {
62
+ httpServer.listen(systemConfig.port, async () => {
63
+ const urls = services.getUrls();
64
+
65
+ logStartupConfig(log, {
66
+ systemConfig,
67
+ config,
68
+ });
69
+
70
+ log.info({url: urls.entryUrl, qrUrl: urls.qrUrl}, 'Remote Mouse server démarré');
71
+ logStartupUrls(urls);
72
+ log.info('Scanner ce QR avec le mobile');
73
+
74
+ if (services.getConfig().qrOverlay?.enabled) {
75
+ await qrOverlay.show();
76
+ }
77
+
78
+ await taskManager.start();
79
+
80
+ try {
81
+ state.cliServer = await startCliServer(services);
82
+ } catch (error) {
83
+ log.error({err: error}, 'Erreur au démarrage de l interface CLI locale');
84
+ }
85
+
86
+ qrcodeTerminal.generate(urls.entryUrl, {small: true});
87
+ resolve();
88
+ });
89
+ });
90
+
91
+ return {
92
+ shutdown: state.shutdown,
93
+ };
94
+ };
95
+ }
@@ -0,0 +1,19 @@
1
+ const lifecycleState = new WeakMap();
2
+
3
+ export function ensureApplicationLifecycleState(services) {
4
+ let state = lifecycleState.get(services);
5
+ if (!state) {
6
+ state = {
7
+ cliServer: null,
8
+ shuttingDown: false,
9
+ stopConfigObserver: () => {},
10
+ stopNotificationObserver: () => {},
11
+ stopDisplaySizeObserver: () => {},
12
+ stopQrOverlayRefreshObserver: () => {},
13
+ stopQrOverlayHoverObserver: () => {},
14
+ shutdown: null,
15
+ };
16
+ lifecycleState.set(services, state);
17
+ }
18
+ return state;
19
+ }
@@ -0,0 +1,65 @@
1
+ import express from 'express';
2
+ import path from 'node:path';
3
+
4
+ import {
5
+ discoverSamsungDevices,
6
+ getSamsungDeviceMac,
7
+ normalizeMac,
8
+ pickSamsungDevice
9
+ } from '../../remotes/samsung/device-config.js';
10
+
11
+ export {
12
+ buildManagedConfigPayload,
13
+ coerceConfigValue,
14
+ } from './configs.js';
15
+
16
+ export function createAdminConfigActionsRouter(services) {
17
+ const router = express.Router();
18
+
19
+ router.post('/configs/samsung/discover', async (_req, res) => {
20
+ try {
21
+ const discoverDevices = discoverSamsungDevices({
22
+ getConfig: () => services.getConfig().samsungTv,
23
+ });
24
+ const samsungConfig = services.getConfig().samsungTv;
25
+ const devices = await discoverDevices();
26
+ const selected = pickSamsungDevice(
27
+ devices,
28
+ samsungConfig.alwaysAutoResolve
29
+ ? {...samsungConfig, host: '', mac: ''}
30
+ : samsungConfig,
31
+ );
32
+
33
+ res.json({
34
+ ok: true,
35
+ devices: devices.map((device) => ({
36
+ name: String(device?.name || '').trim(),
37
+ model: String(device?.model || '').trim(),
38
+ host: String(device?.ip || '').trim(),
39
+ mac: getSamsungDeviceMac(device),
40
+ isSelected: Boolean(
41
+ selected
42
+ && String(selected.ip || '').trim() === String(device?.ip || '').trim()
43
+ && normalizeMac(getSamsungDeviceMac(selected)) === normalizeMac(getSamsungDeviceMac(device)),
44
+ ),
45
+ })),
46
+ });
47
+ } catch (error) {
48
+ res.status(500).json({
49
+ ok: false,
50
+ message: String(error?.message || error || 'Erreur de decouverte Samsung.'),
51
+ });
52
+ }
53
+ });
54
+
55
+ router.post('/restart-service', async (_req, res) => {
56
+ const result = await services.getApplicationDaemonService().restart({
57
+ cause: 'user',
58
+ source: 'admin-http',
59
+ });
60
+
61
+ res.status(result?.ok ? 200 : 500).json(result);
62
+ });
63
+
64
+ return router;
65
+ }
@@ -0,0 +1,165 @@
1
+ import express from 'express';
2
+
3
+ import {CONFIG_PATHS} from '../../services/config/configPaths.js';
4
+ import {
5
+ adminConfigDefaults,
6
+ adminConfigSchema,
7
+ buildConfigEntry,
8
+ coerceConfigValue,
9
+ getFieldDefinition,
10
+ getManagedConfigSnapshot,
11
+ } from './configs.js';
12
+
13
+ export function createAdminConfigsRouter(services) {
14
+ const getConfig = services.getConfig;
15
+ const getSystemConfig = services.getSystemConfig;
16
+ const router = express.Router();
17
+
18
+ async function getManagedContext() {
19
+ const vlcAvailable = await services.getRemotes().vlc.isAvailable();
20
+ const managedPaths = CONFIG_PATHS;
21
+ const schema = adminConfigSchema;
22
+ const defaults = getManagedConfigSnapshot({
23
+ ...adminConfigDefaults,
24
+ vlc: {
25
+ enabled: false,
26
+ },
27
+ }, managedPaths);
28
+ const config = getManagedConfigSnapshot({
29
+ ...getConfig(),
30
+ vlc: {
31
+ enabled: vlcAvailable ? getConfig()?.vlc?.enabled : false,
32
+ },
33
+ }, managedPaths);
34
+
35
+ return {
36
+ managedPaths,
37
+ schema,
38
+ defaults,
39
+ config,
40
+ };
41
+ }
42
+
43
+ router.get('/', async (_req, res) => {
44
+ const {
45
+ managedPaths,
46
+ schema,
47
+ defaults,
48
+ config,
49
+ } = await getManagedContext();
50
+
51
+ res.json({
52
+ configs: managedPaths.map((pathKey) => buildConfigEntry(pathKey, schema, config, defaults)),
53
+ defaults,
54
+ schema,
55
+ managedPaths,
56
+ systemConfig: {
57
+ adminActionsEnabled: Boolean(getSystemConfig().adminActionsEnabled),
58
+ },
59
+ });
60
+ });
61
+
62
+ router.get('/:configId', async (req, res) => {
63
+ const pathKey = String(req.params.configId || '').trim();
64
+ const {
65
+ managedPaths,
66
+ schema,
67
+ defaults,
68
+ config,
69
+ } = await getManagedContext();
70
+
71
+ if (!managedPaths.includes(pathKey)) {
72
+ res.status(404).json({
73
+ ok: false,
74
+ message: 'Invalid config path.',
75
+ });
76
+ return;
77
+ }
78
+
79
+ res.json({
80
+ config: buildConfigEntry(pathKey, schema, config, defaults),
81
+ });
82
+ });
83
+
84
+ router.patch('/:configId', express.json(), async (req, res) => {
85
+ const pathKey = String(req.params.configId || '').trim();
86
+ const {
87
+ managedPaths,
88
+ schema,
89
+ defaults,
90
+ } = await getManagedContext();
91
+
92
+ if (!managedPaths.includes(pathKey)) {
93
+ res.status(404).json({
94
+ ok: false,
95
+ message: 'Invalid config path.',
96
+ });
97
+ return;
98
+ }
99
+
100
+ const field = getFieldDefinition(schema, pathKey);
101
+ if (!field) {
102
+ res.status(404).json({
103
+ ok: false,
104
+ message: 'Unknown config field.',
105
+ });
106
+ return;
107
+ }
108
+
109
+ if (!req.body || !Object.hasOwn(req.body, 'value')) {
110
+ res.status(400).json({
111
+ ok: false,
112
+ message: 'Invalid payload: value expected.',
113
+ });
114
+ return;
115
+ }
116
+
117
+ try {
118
+ if (req.body.value === null) {
119
+ services.getConfigService().resetConfig(pathKey);
120
+ } else {
121
+ const nextValue = coerceConfigValue(req.body.value, field);
122
+ services.getConfigService().setConfig(pathKey, nextValue);
123
+ }
124
+
125
+ const nextContext = await getManagedContext();
126
+ res.json({
127
+ ok: true,
128
+ message: 'Configuration updated.',
129
+ config: buildConfigEntry(pathKey, nextContext.schema, nextContext.config, nextContext.defaults),
130
+ });
131
+ } catch (error) {
132
+ res.status(400).json({
133
+ ok: false,
134
+ message: `Configuration invalide: ${error.message}`,
135
+ });
136
+ }
137
+ });
138
+
139
+ router.delete('/:configId', async (req, res) => {
140
+ const pathKey = String(req.params.configId || '').trim();
141
+ const {
142
+ managedPaths,
143
+ schema,
144
+ defaults,
145
+ } = await getManagedContext();
146
+
147
+ if (!managedPaths.includes(pathKey)) {
148
+ res.status(404).json({
149
+ ok: false,
150
+ message: 'Invalid config path.',
151
+ });
152
+ return;
153
+ }
154
+
155
+ services.getConfigService().resetConfig(pathKey);
156
+ const nextContext = await getManagedContext();
157
+ res.json({
158
+ ok: true,
159
+ message: `${pathKey} reset to default.`,
160
+ config: buildConfigEntry(pathKey, schema, nextContext.config, defaults),
161
+ });
162
+ });
163
+
164
+ return router;
165
+ }
@@ -0,0 +1,61 @@
1
+ import express from 'express';
2
+
3
+ export function createAdminRemotesRouter(services) {
4
+ const router = express.Router();
5
+
6
+ function isBrowserEnabled(config, browserId) {
7
+ return config?.browser?.enabled !== false && config?.browser?.[browserId] !== false;
8
+ }
9
+
10
+ router.get('/browsers', async (_req, res) => {
11
+ const config = services.getConfig();
12
+ const browsers = await services.getSystem().listBrowsers();
13
+ res.json({
14
+ browsers: browsers.map((browser) => ({
15
+ ...browser,
16
+ enabled: isBrowserEnabled(config, browser.id),
17
+ })),
18
+ });
19
+ });
20
+
21
+ router.get('/', async (_req, res) => {
22
+ const config = services.getConfig();
23
+ const vlcAvailable = await services.getSystem().isVlcAvailable();
24
+ const remotes = [
25
+ {
26
+ id: 'browser',
27
+ labelKey: 'preferences.remote.browser',
28
+ enabled: config?.browser?.enabled !== false,
29
+ },
30
+ {
31
+ id: 'keyboard',
32
+ labelKey: 'preferences.remote.keyboard',
33
+ enabled: config?.keyboard?.enabled !== false,
34
+ },
35
+ {
36
+ id: 'preview',
37
+ labelKey: 'preferences.remote.preview',
38
+ enabled: config?.preview?.enabled !== false,
39
+ },
40
+ {
41
+ id: 'samsung',
42
+ labelKey: 'preferences.remote.samsung',
43
+ enabled: Boolean(config?.samsungTv?.enabled),
44
+ },
45
+ ];
46
+
47
+ if (vlcAvailable) {
48
+ remotes.splice(2, 0, {
49
+ id: 'vlc',
50
+ labelKey: 'preferences.remote.vlc',
51
+ enabled: config?.vlc?.enabled !== false,
52
+ });
53
+ }
54
+
55
+ res.json({
56
+ remotes,
57
+ });
58
+ });
59
+
60
+ return router;
61
+ }
@@ -0,0 +1,49 @@
1
+ import express from 'express';
2
+ import {PUBSUB_SERVICE_CONFIG} from '../../services/pubsub/serviceEventConstants.js';
3
+
4
+ export function createAdminSubsRouter(services) {
5
+ const router = express.Router();
6
+
7
+ router.post('/configs', express.json(), (_req, res) => {
8
+ const id = services.getSseService().createSubscription({
9
+ filters: {
10
+ service: PUBSUB_SERVICE_CONFIG,
11
+ },
12
+ });
13
+
14
+ res.json({
15
+ ok: true,
16
+ id,
17
+ eventsUrl: `/api/admin/subs/${id}`,
18
+ });
19
+ });
20
+
21
+ router.get('/:id', (req, res) => {
22
+ const connected = services.getSseService().connect(String(req.params.id || '').trim(), req, res);
23
+ if (connected) {
24
+ return;
25
+ }
26
+
27
+ res.status(404).json({
28
+ ok: false,
29
+ message: 'Subscription not found.',
30
+ });
31
+ });
32
+
33
+ router.delete('/:id', (req, res) => {
34
+ const removed = services.getSseService().deleteSubscription(String(req.params.id || '').trim());
35
+ if (!removed) {
36
+ res.status(404).json({
37
+ ok: false,
38
+ message: 'Subscription not found.',
39
+ });
40
+ return;
41
+ }
42
+
43
+ res.json({
44
+ ok: true,
45
+ });
46
+ });
47
+
48
+ return router;
49
+ }
@@ -0,0 +1,15 @@
1
+ import express from 'express';
2
+
3
+ export function createStaticShareRouter({
4
+ publicDir,
5
+ clientDir,
6
+ sharedUtilsDir,
7
+ }) {
8
+ const router = express.Router();
9
+
10
+ router.use(express.static(publicDir));
11
+ router.use('/client', express.static(clientDir));
12
+ router.use('/utils', express.static(sharedUtilsDir));
13
+ return router;
14
+ }
15
+
@@ -0,0 +1,96 @@
1
+ import {CONFIG_PATHS} from '../../services/config/configPaths.js';
2
+ import {getConfigFieldDefinition, getManagedConfigSchema} from '../../services/config/configSchema.js';
3
+ import {DEFAULT_PERSISTED_CONFIG} from '../../services/config/defaultConfig.js';
4
+ import {setNestedValue} from '../../../utils/object.utils.js';
5
+
6
+ export const adminConfigSchema = getManagedConfigSchema(CONFIG_PATHS);
7
+
8
+ export function getValueAtPath(source, dottedPath) {
9
+ return String(dottedPath || '')
10
+ .split('.')
11
+ .filter(Boolean)
12
+ .reduce((cursor, segment) => (cursor == null ? undefined : cursor[segment]), source);
13
+ }
14
+
15
+ export function coerceConfigValue(rawValue, field) {
16
+ if (!field) {
17
+ return rawValue;
18
+ }
19
+
20
+ if (field.type === 'boolean') {
21
+ if (typeof rawValue === 'string') {
22
+ const normalized = rawValue.trim().toLowerCase();
23
+ if (normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on') {
24
+ return true;
25
+ }
26
+ if (normalized === 'false' || normalized === '0' || normalized === 'no' || normalized === 'off') {
27
+ return false;
28
+ }
29
+ throw new Error('must be a boolean');
30
+ }
31
+ return Boolean(rawValue);
32
+ }
33
+
34
+ if (field.type === 'integer') {
35
+ const parsed = Number.parseInt(String(rawValue), 10);
36
+ if (!Number.isFinite(parsed)) {
37
+ throw new Error('must be an integer');
38
+ }
39
+ return parsed;
40
+ }
41
+
42
+ if (field.type === 'number') {
43
+ const parsed = Number.parseFloat(String(rawValue));
44
+ if (!Number.isFinite(parsed)) {
45
+ throw new Error('must be a number');
46
+ }
47
+ return parsed;
48
+ }
49
+
50
+ const value = String(rawValue ?? '').trim();
51
+ if (Array.isArray(field.options) && field.options.length > 0 && !field.options.includes(value)) {
52
+ throw new Error(`must be one of: ${field.options.join(', ')}`);
53
+ }
54
+
55
+ return value;
56
+ }
57
+
58
+ export function buildManagedConfigPayload(rawValues, schema = adminConfigSchema) {
59
+ const payload = {};
60
+
61
+ for (const [pathKey, rawValue] of Object.entries(rawValues || {})) {
62
+ const field = getFieldDefinition(schema, pathKey);
63
+ if (!field) {
64
+ continue;
65
+ }
66
+ const coercedValue = coerceConfigValue(rawValue, field);
67
+ setNestedValue(payload, pathKey, coercedValue);
68
+ }
69
+
70
+ return payload;
71
+ }
72
+
73
+ export function getManagedConfigSnapshot(config, managedPaths = CONFIG_PATHS) {
74
+ const snapshot = {};
75
+
76
+ for (const pathKey of managedPaths) {
77
+ setNestedValue(snapshot, pathKey, getValueAtPath(config, pathKey));
78
+ }
79
+ return snapshot;
80
+ }
81
+
82
+ export function getFieldDefinition(schema, pathKey) {
83
+ const [sectionKey, fieldKey] = String(pathKey || '').split('.');
84
+ return schema?.[sectionKey]?.fields?.[fieldKey] || getConfigFieldDefinition(pathKey);
85
+ }
86
+
87
+ export function buildConfigEntry(pathKey, schema, config, defaults) {
88
+ return {
89
+ id: pathKey,
90
+ field: getFieldDefinition(schema, pathKey),
91
+ value: getValueAtPath(config, pathKey),
92
+ defaultValue: getValueAtPath(defaults, pathKey),
93
+ };
94
+ }
95
+
96
+ export const adminConfigDefaults = getManagedConfigSnapshot(DEFAULT_PERSISTED_CONFIG, CONFIG_PATHS);
@@ -0,0 +1,17 @@
1
+ import QRCode from "qrcode";
2
+ import {renderQrPage} from "../../services/overlay/renderQrPage.js";
3
+
4
+ export function createQrPageHandler(services) {
5
+ return async (_req, res) => {
6
+ try {
7
+ const publicUrl = String(services.getUrls().entryUrl || '');
8
+ const qrDataUrl = await QRCode.toDataURL(publicUrl);
9
+ res.type('html').send(renderQrPage({
10
+ qrDataUrl,
11
+ publicUrl,
12
+ }));
13
+ } catch (_error) {
14
+ res.status(500).type('text/plain').send('QR generation failed');
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,30 @@
1
+ import express from 'express';
2
+
3
+ export function createRemotesRouter(services) {
4
+ const router = express.Router();
5
+
6
+ router.get('/:remoteId/status', async (req, res) => {
7
+ const remoteId = String(req.params.remoteId || '').trim();
8
+
9
+ if (remoteId === 'samsung') {
10
+ const enabled = Boolean(services.getConfig()?.samsungTv?.enabled);
11
+ const power = enabled
12
+ ? await services.getRemotes().samsung.getPowerState({ maxAgeMs: 2500 })
13
+ : 'disabled';
14
+
15
+ res.json({
16
+ remoteId,
17
+ enabled,
18
+ power,
19
+ });
20
+ return;
21
+ }
22
+
23
+ res.status(404).json({
24
+ ok: false,
25
+ message: 'Unknown remote.',
26
+ });
27
+ });
28
+
29
+ return router;
30
+ }