@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,170 @@
1
+ import os from 'node:os';
2
+ import {getScreenInfo} from "./getScreenInfo.js";
3
+ import {getNetworkInfo} from "./getNetworkInfo.js";
4
+ import {createLogger} from '../../application/logger.js';
5
+ import {BROWSER_CATALOG} from '../../remotes/browser/browserCatalog.js';
6
+
7
+ let log;
8
+ function getModuleLog() {
9
+ log ??= createLogger('system');
10
+ return log;
11
+ }
12
+
13
+ function getConfigSection(config, key) {
14
+ return config?.[key] && typeof config[key] === 'object' ? config[key] : {};
15
+ }
16
+
17
+ function isConfigEnabled(config, key) {
18
+ return getConfigSection(config, key).enabled !== false;
19
+ }
20
+
21
+ function buildApplications({browsers, vlcAvailable}) {
22
+ const installedBrowsers = new Map(
23
+ browsers.map((browser) => [browser.id, browser]),
24
+ );
25
+ const browserApplications = BROWSER_CATALOG.map((browser) => {
26
+ const installedBrowser = installedBrowsers.get(browser.id);
27
+ return {
28
+ id: `browser:${browser.id}`,
29
+ applicationId: browser.id,
30
+ name: browser.name,
31
+ shortLabel: browser.shortLabel,
32
+ kind: 'browser',
33
+ available: Boolean(installedBrowser),
34
+ command: installedBrowser?.command || '',
35
+ app: installedBrowser?.app || '',
36
+ remotes: ['browser'],
37
+ };
38
+ });
39
+
40
+ return [
41
+ ...browserApplications,
42
+ {
43
+ id: 'vlc',
44
+ applicationId: 'vlc',
45
+ name: 'VLC media player',
46
+ shortLabel: 'VLC',
47
+ kind: 'media-player',
48
+ available: Boolean(vlcAvailable),
49
+ remotes: ['vlc'],
50
+ },
51
+ ];
52
+ }
53
+
54
+ function buildRemoteCapabilities({applications, config}) {
55
+ const availableBrowserApplicationIds = applications
56
+ .filter((application) => application.kind === 'browser' && application.available)
57
+ .map((application) => application.id);
58
+ const hasBrowserApplication = availableBrowserApplicationIds.length > 0;
59
+ const isVlcAvailable = applications.some(
60
+ (application) => application.applicationId === 'vlc' && application.available,
61
+ );
62
+ const remoteVisibility = [
63
+ {
64
+ id: 'browser',
65
+ labelKey: 'preferences.remote.browser',
66
+ applicationIds: availableBrowserApplicationIds,
67
+ available: hasBrowserApplication,
68
+ enabled: isConfigEnabled(config, 'browser'),
69
+ },
70
+ {
71
+ id: 'keyboard',
72
+ labelKey: 'preferences.remote.keyboard',
73
+ applicationIds: [],
74
+ available: true,
75
+ enabled: isConfigEnabled(config, 'keyboard'),
76
+ },
77
+ {
78
+ id: 'vlc',
79
+ labelKey: 'preferences.remote.vlc',
80
+ applicationIds: isVlcAvailable ? ['vlc'] : [],
81
+ available: isVlcAvailable,
82
+ enabled: isConfigEnabled(config, 'vlc'),
83
+ },
84
+ {
85
+ id: 'preview',
86
+ labelKey: 'preferences.remote.preview',
87
+ applicationIds: [],
88
+ available: true,
89
+ enabled: isConfigEnabled(config, 'preview'),
90
+ },
91
+ {
92
+ id: 'samsung',
93
+ labelKey: 'preferences.remote.samsung',
94
+ applicationIds: [],
95
+ available: true,
96
+ enabled: Boolean(getConfigSection(config, 'samsungTv').enabled),
97
+ },
98
+ ];
99
+
100
+ return remoteVisibility.map((remote) => ({
101
+ ...remote,
102
+ inactiveReasons: [
103
+ remote.available ? '' : 'application-unavailable',
104
+ remote.enabled ? '' : 'config-disabled',
105
+ ].filter(Boolean),
106
+ }));
107
+ }
108
+
109
+ export function createSystemService(services) {
110
+ const log = getModuleLog();
111
+ return {
112
+ listBrowsers() {
113
+ log.debug('Detection des navigateurs disponibles');
114
+ return services.getRemotes().browser.listBrowsers();
115
+ },
116
+ isVlcAvailable() {
117
+ log.debug('Detection disponibilite VLC');
118
+ return services.getRemotes().vlc.isAvailable();
119
+ },
120
+ async getScreenInfo() {
121
+ const screen = await getScreenInfo(services);
122
+ log.debug({screen}, 'Detection resolution ecran');
123
+ return screen;
124
+ },
125
+ getNetworkInfo() {
126
+ const network = getNetworkInfo(services);
127
+ log.debug({
128
+ lanIp: network.lanIp,
129
+ publicBaseUrl: network.publicBaseUrl,
130
+ interfaceCount: network.interfaces.length,
131
+ }, 'Detection reseau');
132
+ return network;
133
+ },
134
+ async getInfo() {
135
+ log.debug('Collecte des capacites serveur');
136
+ const browsers = await this.listBrowsers();
137
+ const vlcAvailable = await this.isVlcAvailable();
138
+ const applications = buildApplications({browsers, vlcAvailable});
139
+ const allRemotes = buildRemoteCapabilities({
140
+ applications,
141
+ config: services.getConfig(),
142
+ });
143
+ const screen = await this.getScreenInfo();
144
+ const network = this.getNetworkInfo();
145
+
146
+ log.debug({
147
+ browserCount: browsers.length,
148
+ vlcAvailable,
149
+ applicationCount: applications.filter((application) => application.available).length,
150
+ remoteCount: allRemotes.filter((remote) => remote.available).length,
151
+ screen,
152
+ lanIp: network.lanIp,
153
+ }, 'Capacites serveur collectees');
154
+
155
+ return {
156
+ platform: services.getOs().platform,
157
+ hostname: os.hostname(),
158
+ browsers,
159
+ vlc: {
160
+ available: vlcAvailable,
161
+ },
162
+ applications,
163
+ remotes: allRemotes.filter((remote) => remote.available),
164
+ allRemotes,
165
+ screen,
166
+ network,
167
+ };
168
+ },
169
+ };
170
+ }
@@ -0,0 +1,18 @@
1
+ import os from "node:os";
2
+ import {getLanIp} from "../../utils/network.js";
3
+ import {listNetworkInterfaces} from "./listNetworkInterfaces.js";
4
+
5
+ export function getNetworkInfo(services) {
6
+ const systemConfig = services.getSystemConfig();
7
+ const urls = services.getUrls();
8
+
9
+ return {
10
+ hostname: os.hostname(),
11
+ protocol: String(systemConfig?.protocol || 'http'),
12
+ port: Number.isFinite(Number(systemConfig?.port)) ? Number(systemConfig.port) : null,
13
+ lanIp: getLanIp(systemConfig?.host || ''),
14
+ publicBaseUrl: urls.publicBaseUrl,
15
+ localBaseUrl: urls.localBaseUrl,
16
+ interfaces: listNetworkInterfaces(),
17
+ };
18
+ }
@@ -0,0 +1,32 @@
1
+ import {resolveLinuxScreenSize} from '../../os/linux/screen.js';
2
+
3
+ function normalizeScreenInfo(screen) {
4
+ const width = Number(screen?.width);
5
+ const height = Number(screen?.height);
6
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
7
+ return null;
8
+ }
9
+
10
+ return {
11
+ width: Math.round(width),
12
+ height: Math.round(height),
13
+ };
14
+ }
15
+
16
+ export async function getScreenInfo(services) {
17
+ try {
18
+ if (services.getOs?.().platform === 'linux') {
19
+ const linuxScreen = await resolveLinuxScreenSize();
20
+ if (linuxScreen) {
21
+ return linuxScreen;
22
+ }
23
+ }
24
+ } catch (_error) {}
25
+
26
+ try {
27
+ const screen = services.getRobot().getScreenSize();
28
+ return normalizeScreenInfo(screen);
29
+ } catch (_error) {
30
+ return null;
31
+ }
32
+ }
@@ -0,0 +1,27 @@
1
+ import os from "node:os";
2
+
3
+ export function listNetworkInterfaces() {
4
+ let interfaces = {};
5
+ try {
6
+ interfaces = os.networkInterfaces();
7
+ } catch (_error) {
8
+ interfaces = {};
9
+ }
10
+ const entries = [];
11
+
12
+ for (const [name, addresses] of Object.entries(interfaces)) {
13
+ for (const address of addresses || []) {
14
+ entries.push({
15
+ name,
16
+ family: String(address.family || ''),
17
+ address: String(address.address || ''),
18
+ internal: Boolean(address.internal),
19
+ mac: String(address.mac || ''),
20
+ netmask: String(address.netmask || ''),
21
+ cidr: String(address.cidr || ''),
22
+ });
23
+ }
24
+ }
25
+
26
+ return entries;
27
+ }
@@ -0,0 +1,68 @@
1
+ import {PUBSUB_SERVICE_TASK_MANAGER} from "../pubsub/serviceEventConstants.js";
2
+
3
+ function getFixedDelayMs(valueInMinutes) {
4
+ return Math.max(60_000, Number(valueInMinutes || 0) * 60_000);
5
+ }
6
+
7
+ export function createTaskManager(services) {
8
+ let started = false;
9
+
10
+ function getTaskRunner() {
11
+ return services.getTaskRunner();
12
+ }
13
+
14
+ function publishState() {
15
+ services.getEvents().publishState(PUBSUB_SERVICE_TASK_MANAGER, {
16
+ tasks: getTaskRunner().getTasksSnapshot(),
17
+ });
18
+ }
19
+
20
+ function wrapTask(task) {
21
+ return async () => {
22
+ try {
23
+ await task();
24
+ } finally {
25
+ publishState();
26
+ }
27
+ };
28
+ }
29
+
30
+ async function start() {
31
+ if (started) {
32
+ return;
33
+ }
34
+
35
+ started = true;
36
+ await services.getUpdateManager().check();
37
+
38
+ getTaskRunner().run(
39
+ wrapTask(() => services.getUpdateManager().check()),
40
+ () => getFixedDelayMs(services.getSystemConfig().updateCheck?.intervalMin || 1),
41
+ {name: 'update-check'},
42
+ );
43
+
44
+ getTaskRunner().run(
45
+ wrapTask(() => services.getTokenManager().rotateIfNeeded()),
46
+ () => getFixedDelayMs(services.getSystemConfig().entryPath?.rotateMin || 0),
47
+ {name: 'token-rotation'},
48
+ );
49
+
50
+ publishState();
51
+ }
52
+
53
+ function stop() {
54
+ started = false;
55
+ getTaskRunner().stopAll();
56
+ publishState();
57
+ }
58
+
59
+ function getTasksSnapshot() {
60
+ return getTaskRunner().getTasksSnapshot();
61
+ }
62
+
63
+ return {
64
+ start,
65
+ stop,
66
+ getTasksSnapshot,
67
+ };
68
+ }
@@ -0,0 +1,114 @@
1
+ export function createTaskRunner() {
2
+ const stops = new Set();
3
+ const tasks = new Set();
4
+ let nextTaskId = 1;
5
+
6
+ function normalizeDelay(delay) {
7
+ const value = Number(delay);
8
+ if (!Number.isFinite(value)) {
9
+ return null;
10
+ }
11
+
12
+ return Math.max(0, Math.floor(value));
13
+ }
14
+
15
+ function run(task, delayOrProvider, options = {}) {
16
+ let timer = null;
17
+ let stopped = false;
18
+ const taskState = {
19
+ id: `task-${nextTaskId++}`,
20
+ name: typeof options.name === 'string' && options.name.trim() ? options.name.trim() : 'unnamed-task',
21
+ dueAt: null,
22
+ delayMs: null,
23
+ running: false,
24
+ };
25
+
26
+ tasks.add(taskState);
27
+
28
+ function getDelayMs() {
29
+ const rawDelay = typeof delayOrProvider === 'function'
30
+ ? delayOrProvider()
31
+ : delayOrProvider;
32
+ return normalizeDelay(rawDelay);
33
+ }
34
+
35
+ async function loop() {
36
+ if (stopped) {
37
+ return;
38
+ }
39
+
40
+ taskState.running = true;
41
+ taskState.dueAt = null;
42
+
43
+ try {
44
+ await task();
45
+ } finally {
46
+ taskState.running = false;
47
+ schedule();
48
+ }
49
+ }
50
+
51
+ function schedule() {
52
+ if (stopped) {
53
+ return;
54
+ }
55
+
56
+ const delayMs = getDelayMs();
57
+ taskState.delayMs = delayMs;
58
+
59
+ if (delayMs === null) {
60
+ taskState.dueAt = null;
61
+ return;
62
+ }
63
+
64
+ taskState.dueAt = new Date(Date.now() + delayMs).toISOString();
65
+ timer = setTimeout(() => {
66
+ timer = null;
67
+ void loop();
68
+ }, delayMs);
69
+ }
70
+
71
+ function stop() {
72
+ if (stopped) {
73
+ return;
74
+ }
75
+
76
+ stopped = true;
77
+ if (timer) {
78
+ clearTimeout(timer);
79
+ timer = null;
80
+ }
81
+ taskState.dueAt = null;
82
+ taskState.running = false;
83
+ tasks.delete(taskState);
84
+ stops.delete(stop);
85
+ }
86
+
87
+ stops.add(stop);
88
+ schedule();
89
+
90
+ return stop;
91
+ }
92
+
93
+ function stopAll() {
94
+ for (const stop of Array.from(stops)) {
95
+ stop();
96
+ }
97
+ }
98
+
99
+ function getTasksSnapshot() {
100
+ return Array.from(tasks, (task) => ({
101
+ id: task.id,
102
+ name: task.name,
103
+ dueAt: task.dueAt,
104
+ delayMs: task.delayMs,
105
+ running: task.running,
106
+ }));
107
+ }
108
+
109
+ return {
110
+ run,
111
+ stopAll,
112
+ getTasksSnapshot,
113
+ };
114
+ }
@@ -0,0 +1,244 @@
1
+ import {createRandomToken} from '../../utils/createRandomToken.js';
2
+ import {isTokenFormatValid, normalizeToken} from './token-format.js';
3
+ import {computeTokenTtlMs} from './token-store-utils.js';
4
+ import {
5
+ PUBSUB_EVENT_STATE_CHANGED,
6
+ PUBSUB_EVENT_TOKEN_CHANGED,
7
+ PUBSUB_SERVICE_TOKEN_MANAGER
8
+ } from "../pubsub/serviceEventConstants.js";
9
+ import {createLogger} from '../../application/logger.js';
10
+
11
+ let log;
12
+ function getModuleLog() {
13
+ log ??= createLogger('token-manager');
14
+ return log;
15
+ }
16
+
17
+ function createTokenPersistence(services) {
18
+ return {
19
+ countTokens: () => services.getPersistence().entryTokenDao.countEntryTokens(),
20
+ deleteExpiredTokens: (options) => services.getPersistence().entryTokenDao.deleteExpiredEntryTokens(options),
21
+ getLatestToken: () => services.getPersistence().entryTokenDao.getLatestEntryToken(),
22
+ getLatestTokenRecord: () => services.getPersistence().entryTokenDao.getLatestEntryTokenRecord?.(),
23
+ hasToken: (token) => services.getPersistence().entryTokenDao.hasEntryToken(token),
24
+ createToken: (token, createdAt) => services.getPersistence().entryTokenDao.createEntryToken(token, createdAt),
25
+ };
26
+ }
27
+
28
+ export function createTokenManager(services) {
29
+ const log = getModuleLog();
30
+ const persistence = createTokenPersistence(services);
31
+
32
+ function publishState(type = PUBSUB_EVENT_STATE_CHANGED) {
33
+ const latestToken = getLatestTokenRecord();
34
+ const nextRotationDelayMs = !isPersistenceEnabled()
35
+ ? null
36
+ : !latestToken
37
+ ? 0
38
+ : Math.max(0, latestToken.createdAt + getRotateTtlMs() - Date.now());
39
+
40
+ log.trace({
41
+ type,
42
+ enabled: isEffectivelyEnabled(),
43
+ gateEnabled: isGateEnabled(),
44
+ persistenceEnabled: isPersistenceEnabled(),
45
+ hasCurrentToken: Boolean(getCurrentToken()),
46
+ tokenCount: loadTokens(),
47
+ nextRotationDelayMs,
48
+ }, 'Publication etat token manager');
49
+
50
+ services.getEvents().publishState(PUBSUB_SERVICE_TOKEN_MANAGER, {
51
+ enabled: isEffectivelyEnabled(),
52
+ gateEnabled: isGateEnabled(),
53
+ persistenceEnabled: isPersistenceEnabled(),
54
+ token: getCurrentToken() || '',
55
+ tokenCount: loadTokens(),
56
+ nextRotationDelayMs,
57
+ }, {type});
58
+ }
59
+
60
+ function getEntryPathConfig() {
61
+ return services.getSystemConfig().entryPath;
62
+ }
63
+
64
+ function getNormalizedFixedPath() {
65
+ return normalizeToken(getEntryPathConfig().fixed);
66
+ }
67
+
68
+ function isEffectivelyEnabled() {
69
+ return Boolean(getEntryPathConfig().enabled);
70
+ }
71
+
72
+ function isGateEnabled() {
73
+ return isEffectivelyEnabled() || Boolean(getNormalizedFixedPath());
74
+ }
75
+
76
+ function isPersistenceEnabled() {
77
+ return isEffectivelyEnabled() && !getNormalizedFixedPath();
78
+ }
79
+
80
+ function readCurrentToken() {
81
+ const normalizedFixedPath = getNormalizedFixedPath();
82
+ if (normalizedFixedPath) {
83
+ return normalizedFixedPath;
84
+ }
85
+ if (!isPersistenceEnabled()) {
86
+ return '';
87
+ }
88
+ const token = normalizeToken(persistence.getLatestToken?.());
89
+ return isTokenFormatValid(token) ? token : '';
90
+ }
91
+
92
+ function getCurrentToken() {
93
+ return readCurrentToken();
94
+ }
95
+
96
+ function getRotateTtlMs() {
97
+ return Math.max(60_000, Number(getEntryPathConfig().rotateMin || 0) * 60_000);
98
+ }
99
+
100
+ function getLatestTokenRecord() {
101
+ const record = persistence.getLatestTokenRecord?.() || (() => {
102
+ const token = normalizeToken(persistence.getLatestToken?.());
103
+ return token ? {token, createdAt: Number.NaN} : null;
104
+ })();
105
+ const token = normalizeToken(record?.token);
106
+ const createdAt = Math.floor(Number(record?.createdAt));
107
+
108
+ if (!isTokenFormatValid(token)) {
109
+ return null;
110
+ }
111
+
112
+ if (!Number.isFinite(createdAt)) {
113
+ return {token, createdAt: Number.NaN};
114
+ }
115
+
116
+ return {
117
+ token,
118
+ createdAt,
119
+ };
120
+ }
121
+
122
+ function loadTokens() {
123
+ if (!isPersistenceEnabled()) {
124
+ return 0;
125
+ }
126
+ return Number(persistence.countTokens?.() || 0);
127
+ }
128
+
129
+ function cleanupExpired({persist = false} = {}) {
130
+ const normalizedFixedPath = getNormalizedFixedPath();
131
+ if (!isGateEnabled() || normalizedFixedPath) {
132
+ log.trace({
133
+ persist,
134
+ gateEnabled: isGateEnabled(),
135
+ fixedPathEnabled: Boolean(normalizedFixedPath),
136
+ }, 'Nettoyage tokens expire ignores');
137
+ return;
138
+ }
139
+ if (persist) {
140
+ const graceTtlMs = computeTokenTtlMs(getEntryPathConfig().graceMin);
141
+ log.debug({graceTtlMs}, 'Nettoyage tokens expires');
142
+ persistence.deleteExpiredTokens({
143
+ olderThan: Date.now() - graceTtlMs,
144
+ keepToken: getCurrentToken(),
145
+ });
146
+ }
147
+ }
148
+
149
+ function createToken() {
150
+ const normalizedFixedPath = getNormalizedFixedPath();
151
+ const currentToken = getCurrentToken();
152
+ if (!isEffectivelyEnabled() || normalizedFixedPath) {
153
+ log.trace({
154
+ enabled: isEffectivelyEnabled(),
155
+ fixedPathEnabled: Boolean(normalizedFixedPath),
156
+ hasCurrentToken: Boolean(currentToken),
157
+ }, 'Creation token ignoree');
158
+ return currentToken;
159
+ }
160
+ const createdAt = Date.now();
161
+ const token = createRandomToken(getEntryPathConfig().tokenLength);
162
+
163
+ log.debug({tokenLength: token.length}, 'Creation nouveau token entree');
164
+ persistence.createToken(token, createdAt);
165
+ cleanupExpired({persist: true});
166
+ if (token !== currentToken) {
167
+ publishState(PUBSUB_EVENT_TOKEN_CHANGED);
168
+ }
169
+ return token;
170
+ }
171
+
172
+ function isValid(token) {
173
+ const normalizedFixedPath = getNormalizedFixedPath();
174
+ const currentToken = getCurrentToken();
175
+ const normalized = normalizeToken(token);
176
+ if (normalizedFixedPath) {
177
+ log.trace({
178
+ mode: 'fixed',
179
+ hasInputToken: Boolean(normalized),
180
+ }, 'Validation token entree');
181
+ if (!normalized) {
182
+ return false;
183
+ }
184
+ return normalized === currentToken;
185
+ }
186
+ if (!isGateEnabled()) {
187
+ log.trace({
188
+ mode: 'disabled',
189
+ hasCurrentToken: Boolean(currentToken),
190
+ hasInputToken: Boolean(normalized),
191
+ }, 'Validation token entree');
192
+ if (!currentToken) {
193
+ return true;
194
+ }
195
+ if (!normalized) {
196
+ return false;
197
+ }
198
+ return normalized === currentToken;
199
+ }
200
+ if (!normalized) {
201
+ log.trace('Validation token entree rejetee: token vide');
202
+ return false;
203
+ }
204
+ cleanupExpired({persist: true});
205
+ if (!isPersistenceEnabled()) {
206
+ log.trace('Validation token entree rejetee: persistence inactive');
207
+ return false;
208
+ }
209
+ log.trace('Validation token entree via persistence');
210
+ return Boolean(persistence.hasToken(normalized));
211
+ }
212
+
213
+ function rotateIfNeeded() {
214
+ if (!isPersistenceEnabled()) {
215
+ log.trace('Rotation token ignoree: persistence inactive');
216
+ return getCurrentToken();
217
+ }
218
+
219
+ const latestToken = getLatestTokenRecord();
220
+ if (!latestToken) {
221
+ log.debug('Rotation token: aucun token existant');
222
+ return createToken();
223
+ }
224
+
225
+ if (!Number.isFinite(latestToken.createdAt) || Date.now() < latestToken.createdAt + getRotateTtlMs()) {
226
+ log.trace({
227
+ hasCreatedAt: Number.isFinite(latestToken.createdAt),
228
+ }, 'Rotation token non requise');
229
+ return latestToken.token;
230
+ }
231
+
232
+ log.debug('Rotation token requise');
233
+ return createToken();
234
+ }
235
+
236
+ return {
237
+ isValid,
238
+ createToken,
239
+ cleanupExpired,
240
+ loadTokens,
241
+ getToken: getCurrentToken,
242
+ rotateIfNeeded,
243
+ };
244
+ }
@@ -0,0 +1,7 @@
1
+ export function normalizeToken(value) {
2
+ return String(value || '').replace(/^\/+|\/+$/g, '');
3
+ }
4
+
5
+ export function isTokenFormatValid(token) {
6
+ return /^[A-Za-z0-9_-]{8,128}$/.test(String(token || ''));
7
+ }
@@ -0,0 +1,8 @@
1
+ export function computeTokenTtlMs(graceMin) {
2
+ const value = Number(graceMin);
3
+ if (!Number.isFinite(value)) {
4
+ throw new Error('entryPath.graceMin must be a finite number');
5
+ }
6
+
7
+ return Math.max(60_000, value * 60_000);
8
+ }