@velor/remote-mouse 6.4.11 → 6.6.0
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.
- package/README.md +2 -0
- package/package.json +1 -1
- package/public/server-info.html +53 -85
- package/server/application/shutdown.js +1 -0
- package/server/application/start.js +2 -0
- package/server/application/state.js +1 -0
- package/server/connection/api/server-info.router.js +20 -2
- package/server/init/observers/startUpdateManagerLogObserver.js +9 -0
- package/server/services/config/bootstrapConfig.js +3 -7
- package/server/services/persistence/createUpdateEventLogDao.js +93 -0
- package/server/services/persistence/index.js +2 -0
- package/server/term/cli/parseCliArgs.js +6 -0
- package/server/term/cli/runCliCmd.js +7 -0
- package/server/term/srv/commands/helpCommand.js +19 -1
- package/server/term/srv/commands/updateEventsCommand.js +7 -0
- package/server/term/srv/executeCliCommand.js +3 -0
package/README.md
CHANGED
|
@@ -305,12 +305,14 @@ Useful CLI commands:
|
|
|
305
305
|
- `config get <path>` prints one persisted configuration value
|
|
306
306
|
- `config set <path> <value>` updates one persisted configuration value
|
|
307
307
|
- `sys-config` prints the system configuration
|
|
308
|
+
- `system-config` is an alias of `sys-config`
|
|
308
309
|
- `service install` installs the local daemon/service
|
|
309
310
|
- `service disable` disables the local daemon/service
|
|
310
311
|
- `service uninstall` uninstalls the local daemon/service
|
|
311
312
|
- `service restart` restarts the local daemon/service
|
|
312
313
|
- `tasks` prints the task manager snapshot
|
|
313
314
|
- `task-manager` is an alias of `tasks`
|
|
315
|
+
- `update-events` prints persisted update-manager events
|
|
314
316
|
- `samsung-detect` detects Samsung TVs available on the network
|
|
315
317
|
- `tokens` lists persisted entry tokens
|
|
316
318
|
- `open-qr` opens the QR page on the server
|
package/package.json
CHANGED
package/public/server-info.html
CHANGED
|
@@ -150,6 +150,28 @@
|
|
|
150
150
|
</div>
|
|
151
151
|
</section>
|
|
152
152
|
|
|
153
|
+
<section>
|
|
154
|
+
<h2>Update-manager events</h2>
|
|
155
|
+
<div class="table-wrap">
|
|
156
|
+
<table>
|
|
157
|
+
<thead>
|
|
158
|
+
<tr>
|
|
159
|
+
<th>ID</th>
|
|
160
|
+
<th>Type</th>
|
|
161
|
+
<th>At</th>
|
|
162
|
+
<th>Enabled</th>
|
|
163
|
+
<th>Key</th>
|
|
164
|
+
<th>Checked</th>
|
|
165
|
+
<th>Has update</th>
|
|
166
|
+
<th>Skipped</th>
|
|
167
|
+
<th>Error</th>
|
|
168
|
+
</tr>
|
|
169
|
+
</thead>
|
|
170
|
+
<tbody id="update-events-table"></tbody>
|
|
171
|
+
</table>
|
|
172
|
+
</div>
|
|
173
|
+
</section>
|
|
174
|
+
|
|
153
175
|
<section>
|
|
154
176
|
<h2 data-i18n="serverInfo.section.capabilities">Capabilities</h2>
|
|
155
177
|
<pre id="capabilities"></pre>
|
|
@@ -192,6 +214,7 @@
|
|
|
192
214
|
const tasksTable = document.getElementById('tasks-table');
|
|
193
215
|
const tokensTable = document.getElementById('tokens-table');
|
|
194
216
|
const restartsTable = document.getElementById('restarts-table');
|
|
217
|
+
const updateEventsTable = document.getElementById('update-events-table');
|
|
195
218
|
const capabilitiesEl = document.getElementById('capabilities');
|
|
196
219
|
const configEl = document.getElementById('config');
|
|
197
220
|
const sysConfigEl = document.getElementById('sys-config');
|
|
@@ -202,10 +225,6 @@
|
|
|
202
225
|
timeStyle: 'medium',
|
|
203
226
|
});
|
|
204
227
|
let logsAutoScroll = true;
|
|
205
|
-
let configStream = null;
|
|
206
|
-
let configSubscriptionId = '';
|
|
207
|
-
let pendingConfigPayload = null;
|
|
208
|
-
let applyingConfigPayload = false;
|
|
209
228
|
|
|
210
229
|
function t(key, params) {
|
|
211
230
|
return i18n.t(key, params);
|
|
@@ -349,6 +368,33 @@
|
|
|
349
368
|
}
|
|
350
369
|
}
|
|
351
370
|
|
|
371
|
+
function renderUpdateEvents(updateEvents) {
|
|
372
|
+
updateEventsTable.innerHTML = '';
|
|
373
|
+
if (!Array.isArray(updateEvents) || updateEvents.length === 0) {
|
|
374
|
+
const row = document.createElement('tr');
|
|
375
|
+
row.innerHTML = '<td colspan="9">No update-manager events.</td>';
|
|
376
|
+
updateEventsTable.appendChild(row);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
for (const event of updateEvents) {
|
|
381
|
+
const row = document.createElement('tr');
|
|
382
|
+
const result = event.lastResult || {};
|
|
383
|
+
row.innerHTML = `
|
|
384
|
+
<td>${event.id ?? ''}</td>
|
|
385
|
+
<td>${event.type || '-'}</td>
|
|
386
|
+
<td>${formatDateTime(event.eventAt)}</td>
|
|
387
|
+
<td>${event.enabled ? 'yes' : 'no'}</td>
|
|
388
|
+
<td>${event.lastKey || '-'}</td>
|
|
389
|
+
<td>${Object.hasOwn(result, 'checked') ? (result.checked ? 'yes' : 'no') : '-'}</td>
|
|
390
|
+
<td>${Object.hasOwn(result, 'hasUpdate') ? (result.hasUpdate ? 'yes' : 'no') : '-'}</td>
|
|
391
|
+
<td>${Object.hasOwn(result, 'skipped') ? (result.skipped ? 'yes' : 'no') : '-'}</td>
|
|
392
|
+
<td>${result.error || '-'}</td>
|
|
393
|
+
`;
|
|
394
|
+
updateEventsTable.appendChild(row);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
352
398
|
function renderLogs(logs) {
|
|
353
399
|
const previousScrollTop = logsEl.scrollTop;
|
|
354
400
|
const shouldAutoScroll = logsAutoScroll;
|
|
@@ -446,33 +492,6 @@
|
|
|
446
492
|
sysConfigEl.textContent = JSON.stringify(snapshot || {}, null, 2);
|
|
447
493
|
}
|
|
448
494
|
|
|
449
|
-
function flushPendingConfigPayload() {
|
|
450
|
-
if (applyingConfigPayload || !pendingConfigPayload) {
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
applyingConfigPayload = true;
|
|
455
|
-
const payload = pendingConfigPayload;
|
|
456
|
-
pendingConfigPayload = null;
|
|
457
|
-
|
|
458
|
-
try {
|
|
459
|
-
renderConfigSnapshot(payload.config);
|
|
460
|
-
renderSystemConfigSnapshot(payload.sysConfig);
|
|
461
|
-
} finally {
|
|
462
|
-
applyingConfigPayload = false;
|
|
463
|
-
if (pendingConfigPayload) {
|
|
464
|
-
flushPendingConfigPayload();
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
function scheduleConfigPayload(payload) {
|
|
470
|
-
pendingConfigPayload = payload;
|
|
471
|
-
queueMicrotask(() => {
|
|
472
|
-
flushPendingConfigPayload();
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
|
|
476
495
|
async function refresh() {
|
|
477
496
|
try {
|
|
478
497
|
const response = await fetch('/api/admin/server-info/data', { cache: 'no-store' });
|
|
@@ -498,77 +517,26 @@
|
|
|
498
517
|
renderTasks(data.tasks || []);
|
|
499
518
|
renderTokens(data.tokens || []);
|
|
500
519
|
renderRestarts(data.restarts || []);
|
|
520
|
+
renderUpdateEvents(data.updateEvents || []);
|
|
501
521
|
renderCapabilities(data.system || null);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
sysConfig: data.sysConfig,
|
|
505
|
-
});
|
|
522
|
+
renderConfigSnapshot(data.config);
|
|
523
|
+
renderSystemConfigSnapshot(data.sysConfig);
|
|
506
524
|
renderLogs(data.logs || []);
|
|
507
525
|
} catch (error) {
|
|
508
526
|
logsEl.textContent = t('serverInfo.loadError', {message: error?.message || error});
|
|
509
527
|
}
|
|
510
528
|
}
|
|
511
529
|
|
|
512
|
-
async function subscribeToConfigEvents() {
|
|
513
|
-
if (typeof window.EventSource !== 'function') {
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const response = await fetch('/api/admin/subs/configs', {
|
|
518
|
-
method: 'POST',
|
|
519
|
-
headers: {
|
|
520
|
-
'Content-Type': 'application/json',
|
|
521
|
-
},
|
|
522
|
-
body: JSON.stringify({scope: 'config'}),
|
|
523
|
-
});
|
|
524
|
-
if (!response.ok) {
|
|
525
|
-
throw new Error(t('serverInfo.sseCreateError'));
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
const payload = await response.json();
|
|
529
|
-
configSubscriptionId = String(payload.id || '');
|
|
530
|
-
if (!configSubscriptionId || !payload.eventsUrl) {
|
|
531
|
-
throw new Error(t('serverInfo.sseInvalid'));
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
configStream?.close();
|
|
535
|
-
configStream = new EventSource(payload.eventsUrl);
|
|
536
|
-
configStream.addEventListener('config.changed', (event) => {
|
|
537
|
-
try {
|
|
538
|
-
scheduleConfigPayload(JSON.parse(event.data || '{}'));
|
|
539
|
-
} catch (_error) {
|
|
540
|
-
// Best effort.
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
function unsubscribeFromConfigEvents() {
|
|
546
|
-
if (!configSubscriptionId) {
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
fetch(`/api/admin/subs/${encodeURIComponent(configSubscriptionId)}`, {
|
|
551
|
-
method: 'DELETE',
|
|
552
|
-
keepalive: true,
|
|
553
|
-
}).catch(() => {});
|
|
554
|
-
configSubscriptionId = '';
|
|
555
|
-
}
|
|
556
|
-
|
|
557
530
|
logsEl.addEventListener('scroll', () => {
|
|
558
531
|
logsAutoScroll = isLogScrollAtBottom();
|
|
559
532
|
}, { passive: true });
|
|
560
533
|
|
|
561
534
|
refresh();
|
|
562
535
|
setInterval(refresh, 2000);
|
|
563
|
-
subscribeToConfigEvents().catch(() => {});
|
|
564
536
|
i18n.onChange(() => {
|
|
565
537
|
i18n.translateRoot(document);
|
|
566
538
|
refresh();
|
|
567
539
|
});
|
|
568
|
-
window.addEventListener('beforeunload', () => {
|
|
569
|
-
configStream?.close();
|
|
570
|
-
unsubscribeFromConfigEvents();
|
|
571
|
-
});
|
|
572
540
|
</script>
|
|
573
541
|
</body>
|
|
574
542
|
</html>
|
|
@@ -44,6 +44,7 @@ export function createApplicationShutdown(services) {
|
|
|
44
44
|
runShutdownStep('Erreur a l arret du task manager', () => taskManager.stop()),
|
|
45
45
|
runShutdownStep('Erreur a l arret de l observateur de configuration', () => state.stopConfigObserver()),
|
|
46
46
|
runShutdownStep('Erreur a l arret de l observateur de notifications', () => state.stopNotificationObserver()),
|
|
47
|
+
runShutdownStep('Erreur a l arret de l observateur des evenements update-manager', () => state.stopUpdateManagerLogObserver()),
|
|
47
48
|
runShutdownStep('Erreur a l arret de l observateur de resolution ecran', () => state.stopDisplaySizeObserver()),
|
|
48
49
|
runShutdownStep('Erreur a l arret de l observateur du QR overlay', () => state.stopQrOverlayRefreshObserver()),
|
|
49
50
|
runShutdownStep('Erreur a l arret de l observateur du survol QR overlay', () => state.stopQrOverlayHoverObserver()),
|
|
@@ -8,6 +8,7 @@ import {startNotificationObserver} from '../init/observers/startNotificationObse
|
|
|
8
8
|
import {startDisplaySizeObserver} from '../init/observers/startDisplaySizeObserver.js';
|
|
9
9
|
import {startQrOverlayRefreshObserver} from '../init/observers/startQrOverlayRefreshObserver.js';
|
|
10
10
|
import {startQrOverlayHoverObserver} from '../init/observers/startQrOverlayHoverObserver.js';
|
|
11
|
+
import {startUpdateManagerLogObserver} from '../init/observers/startUpdateManagerLogObserver.js';
|
|
11
12
|
import {notifyIfRestarted} from '../remotes/admin/notifyIfRestarted.js';
|
|
12
13
|
import {ensureApplicationLifecycleState} from './state.js';
|
|
13
14
|
import {createLogger} from './logger.js';
|
|
@@ -41,6 +42,7 @@ export function createApplicationStart(services) {
|
|
|
41
42
|
|
|
42
43
|
state.stopConfigObserver = startConfigObserver(services);
|
|
43
44
|
state.stopNotificationObserver = startNotificationObserver(services);
|
|
45
|
+
state.stopUpdateManagerLogObserver = startUpdateManagerLogObserver(services);
|
|
44
46
|
state.stopDisplaySizeObserver = startDisplaySizeObserver(services);
|
|
45
47
|
state.stopQrOverlayRefreshObserver = startQrOverlayRefreshObserver(services);
|
|
46
48
|
state.stopQrOverlayHoverObserver = startQrOverlayHoverObserver(services);
|
|
@@ -8,6 +8,7 @@ export function ensureApplicationLifecycleState(services) {
|
|
|
8
8
|
shuttingDown: false,
|
|
9
9
|
stopConfigObserver: () => {},
|
|
10
10
|
stopNotificationObserver: () => {},
|
|
11
|
+
stopUpdateManagerLogObserver: () => {},
|
|
11
12
|
stopDisplaySizeObserver: () => {},
|
|
12
13
|
stopQrOverlayRefreshObserver: () => {},
|
|
13
14
|
stopQrOverlayHoverObserver: () => {},
|
|
@@ -29,6 +29,22 @@ function redactSecrets(value, key = '') {
|
|
|
29
29
|
return value;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function buildConfigSnapshots(rawConfig, rawSystemConfig) {
|
|
33
|
+
const config = redactSecrets(rawConfig);
|
|
34
|
+
const sysConfig = redactSecrets(rawSystemConfig);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
config: {
|
|
38
|
+
...config,
|
|
39
|
+
updateCheck: {
|
|
40
|
+
...sysConfig?.updateCheck,
|
|
41
|
+
...config?.updateCheck,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
sysConfig,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
function getConnectedClients(io) {
|
|
33
49
|
return Array.from(io.of('/').sockets.values()).map((socket) => ({
|
|
34
50
|
id: socket.id,
|
|
@@ -106,13 +122,13 @@ export function createServerInfoRouter(services) {
|
|
|
106
122
|
const clients = getConnectedClients(services.getServer().io);
|
|
107
123
|
const rawConfig = services.getConfig();
|
|
108
124
|
const rawSystemConfig = services.getSystemConfig();
|
|
109
|
-
const config =
|
|
110
|
-
const sysConfig = redactSecrets(rawSystemConfig);
|
|
125
|
+
const {config, sysConfig} = buildConfigSnapshots(rawConfig, rawSystemConfig);
|
|
111
126
|
const logs = getRecentLogs(250);
|
|
112
127
|
const version = readPackageVersion(packageJsonPath);
|
|
113
128
|
const tasks = services.getTaskManager().getTasksSnapshot();
|
|
114
129
|
const tokenEntries = services.getPersistence().entryTokenDao.loadEntryTokens();
|
|
115
130
|
const restarts = services.getPersistence().restartLogDao.listRecentRestartRecords(20);
|
|
131
|
+
const updateEvents = services.getPersistence().updateEventLogDao.listRecentEvents(20);
|
|
116
132
|
const currentToken = services.getTokenManager().getToken();
|
|
117
133
|
const entryPathConfig = services.getSystemConfig().entryPath;
|
|
118
134
|
const daemon = await services.getApplicationDaemonService().getInfo();
|
|
@@ -135,6 +151,7 @@ export function createServerInfoRouter(services) {
|
|
|
135
151
|
daemon,
|
|
136
152
|
system,
|
|
137
153
|
restarts,
|
|
154
|
+
updateEvents,
|
|
138
155
|
config,
|
|
139
156
|
sysConfig,
|
|
140
157
|
logs,
|
|
@@ -145,5 +162,6 @@ export function createServerInfoRouter(services) {
|
|
|
145
162
|
|
|
146
163
|
export const __testables = {
|
|
147
164
|
buildTokenEntries,
|
|
165
|
+
buildConfigSnapshots,
|
|
148
166
|
redactSecrets,
|
|
149
167
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {PUBSUB_SERVICE_UPDATE_MANAGER} from '../../services/pubsub/serviceEventConstants.js';
|
|
2
|
+
|
|
3
|
+
export function startUpdateManagerLogObserver(services) {
|
|
4
|
+
return services.getPubSub().subscribe((event) => {
|
|
5
|
+
services.getPersistence().updateEventLogDao.createEvent(event);
|
|
6
|
+
}, {
|
|
7
|
+
service: PUBSUB_SERVICE_UPDATE_MANAGER,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -11,7 +11,7 @@ import fs from "node:fs";
|
|
|
11
11
|
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
13
|
const __dirname = path.dirname(__filename);
|
|
14
|
-
export const projectRoot = path.join(__dirname, '
|
|
14
|
+
export const projectRoot = path.join(__dirname, '../../..');
|
|
15
15
|
export const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
16
16
|
|
|
17
17
|
export const bootstrapConfigDir = resolveConfigDir(process.env.CONFIG_DIR || '');
|
|
@@ -27,12 +27,8 @@ loadEnvFile(envFilePath);
|
|
|
27
27
|
export const CONFIG_DIR = resolveConfigDir(readString('CONFIG_DIR', bootstrapConfigDir));
|
|
28
28
|
|
|
29
29
|
export function readPackageJson() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return JSON.parse(raw);
|
|
33
|
-
} catch (_error) {
|
|
34
|
-
return {};
|
|
35
|
-
}
|
|
30
|
+
const raw = fs.readFileSync(packageJsonPath, 'utf8');
|
|
31
|
+
return JSON.parse(raw);
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
export const packageJson = readPackageJson();
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const UPDATE_EVENT_LOG_TABLE = 'update_manager_event_log';
|
|
2
|
+
|
|
3
|
+
function normalizeRecord(row) {
|
|
4
|
+
if (!row) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let lastResult = null;
|
|
9
|
+
try {
|
|
10
|
+
lastResult = JSON.parse(String(row.last_result_json || 'null'));
|
|
11
|
+
} catch (_error) {
|
|
12
|
+
lastResult = null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
id: Number(row.id),
|
|
17
|
+
eventAt: Number(row.event_at),
|
|
18
|
+
type: String(row.event_type || ''),
|
|
19
|
+
enabled: Boolean(row.enabled),
|
|
20
|
+
lastKey: String(row.last_key || ''),
|
|
21
|
+
lastInstallCommand: String(row.last_install_command || ''),
|
|
22
|
+
lastResult,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createUpdateEventLogDao({getDatabase}) {
|
|
27
|
+
let bootstrapped = false;
|
|
28
|
+
|
|
29
|
+
function bootstrapUpdateEventLogTable() {
|
|
30
|
+
if (bootstrapped) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const db = getDatabase();
|
|
35
|
+
db.exec(`
|
|
36
|
+
CREATE TABLE IF NOT EXISTS ${UPDATE_EVENT_LOG_TABLE} (
|
|
37
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38
|
+
event_at INTEGER NOT NULL,
|
|
39
|
+
event_type TEXT NOT NULL,
|
|
40
|
+
enabled INTEGER NOT NULL DEFAULT 0,
|
|
41
|
+
last_key TEXT NOT NULL DEFAULT '',
|
|
42
|
+
last_install_command TEXT NOT NULL DEFAULT '',
|
|
43
|
+
last_result_json TEXT NOT NULL DEFAULT 'null'
|
|
44
|
+
)
|
|
45
|
+
`);
|
|
46
|
+
|
|
47
|
+
bootstrapped = true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function createEvent(event = {}) {
|
|
51
|
+
bootstrapUpdateEventLogTable();
|
|
52
|
+
const db = getDatabase();
|
|
53
|
+
const payload = event?.payload || {};
|
|
54
|
+
const eventAtMs = Math.floor(new Date(event.at || Date.now()).getTime());
|
|
55
|
+
|
|
56
|
+
const result = db.prepare(`
|
|
57
|
+
INSERT INTO ${UPDATE_EVENT_LOG_TABLE} (
|
|
58
|
+
event_at,
|
|
59
|
+
event_type,
|
|
60
|
+
enabled,
|
|
61
|
+
last_key,
|
|
62
|
+
last_install_command,
|
|
63
|
+
last_result_json
|
|
64
|
+
)
|
|
65
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
66
|
+
`).run(
|
|
67
|
+
Number.isFinite(eventAtMs) ? eventAtMs : Date.now(),
|
|
68
|
+
String(event.type || 'event'),
|
|
69
|
+
payload?.enabled ? 1 : 0,
|
|
70
|
+
String(payload?.lastKey || ''),
|
|
71
|
+
String(payload?.lastInstallCommand || ''),
|
|
72
|
+
JSON.stringify(payload?.lastResult ?? null),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return Number(result.lastInsertRowid);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function listRecentEvents(limit = 20) {
|
|
79
|
+
bootstrapUpdateEventLogTable();
|
|
80
|
+
const db = getDatabase();
|
|
81
|
+
return db.prepare(`
|
|
82
|
+
SELECT *
|
|
83
|
+
FROM ${UPDATE_EVENT_LOG_TABLE}
|
|
84
|
+
ORDER BY event_at DESC, id DESC
|
|
85
|
+
LIMIT ?
|
|
86
|
+
`).all(Math.max(1, Number(limit) || 20)).map(normalizeRecord);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
createEvent,
|
|
91
|
+
listRecentEvents,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -2,6 +2,7 @@ import {createConfigDao} from './createConfigDao.js';
|
|
|
2
2
|
import {createEntryTokenDao} from './createEntryTokenDao.js';
|
|
3
3
|
import {createDatabaseProvider} from './createDatabaseProvider.js';
|
|
4
4
|
import {createRestartLogDao} from './createRestartLogDao.js';
|
|
5
|
+
import {createUpdateEventLogDao} from './createUpdateEventLogDao.js';
|
|
5
6
|
|
|
6
7
|
export function createPersistence(services) {
|
|
7
8
|
const getDatabase = createDatabaseProvider({
|
|
@@ -15,5 +16,6 @@ export function createPersistence(services) {
|
|
|
15
16
|
}),
|
|
16
17
|
entryTokenDao: createEntryTokenDao({getDatabase}),
|
|
17
18
|
restartLogDao: createRestartLogDao({getDatabase}),
|
|
19
|
+
updateEventLogDao: createUpdateEventLogDao({getDatabase}),
|
|
18
20
|
};
|
|
19
21
|
}
|
|
@@ -51,6 +51,9 @@ export function parseCliArgs(args) {
|
|
|
51
51
|
.command('sys-config', false, () => {}, () => {
|
|
52
52
|
command = {name: 'sys-config', args: {}};
|
|
53
53
|
})
|
|
54
|
+
.command('system-config', false, () => {}, () => {
|
|
55
|
+
command = {name: 'system-config', args: {}};
|
|
56
|
+
})
|
|
54
57
|
.command('info', false, () => {}, () => {
|
|
55
58
|
command = {name: 'info', args: {}};
|
|
56
59
|
})
|
|
@@ -72,6 +75,9 @@ export function parseCliArgs(args) {
|
|
|
72
75
|
.command('task-manager', false, () => {}, () => {
|
|
73
76
|
command = {name: 'task-manager', args: {}};
|
|
74
77
|
})
|
|
78
|
+
.command('update-events', false, () => {}, () => {
|
|
79
|
+
command = {name: 'update-events', args: {}};
|
|
80
|
+
})
|
|
75
81
|
.command('samsung-detect', false, () => {}, () => {
|
|
76
82
|
command = {name: 'samsung-detect', args: {}};
|
|
77
83
|
})
|
|
@@ -18,16 +18,23 @@ export async function runCliCmd(args) {
|
|
|
18
18
|
if (!command?.name || command.name === 'help') {
|
|
19
19
|
console.log('Usage:');
|
|
20
20
|
console.log(' remote-mouse Demarre le serveur');
|
|
21
|
+
console.log(' remote-mouse help Affiche cette aide');
|
|
21
22
|
console.log(' remote-mouse config Affiche la configuration persistée effective');
|
|
23
|
+
console.log(' remote-mouse config get <path> Affiche une valeur de configuration persistée');
|
|
24
|
+
console.log(' remote-mouse config set <path> <value> Met a jour une valeur de configuration persistée');
|
|
25
|
+
console.log(' remote-mouse sys-config Affiche la configuration systeme');
|
|
26
|
+
console.log(' remote-mouse system-config Alias de sys-config');
|
|
22
27
|
console.log(' remote-mouse service install Installe le daemon/service local');
|
|
23
28
|
console.log(' remote-mouse service disable Desactive le daemon/service local');
|
|
24
29
|
console.log(' remote-mouse service uninstall Desinstalle le daemon/service local');
|
|
25
30
|
console.log(' remote-mouse service restart Redemarre le daemon/service local');
|
|
26
31
|
console.log(' remote-mouse tasks Affiche les informations du task manager');
|
|
27
32
|
console.log(' remote-mouse task-manager Alias de tasks');
|
|
33
|
+
console.log(' remote-mouse update-events Affiche les evenements persistés du update-manager');
|
|
28
34
|
console.log(' remote-mouse info --verbosity 2 Affiche les capacites serveur avec logs detailles');
|
|
29
35
|
console.log(' remote-mouse system-info Alias de info');
|
|
30
36
|
console.log(' remote-mouse tokens Liste les tokens en base');
|
|
37
|
+
console.log(' remote-mouse samsung-detect Detecte les TV Samsung sur le reseau');
|
|
31
38
|
console.log(' remote-mouse open-qr Envoie une commande au service deja demarre');
|
|
32
39
|
console.log(' remote-mouse qr Alias de open-qr');
|
|
33
40
|
process.exit(0);
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
export async function executeHelpCommand() {
|
|
2
2
|
return {
|
|
3
3
|
ok: true,
|
|
4
|
-
message:
|
|
4
|
+
message: [
|
|
5
|
+
'Commandes disponibles:',
|
|
6
|
+
'remote-mouse help',
|
|
7
|
+
'remote-mouse config',
|
|
8
|
+
'remote-mouse config get <path>',
|
|
9
|
+
'remote-mouse config set <path> <value>',
|
|
10
|
+
'remote-mouse sys-config',
|
|
11
|
+
'remote-mouse system-config',
|
|
12
|
+
'remote-mouse info',
|
|
13
|
+
'remote-mouse system-info',
|
|
14
|
+
'remote-mouse service <install|disable|uninstall|restart>',
|
|
15
|
+
'remote-mouse tasks',
|
|
16
|
+
'remote-mouse task-manager',
|
|
17
|
+
'remote-mouse update-events',
|
|
18
|
+
'remote-mouse samsung-detect',
|
|
19
|
+
'remote-mouse tokens',
|
|
20
|
+
'remote-mouse open-qr',
|
|
21
|
+
'remote-mouse qr',
|
|
22
|
+
].join('\n'),
|
|
5
23
|
};
|
|
6
24
|
}
|
|
@@ -7,6 +7,7 @@ import {executeServiceCommand} from './commands/serviceCommand.js';
|
|
|
7
7
|
import {executeSystemConfigCommand} from './commands/systemConfigCommand.js';
|
|
8
8
|
import {executeTasksCommand} from './commands/tasksCommand.js';
|
|
9
9
|
import {executeTokensCommand} from './commands/tokensCommand.js';
|
|
10
|
+
import {executeUpdateEventsCommand} from './commands/updateEventsCommand.js';
|
|
10
11
|
import {formatCliCommand} from '../cli/parseCliArgs.js';
|
|
11
12
|
|
|
12
13
|
const commandHandlers = {
|
|
@@ -15,11 +16,13 @@ const commandHandlers = {
|
|
|
15
16
|
qr: executeOpenQrCommand,
|
|
16
17
|
config: executeConfigCommand,
|
|
17
18
|
'sys-config': executeSystemConfigCommand,
|
|
19
|
+
'system-config': executeSystemConfigCommand,
|
|
18
20
|
info: executeInfoCommand,
|
|
19
21
|
'system-info': executeInfoCommand,
|
|
20
22
|
service: executeServiceCommand,
|
|
21
23
|
tasks: executeTasksCommand,
|
|
22
24
|
'task-manager': executeTasksCommand,
|
|
25
|
+
'update-events': executeUpdateEventsCommand,
|
|
23
26
|
'samsung-detect': executeSamsungDetectCommand,
|
|
24
27
|
tokens: executeTokensCommand,
|
|
25
28
|
};
|