Session 14: Africa checkout, Tank01 NBA/MLB wiring, WNBA+MLB odds proxies, OAuth icons, loading skeletons (1330 tests)

This commit is contained in:
Kev
2026-06-11 10:06:49 -04:00
parent 10159209fa
commit f5d79cf70d
22 changed files with 979 additions and 27 deletions
+33
View File
@@ -108,6 +108,39 @@ router.get('/nba', async (req, res) => {
}
});
// Session 14 — WNBA + MLB. Same pattern as /nba: validate query,
// fetch via cached oddsService, project to the {sport, props}
// envelope the Slate consumes. odds-api may return empty during
// off-season; we still return 200 with an empty `props` array so
// the Slate can render its empty-state UX.
function buildSportRoute(sport) {
return async (req, res) => {
const errors = validateQueryParams(req.query);
if (errors.length > 0) {
return res.status(400).json({ error: errors.join('; ') });
}
try {
const result = await getOdds(sport);
const filtered = filterProps(result.props || [], req.query);
const props = groupProps(filtered);
if (result.stale) res.set('X-VYNDR-Stale', 'true');
return res.json({
sport,
updated_at: result.updated_at,
source: result.source,
quota_remaining: result.quota_remaining,
props,
});
} catch (err) {
const status = err.statusCode || 500;
return res.status(status).json({ error: err.message });
}
};
}
router.get('/wnba', buildSportRoute('wnba'));
router.get('/mlb', buildSportRoute('mlb'));
router.get('/ncaab', async (req, res) => {
if (!isNcaabSeason()) {
return res.json({