feat(backend): add GET /api/bootstrap route + test
- Returns productId, displayName, backendPort for client bootstrapping - Integration test validates response shape and types
This commit is contained in:
parent
fd4d35b308
commit
f7356706cd
@ -4,7 +4,7 @@ import type { FastifyInstance } from 'fastify';
|
|||||||
import { getAllFlags } from './lib/feature-flags.js';
|
import { getAllFlags } from './lib/feature-flags.js';
|
||||||
import { getBufferedEvents, flushEvents } from './lib/telemetry.js';
|
import { getBufferedEvents, flushEvents } from './lib/telemetry.js';
|
||||||
import { config } from './lib/config.js';
|
import { config } from './lib/config.js';
|
||||||
import { PRODUCT_ID } from './lib/product-config.js';
|
import { PRODUCT_ID, productConfig } from './lib/product-config.js';
|
||||||
|
|
||||||
let app: FastifyInstance;
|
let app: FastifyInstance;
|
||||||
|
|
||||||
@ -29,6 +29,11 @@ beforeAll(async () => {
|
|||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
requestId: req.id,
|
requestId: req.id,
|
||||||
}));
|
}));
|
||||||
|
app.get('/api/bootstrap', async () => ({
|
||||||
|
productId: productConfig.productId,
|
||||||
|
displayName: productConfig.displayName,
|
||||||
|
backendPort: config.PORT,
|
||||||
|
}));
|
||||||
await app.ready();
|
await app.ready();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,4 +89,16 @@ describe('diagnostics routes', () => {
|
|||||||
expect(body).toHaveProperty('timestamp');
|
expect(body).toHaveProperty('timestamp');
|
||||||
expect(body.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
expect(body.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('GET /api/bootstrap returns product identity', async () => {
|
||||||
|
const res = await app.inject({ method: 'GET', url: '/api/bootstrap' });
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
const body = res.json();
|
||||||
|
expect(body).toHaveProperty('productId');
|
||||||
|
expect(body).toHaveProperty('displayName');
|
||||||
|
expect(body).toHaveProperty('backendPort');
|
||||||
|
expect(typeof body.productId).toBe('string');
|
||||||
|
expect(typeof body.displayName).toBe('string');
|
||||||
|
expect(typeof body.backendPort).toBe('number');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { initDatastore } from './lib/datastore.js';
|
|||||||
import { config } from './lib/config.js';
|
import { config } from './lib/config.js';
|
||||||
import { getAllFlags } from './lib/feature-flags.js';
|
import { getAllFlags } from './lib/feature-flags.js';
|
||||||
import { getBufferedEvents, flushEvents } from './lib/telemetry.js';
|
import { getBufferedEvents, flushEvents } from './lib/telemetry.js';
|
||||||
import { PRODUCT_ID } from './lib/product-config.js';
|
import { PRODUCT_ID, productConfig } from './lib/product-config.js';
|
||||||
|
|
||||||
import { jwtVerify } from 'jose';
|
import { jwtVerify } from 'jose';
|
||||||
import type { JwtPayload } from './lib/request-context.js';
|
import type { JwtPayload } from './lib/request-context.js';
|
||||||
@ -53,6 +53,13 @@ await app.register(householdRoutes, { prefix: '/api' });
|
|||||||
await app.register(sharedTimerRoutes, { prefix: '/api' });
|
await app.register(sharedTimerRoutes, { prefix: '/api' });
|
||||||
await app.register(webhookRoutes, { prefix: '/api' });
|
await app.register(webhookRoutes, { prefix: '/api' });
|
||||||
|
|
||||||
|
// ── Bootstrap (no auth) ──────────────────────────────────────────
|
||||||
|
app.get('/api/bootstrap', async () => ({
|
||||||
|
productId: productConfig.productId,
|
||||||
|
displayName: productConfig.displayName,
|
||||||
|
backendPort: config.PORT,
|
||||||
|
}));
|
||||||
|
|
||||||
// ── Diagnostics routes (no auth) ────────────────────────────────
|
// ── Diagnostics routes (no auth) ────────────────────────────────
|
||||||
app.get('/api/diagnostics/flags', async () => getAllFlags());
|
app.get('/api/diagnostics/flags', async () => getAllFlags());
|
||||||
app.get('/api/diagnostics/telemetry', async () => ({ events: getBufferedEvents() }));
|
app.get('/api/diagnostics/telemetry', async () => ({ events: getBufferedEvents() }));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user