feat(health): expose external in /services payload and accept on add/edit
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ router.get('/services', asyncWrap(async (_req, res) => {
|
|||||||
const list = g.services.map(s => {
|
const list = g.services.map(s => {
|
||||||
const st = statuses[s.id];
|
const st = statuses[s.id];
|
||||||
return {
|
return {
|
||||||
id: s.id, name: s.name, host: s.host, url: s.url, icon: iconSlug(s),
|
id: s.id, name: s.name, host: s.host, url: s.url, external: s.external ?? null, icon: iconSlug(s),
|
||||||
status: st?.status || 'unknown', latency_ms: st?.latency_ms ?? null,
|
status: st?.status || 'unknown', latency_ms: st?.latency_ms ?? null,
|
||||||
detail: st?.detail || null, checked_at: st?.checked_at || null
|
detail: st?.detail || null, checked_at: st?.checked_at || null
|
||||||
};
|
};
|
||||||
@@ -39,6 +39,7 @@ const svcBody = z.object({
|
|||||||
category: z.enum(['agents', 'infrastructure', 'media', 'other']).default('other'),
|
category: z.enum(['agents', 'infrastructure', 'media', 'other']).default('other'),
|
||||||
host: z.string().max(120).optional(),
|
host: z.string().max(120).optional(),
|
||||||
url: z.string().url(),
|
url: z.string().url(),
|
||||||
|
external: z.string().url().optional(),
|
||||||
icon: z.string().max(64).optional(),
|
icon: z.string().max(64).optional(),
|
||||||
check: checkCfg.optional()
|
check: checkCfg.optional()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,6 +28,18 @@ describe('health api (DB-backed registry)', () => {
|
|||||||
expect(infra.services.find(s => s.id === 'gitea').status).toBe('ok');
|
expect(infra.services.find(s => s.id === 'gitea').status).toBe('ok');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('GET /services includes external on every tile; POST round-trips it', async () => {
|
||||||
|
const res = await request(app).get('/api/health/services').set(ownerHeaders);
|
||||||
|
const all = res.body.flatMap(g => g.services);
|
||||||
|
expect(all.every(s => 'external' in s)).toBe(true); // key present (may be null)
|
||||||
|
expect(all.find(s => s.id === 'gitea').external).toBeNull(); // no domain set
|
||||||
|
await request(app).post('/api/health/services').set(ownerHeaders)
|
||||||
|
.send({ id: 'gramps', name: 'Gramps', category: 'infrastructure', url: 'http://192.168.1.99', external: 'https://gramps.hynesy.com' });
|
||||||
|
const res2 = await request(app).get('/api/health/services').set(ownerHeaders);
|
||||||
|
const gramps = res2.body.flatMap(g => g.services).find(s => s.id === 'gramps');
|
||||||
|
expect(gramps.external).toBe('https://gramps.hynesy.com');
|
||||||
|
});
|
||||||
|
|
||||||
it('POST /services adds a service that shows up in the band', async () => {
|
it('POST /services adds a service that shows up in the band', async () => {
|
||||||
const create = await request(app).post('/api/health/services').set(ownerHeaders)
|
const create = await request(app).post('/api/health/services').set(ownerHeaders)
|
||||||
.send({ id: 'ollama', name: 'Ollama', category: 'agents', host: 'ct102', url: 'http://192.168.1.185:11434' });
|
.send({ id: 'ollama', name: 'Ollama', category: 'agents', host: 'ct102', url: 'http://192.168.1.185:11434' });
|
||||||
|
|||||||
Reference in New Issue
Block a user