@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,84 @@
1
+ import {CONFIG_PATHS} from '../../../services/config/configPaths.js';
2
+ import {
3
+ adminConfigSchema,
4
+ coerceConfigValue,
5
+ getFieldDefinition,
6
+ } from '../../../connection/api/configs.js';
7
+
8
+ export async function executeConfigCommand(services, args = {}) {
9
+ if (!args.action) {
10
+ return {
11
+ ok: true,
12
+ message: 'Configuration persistée effective.',
13
+ data: services.getConfig(),
14
+ };
15
+ }
16
+
17
+ if (args.action === 'get') {
18
+ const pathKey = String(args.path || '').trim();
19
+ if (!CONFIG_PATHS.includes(pathKey)) {
20
+ return {
21
+ ok: false,
22
+ message: `Chemin de configuration invalide: ${pathKey || '(vide)'}`,
23
+ };
24
+ }
25
+
26
+ return {
27
+ ok: true,
28
+ message: `Configuration ${pathKey}.`,
29
+ data: {
30
+ path: pathKey,
31
+ value: services.getConfigService().getConfig(pathKey),
32
+ },
33
+ };
34
+ }
35
+
36
+ if (args.action === 'set') {
37
+ const pathKey = String(args.path || '').trim();
38
+ if (!CONFIG_PATHS.includes(pathKey)) {
39
+ return {
40
+ ok: false,
41
+ message: `Chemin de configuration invalide: ${pathKey || '(vide)'}`,
42
+ };
43
+ }
44
+
45
+ if (args.value === '') {
46
+ return {
47
+ ok: false,
48
+ message: 'Valeur de configuration manquante.',
49
+ };
50
+ }
51
+
52
+ const field = getFieldDefinition(adminConfigSchema, pathKey);
53
+ if (!field) {
54
+ return {
55
+ ok: false,
56
+ message: `Champ de configuration inconnu: ${pathKey}`,
57
+ };
58
+ }
59
+
60
+ try {
61
+ const nextValue = coerceConfigValue(String(args.value || ''), field);
62
+ services.getConfigService().setConfig(pathKey, nextValue);
63
+
64
+ return {
65
+ ok: true,
66
+ message: `Configuration ${pathKey} mise a jour.`,
67
+ data: {
68
+ path: pathKey,
69
+ value: services.getConfigService().getConfig(pathKey),
70
+ },
71
+ };
72
+ } catch (error) {
73
+ return {
74
+ ok: false,
75
+ message: `Configuration invalide: ${error.message}`,
76
+ };
77
+ }
78
+ }
79
+
80
+ return {
81
+ ok: false,
82
+ message: `Action config inconnue: ${args.action}`,
83
+ };
84
+ }
@@ -0,0 +1,6 @@
1
+ export async function executeHelpCommand() {
2
+ return {
3
+ ok: true,
4
+ message: 'Utilisez remote-mouse --help pour afficher les commandes disponibles.',
5
+ };
6
+ }
@@ -0,0 +1,7 @@
1
+ export async function executeInfoCommand(services) {
2
+ return {
3
+ ok: true,
4
+ message: 'Capacites du serveur.',
5
+ data: await services.getSystem().getInfo(),
6
+ };
7
+ }
@@ -0,0 +1,7 @@
1
+ export async function executeOpenQrCommand(services) {
2
+ const result = await services.getRemotes().adminActions.openQrBrowserServer();
3
+ return {
4
+ ok: Boolean(result?.ok),
5
+ message: String(result?.message || 'Commande executee.'),
6
+ };
7
+ }
@@ -0,0 +1,52 @@
1
+ import {
2
+ getSamsungDeviceMac,
3
+ pickSamsungDevice,
4
+ } from '../../../remotes/samsung/device-config.js';
5
+
6
+ function mapDevice(device) {
7
+ return {
8
+ name: String(device?.name || '').trim(),
9
+ model: String(device?.model || '').trim(),
10
+ host: String(device?.ip || '').trim(),
11
+ mac: getSamsungDeviceMac(device),
12
+ };
13
+ }
14
+
15
+ export async function executeSamsungDetectCommand(services) {
16
+ try {
17
+ const samsungConfig = services.getConfig().samsungTv;
18
+ const devices = await services.getRemotes().samsung.discoverDevices();
19
+ const selected = pickSamsungDevice(
20
+ devices,
21
+ samsungConfig.alwaysAutoResolve
22
+ ? {...samsungConfig, host: '', mac: ''}
23
+ : samsungConfig,
24
+ );
25
+
26
+ if (!selected) {
27
+ if (!devices.length) {
28
+ return {
29
+ ok: false,
30
+ message: 'Aucune TV Samsung detectee.',
31
+ };
32
+ }
33
+
34
+ return {
35
+ ok: false,
36
+ message: 'Plusieurs TV Samsung detectees. Configurez samsungTv.host ou samsungTv.mac, ou desactivez alwaysAutoResolve.',
37
+ data: devices.map(mapDevice),
38
+ };
39
+ }
40
+
41
+ return {
42
+ ok: true,
43
+ message: 'TV Samsung detectee.',
44
+ data: mapDevice(selected),
45
+ };
46
+ } catch (error) {
47
+ return {
48
+ ok: false,
49
+ message: String(error?.message || error || 'Decouverte Samsung impossible.'),
50
+ };
51
+ }
52
+ }
@@ -0,0 +1,25 @@
1
+ export async function executeServiceCommand(services, args = {}) {
2
+ if (args.action === 'install') {
3
+ return services.getApplicationDaemonService().install();
4
+ }
5
+
6
+ if (args.action === 'disable') {
7
+ return services.getApplicationDaemonService().disable();
8
+ }
9
+
10
+ if (args.action === 'uninstall') {
11
+ return services.getApplicationDaemonService().uninstall();
12
+ }
13
+
14
+ if (args.action === 'restart') {
15
+ return services.getApplicationDaemonService().restart({
16
+ cause: 'user',
17
+ source: 'cli',
18
+ });
19
+ }
20
+
21
+ return {
22
+ ok: false,
23
+ message: `Action service inconnue: ${String(args.action || '').trim() || '(vide)'}`,
24
+ };
25
+ }
@@ -0,0 +1,7 @@
1
+ export async function executeSystemConfigCommand(services) {
2
+ return {
3
+ ok: true,
4
+ message: 'Configuration système.',
5
+ data: services.getSystemConfig(),
6
+ };
7
+ }
@@ -0,0 +1,24 @@
1
+ function mapTask(task) {
2
+ const dueAt = task?.dueAt || null;
3
+ const dueInMs = dueAt ? new Date(dueAt).getTime() - Date.now() : null;
4
+
5
+ return {
6
+ id: task?.id || null,
7
+ name: task?.name || 'unnamed-task',
8
+ running: Boolean(task?.running),
9
+ delayMs: Number.isFinite(task?.delayMs) ? task.delayMs : null,
10
+ dueAt,
11
+ dueInMs: Number.isFinite(dueInMs) ? dueInMs : null,
12
+ };
13
+ }
14
+
15
+ export async function executeTasksCommand(services) {
16
+ return {
17
+ ok: true,
18
+ message: 'Etat du task manager.',
19
+ data: {
20
+ now: new Date().toISOString(),
21
+ tasks: services.getTaskManager().getTasksSnapshot().map(mapTask),
22
+ },
23
+ };
24
+ }
@@ -0,0 +1,15 @@
1
+ export async function executeTokensCommand(services) {
2
+ const tokens = Array.from(
3
+ services.getPersistence().entryTokenDao.loadEntryTokens(),
4
+ ([token, createdAt]) => ({
5
+ token,
6
+ createdAt,
7
+ }),
8
+ );
9
+
10
+ return {
11
+ ok: true,
12
+ message: 'Tokens chargés.',
13
+ data: tokens,
14
+ };
15
+ }
@@ -0,0 +1,44 @@
1
+ import {executeConfigCommand} from './commands/configCommand.js';
2
+ import {executeHelpCommand} from './commands/helpCommand.js';
3
+ import {executeInfoCommand} from './commands/infoCommand.js';
4
+ import {executeOpenQrCommand} from './commands/openQrCommand.js';
5
+ import {executeSamsungDetectCommand} from './commands/samsungDetectCommand.js';
6
+ import {executeServiceCommand} from './commands/serviceCommand.js';
7
+ import {executeSystemConfigCommand} from './commands/systemConfigCommand.js';
8
+ import {executeTasksCommand} from './commands/tasksCommand.js';
9
+ import {executeTokensCommand} from './commands/tokensCommand.js';
10
+ import {formatCliCommand} from '../cli/parseCliArgs.js';
11
+
12
+ const commandHandlers = {
13
+ help: executeHelpCommand,
14
+ 'open-qr': executeOpenQrCommand,
15
+ qr: executeOpenQrCommand,
16
+ config: executeConfigCommand,
17
+ 'sys-config': executeSystemConfigCommand,
18
+ info: executeInfoCommand,
19
+ 'system-info': executeInfoCommand,
20
+ service: executeServiceCommand,
21
+ tasks: executeTasksCommand,
22
+ 'task-manager': executeTasksCommand,
23
+ 'samsung-detect': executeSamsungDetectCommand,
24
+ tokens: executeTokensCommand,
25
+ };
26
+
27
+ export async function executeCliCommand(services, command) {
28
+ const commandName = String(command?.name || '').trim();
29
+ const args = command?.args || {};
30
+
31
+ if (!commandName) {
32
+ return executeHelpCommand(services, args);
33
+ }
34
+
35
+ const handler = commandHandlers[commandName];
36
+ if (handler) {
37
+ return handler(services, args);
38
+ }
39
+
40
+ return {
41
+ ok: false,
42
+ message: `Commande inconnue: ${formatCliCommand(command)}`,
43
+ };
44
+ }
@@ -0,0 +1,38 @@
1
+ import {executeCliCommand} from './executeCliCommand.js';
2
+ import {
3
+ createLogger,
4
+ withCliLogStream,
5
+ } from '../../application/logger.js';
6
+
7
+ let log;
8
+ function getModuleLog() {
9
+ log ??= createLogger('cli:request');
10
+ return log;
11
+ }
12
+
13
+ function normalizeVerbosity(options = {}) {
14
+ return Math.max(0, Number.parseInt(options.verbosity || 0, 10) || 0);
15
+ }
16
+
17
+ function getVerbosityLogLevel(verbosity) {
18
+ return verbosity > 1 ? 'trace' : 'debug';
19
+ }
20
+
21
+ export async function withCliVerbosity(options = {}, callback, onLog = null) {
22
+ const log = getModuleLog();
23
+ const verbosity = normalizeVerbosity(options);
24
+ log.trace({verbosity}, 'Application verbosite CLI');
25
+
26
+ return verbosity > 0
27
+ ? withCliLogStream(getVerbosityLogLevel(verbosity), onLog, callback)
28
+ : callback();
29
+ }
30
+
31
+ export async function executeCliRequest(services, command, options = {}, onLog = null) {
32
+ const log = getModuleLog();
33
+ log.debug({
34
+ command: command?.name || '',
35
+ verbosity: normalizeVerbosity(options),
36
+ }, 'Execution requete CLI');
37
+ return withCliVerbosity(options, () => executeCliCommand(services, command), onLog);
38
+ }
@@ -0,0 +1,140 @@
1
+ import net from 'node:net';
2
+ import {getCliSocketAdapter} from '../cliSocket.js';
3
+ import {executeCliRequest} from './executeCliRequest.js';
4
+ import {createLogger} from '../../application/logger.js';
5
+
6
+ function writeResponse(socket, payload) {
7
+ socket.end(`${JSON.stringify(payload)}\n`);
8
+ }
9
+
10
+ function normalizeVerbosity(options = {}) {
11
+ return Math.max(0, Number.parseInt(options.verbosity || 0, 10) || 0);
12
+ }
13
+
14
+ function writeFrame(socket, payload) {
15
+ socket.write(`${JSON.stringify(payload)}\n`);
16
+ }
17
+
18
+ function writeResult(socket, result, options = {}) {
19
+ if (normalizeVerbosity(options) <= 0) {
20
+ writeResponse(socket, result);
21
+ return;
22
+ }
23
+
24
+ writeFrame(socket, {
25
+ type: 'result',
26
+ result,
27
+ });
28
+ socket.end();
29
+ }
30
+
31
+ function parseRequest(input) {
32
+ try {
33
+ const payload = JSON.parse(String(input || '').trim() || '{}');
34
+ const command = payload.command && typeof payload.command === 'object' ? payload.command : {name: String(payload.command || '').trim(), args: {}};
35
+ const options = payload.options && typeof payload.options === 'object' ? payload.options : {};
36
+ return {
37
+ command,
38
+ options,
39
+ };
40
+ } catch (_error) {
41
+ return {
42
+ command: {name: String(input || '').trim(), args: {}},
43
+ options: {},
44
+ };
45
+ }
46
+ }
47
+
48
+ const log = createLogger('cli');
49
+
50
+ export async function startCliServer(services) {
51
+
52
+ const cliSocket = getCliSocketAdapter();
53
+ const socketPath = cliSocket.getCliSocketPath();
54
+ let isClosed = false;
55
+
56
+ function closeServer() {
57
+ if (isClosed) {
58
+ return;
59
+ }
60
+
61
+ isClosed = true;
62
+ server.close();
63
+ cliSocket.cleanupCliServerSocket(socketPath);
64
+ }
65
+
66
+ cliSocket.prepareCliServerSocket(socketPath);
67
+
68
+ const server = net.createServer({allowHalfOpen: true}, (socket) => {
69
+ let input = '';
70
+ let handled = false;
71
+ socket.setEncoding('utf8');
72
+ log.trace('Connexion CLI ouverte');
73
+
74
+ async function handleCommand() {
75
+ if (handled) {
76
+ return;
77
+ }
78
+
79
+ handled = true;
80
+
81
+ try {
82
+ const request = parseRequest(input);
83
+ log.debug({
84
+ command: request.command?.name || '',
85
+ verbosity: normalizeVerbosity(request.options),
86
+ }, 'Commande CLI recue');
87
+ const result = await executeCliRequest(services, request.command, request.options, (entry) => {
88
+ writeFrame(socket, {
89
+ type: 'log',
90
+ entry,
91
+ });
92
+ });
93
+ log.debug({
94
+ command: request.command?.name || '',
95
+ ok: Boolean(result?.ok),
96
+ }, 'Commande CLI terminee');
97
+ writeResult(socket, result, request.options);
98
+ } catch (error) {
99
+ log.error({err: error}, 'Erreur execution commande CLI');
100
+ writeResponse(socket, {
101
+ ok: false,
102
+ message: `Erreur CLI: ${error.message}`,
103
+ });
104
+ }
105
+ }
106
+
107
+ socket.on('data', (chunk) => {
108
+ input += chunk;
109
+ });
110
+
111
+ socket.on('end', () => {
112
+ void handleCommand();
113
+ });
114
+ socket.on('close', () => {
115
+ log.trace('Connexion CLI fermee');
116
+ });
117
+ });
118
+
119
+ server.once('close', () => {
120
+ cliSocket.cleanupCliServerSocket(socketPath);
121
+ });
122
+
123
+ await new Promise((resolve, reject) => {
124
+ server.once('error', reject);
125
+ server.listen(socketPath, () => {
126
+ server.off('error', reject);
127
+ resolve();
128
+ });
129
+ });
130
+
131
+ cliSocket.secureCliServerSocket(socketPath);
132
+
133
+ log.info({socketPath}, 'Interface CLI locale prête');
134
+
135
+ return {
136
+ close() {
137
+ closeServer();
138
+ },
139
+ };
140
+ }
@@ -0,0 +1,11 @@
1
+ import crypto from "node:crypto";
2
+ import {clamp} from "../../utils/math.js";
3
+
4
+ export function createRandomToken(length) {
5
+ const safeLength = clamp(Math.floor(length), 8, 128);
6
+ let token = '';
7
+ while (token.length < safeLength) {
8
+ token += crypto.randomBytes(24).toString('base64url');
9
+ }
10
+ return token.slice(0, safeLength);
11
+ }
@@ -0,0 +1,155 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import dotenv from 'dotenv';
5
+
6
+ export function expandHomePath(value) {
7
+ const raw = String(value || '').trim();
8
+ if (!raw) {
9
+ return '';
10
+ }
11
+ if (raw === '~') {
12
+ return os.homedir();
13
+ }
14
+ if (raw.startsWith('~/')) {
15
+ return path.join(os.homedir(), raw.slice(2));
16
+ }
17
+ return raw;
18
+ }
19
+
20
+ export function resolveConfigDir(explicitConfigDir = '') {
21
+ const configuredDir = expandHomePath(explicitConfigDir);
22
+ if (configuredDir) {
23
+ return path.resolve(process.cwd(), configuredDir);
24
+ }
25
+ if (process.env.NODE_ENV === 'test') {
26
+ return path.join(os.tmpdir(), 'remote-mouse');
27
+ }
28
+ return path.join(os.homedir(), '.config', 'remote-mouse');
29
+ }
30
+
31
+ export function resolvePathFromConfigDir(value, configDir, fallbackName = '') {
32
+ const rawValue = String(value || '').trim();
33
+ const rawFallback = String(fallbackName || '').trim();
34
+ const candidate = expandHomePath(rawValue || rawFallback);
35
+
36
+ if (!candidate) {
37
+ return '';
38
+ }
39
+
40
+ if (path.isAbsolute(candidate)) {
41
+ return candidate;
42
+ }
43
+
44
+ return path.resolve(configDir, candidate);
45
+ }
46
+
47
+ export function resolveEnvFilePath({ appRoot, configDir = '', explicitEnvFilePath = '' }) {
48
+ const cwdEnvFilePath = path.join(process.cwd(), '.env');
49
+ const appEnvFilePath = appRoot ? path.join(appRoot, '.env') : '';
50
+ const configDirEnvFilePath = configDir ? path.join(configDir, '.env') : '';
51
+ const explicitResolved = explicitEnvFilePath
52
+ ? path.resolve(process.cwd(), expandHomePath(explicitEnvFilePath))
53
+ : '';
54
+
55
+ if (explicitResolved && fs.existsSync(explicitResolved)) {
56
+ return explicitResolved;
57
+ }
58
+ if (configDirEnvFilePath && fs.existsSync(configDirEnvFilePath)) {
59
+ return configDirEnvFilePath;
60
+ }
61
+ if (fs.existsSync(cwdEnvFilePath)) {
62
+ return cwdEnvFilePath;
63
+ }
64
+ if (appEnvFilePath && fs.existsSync(appEnvFilePath)) {
65
+ return appEnvFilePath;
66
+ }
67
+ return '';
68
+ }
69
+
70
+ export function loadEnvFile(envFilePath) {
71
+ if (!envFilePath) {
72
+ return;
73
+ }
74
+ dotenv.config({ path: envFilePath, override: false });
75
+ }
76
+
77
+ export function readPackageVersion(packageJsonPath, fallback = 'unknown') {
78
+ try {
79
+ const raw = fs.readFileSync(packageJsonPath, 'utf8');
80
+ const parsed = JSON.parse(raw);
81
+ return String(parsed?.version || '').trim() || fallback;
82
+ } catch (_error) {
83
+ return fallback;
84
+ }
85
+ }
86
+
87
+ export function readRaw(key, fallback = '') {
88
+ if (Object.prototype.hasOwnProperty.call(process.env, key)
89
+ && process.env[key] !== undefined
90
+ && process.env[key] !== null
91
+ && process.env[key] !== '') {
92
+ return String(process.env[key]);
93
+ }
94
+ return fallback;
95
+ }
96
+
97
+ export function readString(key, fallback = '') {
98
+ return readRaw(key, fallback).trim();
99
+ }
100
+
101
+ export function readOptionalString(key) {
102
+ if (!Object.prototype.hasOwnProperty.call(process.env, key)
103
+ || process.env[key] === undefined
104
+ || process.env[key] === null
105
+ || process.env[key] === '') {
106
+ return undefined;
107
+ }
108
+ return String(process.env[key]).trim();
109
+ }
110
+
111
+ export function readNumber(
112
+ key,
113
+ fallback,
114
+ { min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY } = {},
115
+ ) {
116
+ const raw = readRaw(key, String(fallback));
117
+ const value = Number(raw);
118
+ if (!Number.isFinite(value)) {
119
+ return fallback;
120
+ }
121
+ if (value < min) {
122
+ return min;
123
+ }
124
+ if (value > max) {
125
+ return max;
126
+ }
127
+ return value;
128
+ }
129
+
130
+ export function readOptionalNumber(key) {
131
+ if (!Object.prototype.hasOwnProperty.call(process.env, key)
132
+ || process.env[key] === undefined
133
+ || process.env[key] === null
134
+ || process.env[key] === '') {
135
+ return undefined;
136
+ }
137
+ const value = Number(process.env[key]);
138
+ return Number.isFinite(value) ? value : undefined;
139
+ }
140
+
141
+ export function readBoolean(key, fallback = false) {
142
+ const raw = readRaw(key, fallback ? 'true' : 'false').toLowerCase();
143
+ return raw === '1' || raw === 'true' || raw === 'yes' || raw === 'on';
144
+ }
145
+
146
+ export function readOptionalBoolean(key) {
147
+ if (!Object.prototype.hasOwnProperty.call(process.env, key)
148
+ || process.env[key] === undefined
149
+ || process.env[key] === null
150
+ || process.env[key] === '') {
151
+ return undefined;
152
+ }
153
+ const normalized = String(process.env[key]).trim().toLowerCase();
154
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
155
+ }
@@ -0,0 +1,13 @@
1
+ import { execFile } from 'node:child_process';
2
+
3
+ export function runGit(args) {
4
+ return new Promise((resolve) => {
5
+ execFile('git', args, { timeout: 5000 }, (error, stdout = '', stderr = '') => {
6
+ resolve({
7
+ ok: !error,
8
+ stdout: String(stdout).trim(),
9
+ stderr: String(stderr).trim(),
10
+ });
11
+ });
12
+ });
13
+ }
@@ -0,0 +1,7 @@
1
+ export async function fetchJson(url) {
2
+ const response = await fetch(url);
3
+ if (!response.ok) {
4
+ throw new Error(`HTTP ${response.status}`);
5
+ }
6
+ return response.json();
7
+ }
@@ -0,0 +1,45 @@
1
+ import os from 'node:os';
2
+ import { execFileAsync } from './process.js';
3
+
4
+ export function getLanIp(forcedHost = '') {
5
+ if (forcedHost) {
6
+ return forcedHost;
7
+ }
8
+
9
+ try {
10
+ const interfaces = os.networkInterfaces();
11
+ for (const interfaceName of Object.keys(interfaces)) {
12
+ const addresses = interfaces[interfaceName] || [];
13
+ for (const address of addresses) {
14
+ if (address.family === 'IPv4' && !address.internal) {
15
+ return address.address;
16
+ }
17
+ }
18
+ }
19
+ } catch (_error) {
20
+ console.warn("Impossible de detecter l'IP LAN automatiquement, fallback sur localhost.");
21
+ }
22
+
23
+ return '127.0.0.1';
24
+ }
25
+
26
+ export function getPublicUrl(port, protocol = 'http', forcedHost = '') {
27
+ return `${protocol}://${getLanIp(forcedHost)}:${port}`;
28
+ }
29
+
30
+ export async function pingHost(host, timeoutMs = 2000) {
31
+ const normalizedHost = String(host || '').trim();
32
+ if (!normalizedHost) {
33
+ return false;
34
+ }
35
+
36
+ const args = process.platform === 'win32'
37
+ ? ['-n', '1', normalizedHost]
38
+ : ['-c', '1', normalizedHost];
39
+
40
+ const result = await execFileAsync('ping', args, {
41
+ timeout: Math.max(250, Number(timeoutMs) || 2000),
42
+ });
43
+
44
+ return Boolean(result.ok);
45
+ }