@davidfuchs/mcp-uptime-kuma 0.7.0 → 0.10.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 +47 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +300 -6
- package/dist/server.js.map +1 -1
- package/dist/types/docker-host.d.ts +26 -0
- package/dist/types/docker-host.d.ts.map +1 -0
- package/dist/types/docker-host.js +13 -0
- package/dist/types/docker-host.js.map +1 -0
- package/dist/types/heartbeat.d.ts +32 -32
- package/dist/types/heartbeat.d.ts.map +1 -1
- package/dist/types/heartbeat.js +2 -2
- package/dist/types/heartbeat.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/maintenance.d.ts +27 -27
- package/dist/types/maintenance.js +3 -3
- package/dist/types/maintenance.js.map +1 -1
- package/dist/types/monitor-base.js +1 -1
- package/dist/types/monitor-base.js.map +1 -1
- package/dist/types/status-page.d.ts +12 -12
- package/dist/types/status-page.js +4 -4
- package/dist/types/status-page.js.map +1 -1
- package/dist/uptime-kuma-client.d.ts +108 -6
- package/dist/uptime-kuma-client.d.ts.map +1 -1
- package/dist/uptime-kuma-client.js +341 -20
- package/dist/uptime-kuma-client.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +75 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Socket } from 'socket.io-client';
|
|
2
2
|
import type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
-
import type { MonitorBaseWithExtendedData, MonitorWithExtendedData, ApiResponse, LoginResponse, MonitorList, MonitorSummary, Heartbeat, GetSettingsResponse, Notification, Maintenance, StatusPage } from './types/index.js';
|
|
3
|
+
import type { MonitorBaseWithExtendedData, MonitorWithExtendedData, ApiResponse, LoginResponse, MonitorList, MonitorSummary, Heartbeat, GetSettingsResponse, Notification, Maintenance, StatusPage, DockerHost } from './types/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Uptime Kuma Socket.io API Client
|
|
6
6
|
*/
|
|
@@ -15,6 +15,7 @@ export declare class UptimeKumaClient {
|
|
|
15
15
|
private tagListCache;
|
|
16
16
|
private maintenanceListCache;
|
|
17
17
|
private statusPageListCache;
|
|
18
|
+
private dockerHostListCache;
|
|
18
19
|
private server?;
|
|
19
20
|
private shouldLog;
|
|
20
21
|
private loginCredentials;
|
|
@@ -148,8 +149,11 @@ export declare class UptimeKumaClient {
|
|
|
148
149
|
private setupTagListListeners;
|
|
149
150
|
private setupMaintenanceListListeners;
|
|
150
151
|
private setupStatusPageListListeners;
|
|
152
|
+
private setupDockerHostListListeners;
|
|
151
153
|
/**
|
|
152
|
-
* Create a new monitor
|
|
154
|
+
* Create a new monitor. If `tags` are supplied, they are applied after
|
|
155
|
+
* creation using the separate `addMonitorTag` socket event — the `add`
|
|
156
|
+
* socket handler does not process tags.
|
|
153
157
|
*
|
|
154
158
|
* @param monitorData - Monitor configuration (type-specific fields should be included)
|
|
155
159
|
* @returns Promise resolving to the API response with the new monitorID
|
|
@@ -158,7 +162,11 @@ export declare class UptimeKumaClient {
|
|
|
158
162
|
monitorID?: number;
|
|
159
163
|
}>;
|
|
160
164
|
/**
|
|
161
|
-
* Update an existing monitor
|
|
165
|
+
* Update an existing monitor. If `tags` are supplied, they are reconciled
|
|
166
|
+
* against the monitor's current tag set using `addMonitorTag` /
|
|
167
|
+
* `deleteMonitorTag` — the `editMonitor` socket handler does not process
|
|
168
|
+
* tags. Tags whose name is not yet in the catalog are auto-created via
|
|
169
|
+
* `addTag` before binding.
|
|
162
170
|
*
|
|
163
171
|
* @param monitorData - Monitor configuration including the id field
|
|
164
172
|
* @returns Promise resolving to the API response
|
|
@@ -166,6 +174,26 @@ export declare class UptimeKumaClient {
|
|
|
166
174
|
updateMonitor(monitorData: Record<string, unknown>): Promise<ApiResponse & {
|
|
167
175
|
monitorID?: number;
|
|
168
176
|
}>;
|
|
177
|
+
/**
|
|
178
|
+
* Fetch the tag catalog synchronously from the server. Uptime Kuma does
|
|
179
|
+
* not push `tagList` events — it only responds to the `getTags` request —
|
|
180
|
+
* so relying on the push-populated cache returns stale (often empty) data.
|
|
181
|
+
* This method also refreshes `tagListCache` so subsequent cache reads work.
|
|
182
|
+
*/
|
|
183
|
+
private fetchTagList;
|
|
184
|
+
/**
|
|
185
|
+
* Bind a tag to a monitor (socket: `addMonitorTag`).
|
|
186
|
+
*/
|
|
187
|
+
private addMonitorTag;
|
|
188
|
+
/**
|
|
189
|
+
* Unbind a tag from a monitor (socket: `deleteMonitorTag`).
|
|
190
|
+
*/
|
|
191
|
+
private deleteMonitorTag;
|
|
192
|
+
/**
|
|
193
|
+
* Reconcile a monitor's tags against the desired list. Auto-creates any
|
|
194
|
+
* tag name that isn't yet in the catalog. Tag identity is `(name, value)`.
|
|
195
|
+
*/
|
|
196
|
+
private reconcileMonitorTags;
|
|
169
197
|
/**
|
|
170
198
|
* Delete a monitor
|
|
171
199
|
*
|
|
@@ -195,13 +223,45 @@ export declare class UptimeKumaClient {
|
|
|
195
223
|
*/
|
|
196
224
|
deleteNotification(notificationID: number): Promise<ApiResponse>;
|
|
197
225
|
/**
|
|
198
|
-
* Get the cached
|
|
226
|
+
* Get the cached docker host list
|
|
227
|
+
*/
|
|
228
|
+
getDockerHostList(): DockerHost[];
|
|
229
|
+
/**
|
|
230
|
+
* Add or update a docker host
|
|
231
|
+
*
|
|
232
|
+
* @param dockerHost - Docker host configuration (name, dockerType, dockerDaemon)
|
|
233
|
+
* @param dockerHostID - If provided, updates existing; otherwise creates new
|
|
234
|
+
* @returns Promise resolving to the API response with the docker host id
|
|
235
|
+
*/
|
|
236
|
+
addDockerHost(dockerHost: Record<string, unknown>, dockerHostID?: number): Promise<ApiResponse & {
|
|
237
|
+
id?: number;
|
|
238
|
+
}>;
|
|
239
|
+
/**
|
|
240
|
+
* Delete a docker host. Any monitors referencing it will have their docker_host
|
|
241
|
+
* field cleared by Uptime Kuma.
|
|
242
|
+
*
|
|
243
|
+
* @param dockerHostID - The ID of the docker host to delete
|
|
244
|
+
* @returns Promise resolving to the API response
|
|
245
|
+
*/
|
|
246
|
+
deleteDockerHost(dockerHostID: number): Promise<ApiResponse>;
|
|
247
|
+
/**
|
|
248
|
+
* Test connectivity to a docker host without persisting it. Returns a friendly
|
|
249
|
+
* message containing the number of containers when reachable.
|
|
250
|
+
*
|
|
251
|
+
* @param dockerHost - Docker host configuration to test (name, dockerType, dockerDaemon)
|
|
252
|
+
* @returns Promise resolving to the API response
|
|
199
253
|
*/
|
|
200
|
-
|
|
254
|
+
testDockerHost(dockerHost: Record<string, unknown>): Promise<ApiResponse>;
|
|
255
|
+
/**
|
|
256
|
+
* Get the tag list. Actively fetches from the server since Uptime Kuma
|
|
257
|
+
* does not push `tagList` events on login (issue #46).
|
|
258
|
+
* Falls back to the cache if the socket is not connected.
|
|
259
|
+
*/
|
|
260
|
+
getTagList(): Promise<Array<{
|
|
201
261
|
id: number;
|
|
202
262
|
name: string;
|
|
203
263
|
color: string;
|
|
204
|
-
}
|
|
264
|
+
}>>;
|
|
205
265
|
/**
|
|
206
266
|
* Create a new tag
|
|
207
267
|
*
|
|
@@ -240,6 +300,48 @@ export declare class UptimeKumaClient {
|
|
|
240
300
|
* Get the cached status page list
|
|
241
301
|
*/
|
|
242
302
|
getStatusPageList(): StatusPage[];
|
|
303
|
+
/**
|
|
304
|
+
* Get full details of a single status page, including publicGroupList with monitors
|
|
305
|
+
* and any active incidents. Uses the public HTTP API (`/api/status-page/{slug}`),
|
|
306
|
+
* which returns the same data the status page UI renders — richer than the
|
|
307
|
+
* socket `getStatusPage` event, which only returns config.
|
|
308
|
+
*
|
|
309
|
+
* @param slug - The status page slug
|
|
310
|
+
* @returns Promise resolving to the status page config, groups, and incidents
|
|
311
|
+
*/
|
|
312
|
+
getStatusPage(slug: string): Promise<ApiResponse & {
|
|
313
|
+
config?: StatusPage;
|
|
314
|
+
publicGroupList?: unknown[];
|
|
315
|
+
incidents?: unknown[];
|
|
316
|
+
}>;
|
|
317
|
+
/**
|
|
318
|
+
* Create a new (empty) status page with the given title and slug
|
|
319
|
+
*
|
|
320
|
+
* Note: This creates a blank status page. Use updateStatusPage afterwards to
|
|
321
|
+
* set description, theme, groups, monitors, etc.
|
|
322
|
+
*
|
|
323
|
+
* @param title - Display title of the status page
|
|
324
|
+
* @param slug - URL slug (lowercase letters, digits, and dashes only)
|
|
325
|
+
* @returns Promise resolving to the API response
|
|
326
|
+
*/
|
|
327
|
+
createStatusPage(title: string, slug: string): Promise<ApiResponse>;
|
|
328
|
+
/**
|
|
329
|
+
* Update an existing status page's config and group/monitor list
|
|
330
|
+
*
|
|
331
|
+
* @param slug - The status page slug (immutable identifier)
|
|
332
|
+
* @param config - Status page configuration (title, description, theme, published, etc.)
|
|
333
|
+
* @param publicGroupList - Ordered groups, each with a name, weight, and monitorList `[{id}]`
|
|
334
|
+
* @param imgDataUrl - Optional icon as data URL (pass empty string to keep existing)
|
|
335
|
+
* @returns Promise resolving to the API response
|
|
336
|
+
*/
|
|
337
|
+
updateStatusPage(slug: string, config: Record<string, unknown>, publicGroupList?: Array<Record<string, unknown>>, imgDataUrl?: string): Promise<ApiResponse>;
|
|
338
|
+
/**
|
|
339
|
+
* Delete a status page
|
|
340
|
+
*
|
|
341
|
+
* @param slug - The status page slug
|
|
342
|
+
* @returns Promise resolving to the API response
|
|
343
|
+
*/
|
|
344
|
+
deleteStatusPage(slug: string): Promise<ApiResponse>;
|
|
243
345
|
/**
|
|
244
346
|
* Get the socket instance (for advanced usage)
|
|
245
347
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uptime-kuma-client.d.ts","sourceRoot":"","sources":["../src/uptime-kuma-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EAEV,2BAA2B,EAC3B,uBAAuB,EAGvB,WAAW,EACX,aAAa,EAEb,WAAW,EACX,cAAc,EACd,SAAS,EAET,mBAAmB,EAEnB,YAAY,EACZ,WAAW,EACX,UAAU,EACX,MAAM,kBAAkB,CAAC;AA2B1B;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,gBAAgB,CAA+C;IACvE,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,WAAW,CAAgE;IACnF,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,qBAAqB,CAAsC;IACnE,OAAO,CAAC,YAAY,CAA0D;IAC9E,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,mBAAmB,CAAsC;IACjE,OAAO,CAAC,MAAM,CAAC,CAA4F;IAC3G,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,gBAAgB,CAAkH;gBAGxI,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE;QAAE,kBAAkB,EAAE,CAAC,MAAM,EAAE;YAAE,KAAK,EAAE,YAAY,CAAC;YAAC,IAAI,EAAE,OAAO,CAAA;SAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,EAClG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO;IAO9C;;OAEG;YACW,OAAO;IAWrB;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BxB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAiCtB;;OAEG;IACH,UAAU,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"uptime-kuma-client.d.ts","sourceRoot":"","sources":["../src/uptime-kuma-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,6 +30,7 @@ export class UptimeKumaClient {
|
|
|
30
30
|
tagListCache = [];
|
|
31
31
|
maintenanceListCache = {};
|
|
32
32
|
statusPageListCache = {};
|
|
33
|
+
dockerHostListCache = [];
|
|
33
34
|
server;
|
|
34
35
|
shouldLog;
|
|
35
36
|
loginCredentials = null;
|
|
@@ -138,6 +139,7 @@ export class UptimeKumaClient {
|
|
|
138
139
|
this.socket.off('tagList');
|
|
139
140
|
this.socket.off('maintenanceList');
|
|
140
141
|
this.socket.off('statusPageList');
|
|
142
|
+
this.socket.off('dockerHostList');
|
|
141
143
|
this.socket.disconnect();
|
|
142
144
|
this.socket = null;
|
|
143
145
|
}
|
|
@@ -150,6 +152,7 @@ export class UptimeKumaClient {
|
|
|
150
152
|
this.tagListCache = [];
|
|
151
153
|
this.maintenanceListCache = {};
|
|
152
154
|
this.statusPageListCache = {};
|
|
155
|
+
this.dockerHostListCache = [];
|
|
153
156
|
}
|
|
154
157
|
/**
|
|
155
158
|
* Login using username and password, or JWT token
|
|
@@ -177,6 +180,7 @@ export class UptimeKumaClient {
|
|
|
177
180
|
this.setupTagListListeners();
|
|
178
181
|
this.setupMaintenanceListListeners();
|
|
179
182
|
this.setupStatusPageListListeners();
|
|
183
|
+
this.setupDockerHostListListeners();
|
|
180
184
|
// If JWT token is provided, use token-based authentication
|
|
181
185
|
if (jwtToken) {
|
|
182
186
|
this.socket.emit('loginByToken', jwtToken, (response) => {
|
|
@@ -611,8 +615,9 @@ export class UptimeKumaClient {
|
|
|
611
615
|
if (!this.socket)
|
|
612
616
|
return;
|
|
613
617
|
this.socket.on('tagList', (tagList) => {
|
|
614
|
-
|
|
615
|
-
this.
|
|
618
|
+
const tags = Array.isArray(tagList) ? tagList : Object.values(tagList);
|
|
619
|
+
this.safeLog('debug', `Received tagList with ${tags.length} tags`);
|
|
620
|
+
this.tagListCache = tags;
|
|
616
621
|
});
|
|
617
622
|
}
|
|
618
623
|
setupMaintenanceListListeners() {
|
|
@@ -631,53 +636,177 @@ export class UptimeKumaClient {
|
|
|
631
636
|
this.statusPageListCache = statusPageList;
|
|
632
637
|
});
|
|
633
638
|
}
|
|
639
|
+
setupDockerHostListListeners() {
|
|
640
|
+
if (!this.socket)
|
|
641
|
+
return;
|
|
642
|
+
this.socket.on('dockerHostList', (dockerHostList) => {
|
|
643
|
+
this.safeLog('debug', `Received dockerHostList with ${dockerHostList.length} docker hosts`);
|
|
644
|
+
this.dockerHostListCache = dockerHostList;
|
|
645
|
+
});
|
|
646
|
+
}
|
|
634
647
|
// ─── Monitor write operations ───────────────────────────────────────────────
|
|
635
648
|
/**
|
|
636
|
-
* Create a new monitor
|
|
649
|
+
* Create a new monitor. If `tags` are supplied, they are applied after
|
|
650
|
+
* creation using the separate `addMonitorTag` socket event — the `add`
|
|
651
|
+
* socket handler does not process tags.
|
|
637
652
|
*
|
|
638
653
|
* @param monitorData - Monitor configuration (type-specific fields should be included)
|
|
639
654
|
* @returns Promise resolving to the API response with the new monitorID
|
|
640
655
|
*/
|
|
641
|
-
createMonitor(monitorData) {
|
|
642
|
-
|
|
656
|
+
async createMonitor(monitorData) {
|
|
657
|
+
const { tags, ...payload } = monitorData;
|
|
658
|
+
const response = await new Promise((resolve, reject) => {
|
|
643
659
|
if (!this.socket || !this.socket.connected) {
|
|
644
660
|
reject(new Error('Not connected to server'));
|
|
645
661
|
return;
|
|
646
662
|
}
|
|
647
|
-
this.socket.emit('add',
|
|
648
|
-
if (
|
|
649
|
-
this.safeLog('info', `Successfully created monitor (ID: ${
|
|
650
|
-
resolve(
|
|
663
|
+
this.socket.emit('add', payload, (res) => {
|
|
664
|
+
if (res.ok) {
|
|
665
|
+
this.safeLog('info', `Successfully created monitor (ID: ${res.monitorID})`);
|
|
666
|
+
resolve(res);
|
|
651
667
|
}
|
|
652
668
|
else {
|
|
653
|
-
reject(new Error(
|
|
669
|
+
reject(new Error(res.msg || 'Failed to create monitor'));
|
|
654
670
|
}
|
|
655
671
|
});
|
|
656
672
|
});
|
|
673
|
+
if (tags && Array.isArray(tags) && response.monitorID != null) {
|
|
674
|
+
await this.reconcileMonitorTags(response.monitorID, tags);
|
|
675
|
+
}
|
|
676
|
+
return response;
|
|
657
677
|
}
|
|
658
678
|
/**
|
|
659
|
-
* Update an existing monitor
|
|
679
|
+
* Update an existing monitor. If `tags` are supplied, they are reconciled
|
|
680
|
+
* against the monitor's current tag set using `addMonitorTag` /
|
|
681
|
+
* `deleteMonitorTag` — the `editMonitor` socket handler does not process
|
|
682
|
+
* tags. Tags whose name is not yet in the catalog are auto-created via
|
|
683
|
+
* `addTag` before binding.
|
|
660
684
|
*
|
|
661
685
|
* @param monitorData - Monitor configuration including the id field
|
|
662
686
|
* @returns Promise resolving to the API response
|
|
663
687
|
*/
|
|
664
|
-
updateMonitor(monitorData) {
|
|
665
|
-
|
|
688
|
+
async updateMonitor(monitorData) {
|
|
689
|
+
const { tags, ...payload } = monitorData;
|
|
690
|
+
const response = await new Promise((resolve, reject) => {
|
|
666
691
|
if (!this.socket || !this.socket.connected) {
|
|
667
692
|
reject(new Error('Not connected to server'));
|
|
668
693
|
return;
|
|
669
694
|
}
|
|
670
|
-
this.socket.emit('editMonitor',
|
|
671
|
-
if (
|
|
695
|
+
this.socket.emit('editMonitor', payload, (res) => {
|
|
696
|
+
if (res.ok) {
|
|
672
697
|
this.safeLog('info', `Successfully updated monitor (ID: ${monitorData['id']})`);
|
|
673
|
-
resolve(
|
|
698
|
+
resolve(res);
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
reject(new Error(res.msg || 'Failed to update monitor'));
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
if (tags && Array.isArray(tags) && monitorData['id'] != null) {
|
|
706
|
+
await this.reconcileMonitorTags(Number(monitorData['id']), tags);
|
|
707
|
+
}
|
|
708
|
+
return response;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Fetch the tag catalog synchronously from the server. Uptime Kuma does
|
|
712
|
+
* not push `tagList` events — it only responds to the `getTags` request —
|
|
713
|
+
* so relying on the push-populated cache returns stale (often empty) data.
|
|
714
|
+
* This method also refreshes `tagListCache` so subsequent cache reads work.
|
|
715
|
+
*/
|
|
716
|
+
fetchTagList() {
|
|
717
|
+
return new Promise((resolve, reject) => {
|
|
718
|
+
if (!this.socket || !this.socket.connected) {
|
|
719
|
+
reject(new Error('Not connected to server'));
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
this.socket.emit('getTags', (res) => {
|
|
723
|
+
if (res.ok && res.tags) {
|
|
724
|
+
this.tagListCache = res.tags;
|
|
725
|
+
resolve(res.tags);
|
|
674
726
|
}
|
|
675
727
|
else {
|
|
676
|
-
reject(new Error(
|
|
728
|
+
reject(new Error(res.msg || 'Failed to fetch tag list'));
|
|
677
729
|
}
|
|
678
730
|
});
|
|
679
731
|
});
|
|
680
732
|
}
|
|
733
|
+
/**
|
|
734
|
+
* Bind a tag to a monitor (socket: `addMonitorTag`).
|
|
735
|
+
*/
|
|
736
|
+
addMonitorTag(tagID, monitorID, value) {
|
|
737
|
+
return new Promise((resolve, reject) => {
|
|
738
|
+
if (!this.socket || !this.socket.connected) {
|
|
739
|
+
reject(new Error('Not connected to server'));
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
this.socket.emit('addMonitorTag', tagID, monitorID, value, (res) => {
|
|
743
|
+
if (res.ok)
|
|
744
|
+
resolve(res);
|
|
745
|
+
else
|
|
746
|
+
reject(new Error(res.msg || `Failed to add tag ${tagID} to monitor ${monitorID}`));
|
|
747
|
+
});
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Unbind a tag from a monitor (socket: `deleteMonitorTag`).
|
|
752
|
+
*/
|
|
753
|
+
deleteMonitorTag(tagID, monitorID, value) {
|
|
754
|
+
return new Promise((resolve, reject) => {
|
|
755
|
+
if (!this.socket || !this.socket.connected) {
|
|
756
|
+
reject(new Error('Not connected to server'));
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
this.socket.emit('deleteMonitorTag', tagID, monitorID, value, (res) => {
|
|
760
|
+
if (res.ok)
|
|
761
|
+
resolve(res);
|
|
762
|
+
else
|
|
763
|
+
reject(new Error(res.msg || `Failed to remove tag ${tagID} from monitor ${monitorID}`));
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Reconcile a monitor's tags against the desired list. Auto-creates any
|
|
769
|
+
* tag name that isn't yet in the catalog. Tag identity is `(name, value)`.
|
|
770
|
+
*/
|
|
771
|
+
async reconcileMonitorTags(monitorID, desiredTags) {
|
|
772
|
+
const currentMonitor = this.monitorListCache[String(monitorID)];
|
|
773
|
+
const currentTags = (currentMonitor?.tags ?? []);
|
|
774
|
+
const key = (name, value) => `${name}\u0000${value ?? ''}`;
|
|
775
|
+
const currentKeys = new Set(currentTags.map((t) => key(t.name, t.value)));
|
|
776
|
+
const desiredKeys = new Set(desiredTags.map((t) => key(String(t.name), t.value)));
|
|
777
|
+
// Uptime Kuma never pushes `tagList` events, so the cache is unreliable
|
|
778
|
+
// — fetch the catalog synchronously via the `getTags` socket request.
|
|
779
|
+
const freshTags = await this.fetchTagList();
|
|
780
|
+
const nameToID = new Map();
|
|
781
|
+
for (const t of freshTags)
|
|
782
|
+
nameToID.set(t.name, t.id);
|
|
783
|
+
for (const desired of desiredTags) {
|
|
784
|
+
const name = String(desired.name);
|
|
785
|
+
const value = desired.value ?? '';
|
|
786
|
+
if (currentKeys.has(key(name, value)))
|
|
787
|
+
continue;
|
|
788
|
+
let tagID = nameToID.get(name);
|
|
789
|
+
if (tagID == null) {
|
|
790
|
+
const color = desired.color ?? '#808080';
|
|
791
|
+
const created = await this.addTag(name, color);
|
|
792
|
+
tagID = created.tag?.id;
|
|
793
|
+
if (tagID != null)
|
|
794
|
+
nameToID.set(name, tagID);
|
|
795
|
+
}
|
|
796
|
+
if (tagID == null) {
|
|
797
|
+
throw new Error(`Could not resolve tag ID for "${name}"`);
|
|
798
|
+
}
|
|
799
|
+
await this.addMonitorTag(tagID, monitorID, value);
|
|
800
|
+
}
|
|
801
|
+
for (const existing of currentTags) {
|
|
802
|
+
if (desiredKeys.has(key(existing.name, existing.value)))
|
|
803
|
+
continue;
|
|
804
|
+
const tagID = existing.tag_id ?? nameToID.get(existing.name);
|
|
805
|
+
if (tagID == null)
|
|
806
|
+
continue;
|
|
807
|
+
await this.deleteMonitorTag(tagID, monitorID, existing.value ?? '');
|
|
808
|
+
}
|
|
809
|
+
}
|
|
681
810
|
/**
|
|
682
811
|
* Delete a monitor
|
|
683
812
|
*
|
|
@@ -756,12 +885,96 @@ export class UptimeKumaClient {
|
|
|
756
885
|
});
|
|
757
886
|
});
|
|
758
887
|
}
|
|
888
|
+
// ─── Docker host operations ─────────────────────────────────────────────────
|
|
889
|
+
/**
|
|
890
|
+
* Get the cached docker host list
|
|
891
|
+
*/
|
|
892
|
+
getDockerHostList() {
|
|
893
|
+
return this.dockerHostListCache;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Add or update a docker host
|
|
897
|
+
*
|
|
898
|
+
* @param dockerHost - Docker host configuration (name, dockerType, dockerDaemon)
|
|
899
|
+
* @param dockerHostID - If provided, updates existing; otherwise creates new
|
|
900
|
+
* @returns Promise resolving to the API response with the docker host id
|
|
901
|
+
*/
|
|
902
|
+
addDockerHost(dockerHost, dockerHostID) {
|
|
903
|
+
return new Promise((resolve, reject) => {
|
|
904
|
+
if (!this.socket || !this.socket.connected) {
|
|
905
|
+
reject(new Error('Not connected to server'));
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
const id = dockerHostID ?? null;
|
|
909
|
+
this.socket.emit('addDockerHost', dockerHost, id, (response) => {
|
|
910
|
+
if (response.ok) {
|
|
911
|
+
this.safeLog('info', `Successfully saved docker host (ID: ${response.id})`);
|
|
912
|
+
resolve(response);
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
reject(new Error(response.msg || 'Failed to save docker host'));
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Delete a docker host. Any monitors referencing it will have their docker_host
|
|
922
|
+
* field cleared by Uptime Kuma.
|
|
923
|
+
*
|
|
924
|
+
* @param dockerHostID - The ID of the docker host to delete
|
|
925
|
+
* @returns Promise resolving to the API response
|
|
926
|
+
*/
|
|
927
|
+
deleteDockerHost(dockerHostID) {
|
|
928
|
+
return new Promise((resolve, reject) => {
|
|
929
|
+
if (!this.socket || !this.socket.connected) {
|
|
930
|
+
reject(new Error('Not connected to server'));
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
this.socket.emit('deleteDockerHost', dockerHostID, (response) => {
|
|
934
|
+
if (response.ok) {
|
|
935
|
+
this.safeLog('info', `Successfully deleted docker host ${dockerHostID}`);
|
|
936
|
+
resolve(response);
|
|
937
|
+
}
|
|
938
|
+
else {
|
|
939
|
+
reject(new Error(response.msg || 'Failed to delete docker host'));
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Test connectivity to a docker host without persisting it. Returns a friendly
|
|
946
|
+
* message containing the number of containers when reachable.
|
|
947
|
+
*
|
|
948
|
+
* @param dockerHost - Docker host configuration to test (name, dockerType, dockerDaemon)
|
|
949
|
+
* @returns Promise resolving to the API response
|
|
950
|
+
*/
|
|
951
|
+
testDockerHost(dockerHost) {
|
|
952
|
+
return new Promise((resolve, reject) => {
|
|
953
|
+
if (!this.socket || !this.socket.connected) {
|
|
954
|
+
reject(new Error('Not connected to server'));
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
this.socket.emit('testDockerHost', dockerHost, (response) => {
|
|
958
|
+
// Resolve either way so callers can inspect ok/msg without try/catch
|
|
959
|
+
// (matches the pattern used by UK's UI, which shows both success and
|
|
960
|
+
// failure messages from the same callback).
|
|
961
|
+
resolve(response);
|
|
962
|
+
});
|
|
963
|
+
});
|
|
964
|
+
}
|
|
759
965
|
// ─── Tag operations ─────────────────────────────────────────────────────────
|
|
760
966
|
/**
|
|
761
|
-
* Get the
|
|
967
|
+
* Get the tag list. Actively fetches from the server since Uptime Kuma
|
|
968
|
+
* does not push `tagList` events on login (issue #46).
|
|
969
|
+
* Falls back to the cache if the socket is not connected.
|
|
762
970
|
*/
|
|
763
|
-
getTagList() {
|
|
764
|
-
|
|
971
|
+
async getTagList() {
|
|
972
|
+
try {
|
|
973
|
+
return await this.fetchTagList();
|
|
974
|
+
}
|
|
975
|
+
catch {
|
|
976
|
+
return this.tagListCache;
|
|
977
|
+
}
|
|
765
978
|
}
|
|
766
979
|
/**
|
|
767
980
|
* Create a new tag
|
|
@@ -847,6 +1060,114 @@ export class UptimeKumaClient {
|
|
|
847
1060
|
getStatusPageList() {
|
|
848
1061
|
return Object.values(this.statusPageListCache);
|
|
849
1062
|
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Get full details of a single status page, including publicGroupList with monitors
|
|
1065
|
+
* and any active incidents. Uses the public HTTP API (`/api/status-page/{slug}`),
|
|
1066
|
+
* which returns the same data the status page UI renders — richer than the
|
|
1067
|
+
* socket `getStatusPage` event, which only returns config.
|
|
1068
|
+
*
|
|
1069
|
+
* @param slug - The status page slug
|
|
1070
|
+
* @returns Promise resolving to the status page config, groups, and incidents
|
|
1071
|
+
*/
|
|
1072
|
+
async getStatusPage(slug) {
|
|
1073
|
+
try {
|
|
1074
|
+
const baseUrl = this.url.replace(/\/$/, '');
|
|
1075
|
+
const res = await fetch(`${baseUrl}/api/status-page/${encodeURIComponent(slug)}`);
|
|
1076
|
+
if (res.status === 404) {
|
|
1077
|
+
return { ok: false, msg: `Status page ${slug} not found` };
|
|
1078
|
+
}
|
|
1079
|
+
if (!res.ok) {
|
|
1080
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
1081
|
+
}
|
|
1082
|
+
const data = await res.json();
|
|
1083
|
+
return {
|
|
1084
|
+
ok: true,
|
|
1085
|
+
config: data.config,
|
|
1086
|
+
publicGroupList: data.publicGroupList,
|
|
1087
|
+
incidents: data.incidents ?? [],
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
catch (error) {
|
|
1091
|
+
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
1092
|
+
throw new Error(`Failed to get status page ${slug}: ${msg}`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Create a new (empty) status page with the given title and slug
|
|
1097
|
+
*
|
|
1098
|
+
* Note: This creates a blank status page. Use updateStatusPage afterwards to
|
|
1099
|
+
* set description, theme, groups, monitors, etc.
|
|
1100
|
+
*
|
|
1101
|
+
* @param title - Display title of the status page
|
|
1102
|
+
* @param slug - URL slug (lowercase letters, digits, and dashes only)
|
|
1103
|
+
* @returns Promise resolving to the API response
|
|
1104
|
+
*/
|
|
1105
|
+
createStatusPage(title, slug) {
|
|
1106
|
+
return new Promise((resolve, reject) => {
|
|
1107
|
+
if (!this.socket || !this.socket.connected) {
|
|
1108
|
+
reject(new Error('Not connected to server'));
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
this.socket.emit('addStatusPage', title, slug, (response) => {
|
|
1112
|
+
if (response.ok) {
|
|
1113
|
+
this.safeLog('info', `Successfully created status page ${slug}`);
|
|
1114
|
+
resolve(response);
|
|
1115
|
+
}
|
|
1116
|
+
else {
|
|
1117
|
+
reject(new Error(response.msg || `Failed to create status page ${slug}`));
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Update an existing status page's config and group/monitor list
|
|
1124
|
+
*
|
|
1125
|
+
* @param slug - The status page slug (immutable identifier)
|
|
1126
|
+
* @param config - Status page configuration (title, description, theme, published, etc.)
|
|
1127
|
+
* @param publicGroupList - Ordered groups, each with a name, weight, and monitorList `[{id}]`
|
|
1128
|
+
* @param imgDataUrl - Optional icon as data URL (pass empty string to keep existing)
|
|
1129
|
+
* @returns Promise resolving to the API response
|
|
1130
|
+
*/
|
|
1131
|
+
updateStatusPage(slug, config, publicGroupList = [], imgDataUrl = '') {
|
|
1132
|
+
return new Promise((resolve, reject) => {
|
|
1133
|
+
if (!this.socket || !this.socket.connected) {
|
|
1134
|
+
reject(new Error('Not connected to server'));
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
this.socket.emit('saveStatusPage', slug, config, imgDataUrl, publicGroupList, (response) => {
|
|
1138
|
+
if (response.ok) {
|
|
1139
|
+
this.safeLog('info', `Successfully updated status page ${slug}`);
|
|
1140
|
+
resolve(response);
|
|
1141
|
+
}
|
|
1142
|
+
else {
|
|
1143
|
+
reject(new Error(response.msg || `Failed to update status page ${slug}`));
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Delete a status page
|
|
1150
|
+
*
|
|
1151
|
+
* @param slug - The status page slug
|
|
1152
|
+
* @returns Promise resolving to the API response
|
|
1153
|
+
*/
|
|
1154
|
+
deleteStatusPage(slug) {
|
|
1155
|
+
return new Promise((resolve, reject) => {
|
|
1156
|
+
if (!this.socket || !this.socket.connected) {
|
|
1157
|
+
reject(new Error('Not connected to server'));
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
this.socket.emit('deleteStatusPage', slug, (response) => {
|
|
1161
|
+
if (response.ok) {
|
|
1162
|
+
this.safeLog('info', `Successfully deleted status page ${slug}`);
|
|
1163
|
+
resolve(response);
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
reject(new Error(response.msg || `Failed to delete status page ${slug}`));
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
850
1171
|
// ─── Socket accessor ─────────────────────────────────────────────────────────
|
|
851
1172
|
/**
|
|
852
1173
|
* Get the socket instance (for advanced usage)
|