buildHandler function
Build the Shelf Handler for projectRoot. Pulled out of the
serve command so tests can drive it without binding a real port.
Implementation
Handler buildHandler(String projectRoot) {
final router = Router();
router.get('/api/config', (Request _) {
final project = _loadOrFail(projectRoot);
return configHandler(project);
});
router.get('/api/glossary', (Request _) {
final project = _loadOrFail(projectRoot);
return glossaryHandler(project);
});
router.get('/api/status', (Request _) {
final project = _loadOrFail(projectRoot);
return statusHandler(project);
});
router.get('/api/strings', (Request req) {
final project = _loadOrFail(projectRoot);
return stringsListHandler(project, req);
});
router.put('/api/strings/<key>', (Request req, String key) async {
final project = _loadOrFail(projectRoot);
return stringsPutHandler(project, req, key);
});
// Unknown /api/* paths return JSON 404 rather than falling through
// to the SPA handler (which would happily serve HTML).
router.all('/api/<rest|.*>', (Request _) {
return Response.notFound(
jsonEncode({'error': 'No such API endpoint.'}),
headers: const {'content-type': 'application/json; charset=utf-8'},
);
});
// Static assets — index.html + bundled JS/CSS — fall through to the
// SPA handler. Anything outside /api/* gets served from the embedded
// bundle; unknown paths return index.html so client-side routing
// works ("/strings", "/glossary", …).
router.all('/<rest|.*>', _staticAssetHandler);
return const Pipeline()
.addMiddleware(_corsHeaders())
.addMiddleware(_errorAsJson())
.addHandler(router.call);
}