← back to build-pages
api/recent: ?since= filter (24h|7d|YYYY-MM-DD) + 2 smoke
d96574185574c140944043beb3daf0edb9e65a0b · 2026-05-13 18:30:14 -0700 · SteveStudio2
Files touched
M server.jsM test/smoke.js
Diff
commit d96574185574c140944043beb3daf0edb9e65a0b
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 18:30:14 2026 -0700
api/recent: ?since= filter (24h|7d|YYYY-MM-DD) + 2 smoke
---
server.js | 29 ++++++++++++++++++++++++-----
test/smoke.js | 5 ++++-
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/server.js b/server.js
index 2976059..0177fc5 100644
--- a/server.js
+++ b/server.js
@@ -770,14 +770,28 @@ for (const facet of ['agents', 'skills']) {
// cache so it's free after the first warm.
app.get('/api/recent', async (req, res, next) => {
const limit = Math.min(Math.max(parseInt(req.query.limit, 10) || 20, 1), 200);
+ // Optional ?since=YYYY-MM-DD or ?since=1d|7d|24h date filter — anything older
+ // than the cutoff is dropped before the merge. Lets you slice "what shipped
+ // since last Monday" without paginating through everything.
+ let sinceMs = 0;
+ if (typeof req.query.since === 'string' && req.query.since.length) {
+ const s = req.query.since;
+ const rel = s.match(/^(\d+)([dhm])$/);
+ if (rel) {
+ const [, n, u] = rel;
+ const mult = u === 'd' ? 86400000 : u === 'h' ? 3600000 : 60000;
+ sinceMs = Date.now() - parseInt(n, 10) * mult;
+ } else if (/^\d{4}-\d{2}-\d{2}/.test(s)) {
+ sinceMs = new Date(s).getTime();
+ }
+ }
try {
const all = [];
for (const [slug, p] of Object.entries(PROJECTS)) {
const bundle = await getProjectBundle(slug, p).catch(() => null);
if (!bundle) continue;
- // Each project's commits are already date-desc; take the leading slice
- // up to `limit`. Final merge will sort the union back into date order.
- for (const c of bundle.commits.slice(0, limit)) {
+ for (const c of bundle.commits.slice(0, limit * 4)) {
+ if (sinceMs && new Date(c.dateISO).getTime() < sinceMs) break;
all.push({
slug, project: p.name,
hash: c.shortHash, date: c.dateISO, subject: c.subject,
@@ -786,7 +800,12 @@ app.get('/api/recent', async (req, res, next) => {
}
all.sort((a, b) => (b.date < a.date ? -1 : b.date > a.date ? 1 : 0));
res.setHeader('Cache-Control', 'public, max-age=30, stale-while-revalidate=60');
- res.json({ total: all.length, limit, results: all.slice(0, limit) });
+ res.json({
+ total: all.length,
+ limit,
+ since: sinceMs ? new Date(sinceMs).toISOString() : null,
+ results: all.slice(0, limit),
+ });
} catch (e) { next(e); }
});
@@ -988,7 +1007,7 @@ app.get('/api', (_req, res) => {
'GET /api/projects/:slug/skills': 'Raw skills facet — /skill-name slugs auto-extracted from commit bodies',
'GET /api/projects/:slug/ideas': 'Raw ideas — commit bodies ≥120 chars (design-rationale + scaffolds)',
'GET /api/search': 'Cross-project commit search — ?q=<term>&limit=N, round-robin + by_project breakdown',
- 'GET /api/recent': 'Most recent N commits across the whole fleet — date-sorted, ?limit=20',
+ 'GET /api/recent': 'Most recent N commits across the whole fleet — date-sorted, ?limit=20&since=<24h|7d|YYYY-MM-DD>',
'GET /api/fleet/agents': 'Fleet-wide agent tallies merged across every project',
'GET /api/fleet/skills': 'Fleet-wide skill tallies merged across every project',
'GET /api/fleet/velocity': 'Commits-per-rolling-window across the fleet — last 24h + last 7d, with per-project breakdown',
diff --git a/test/smoke.js b/test/smoke.js
index cfd7b5a..ba3435c 100644
--- a/test/smoke.js
+++ b/test/smoke.js
@@ -203,11 +203,14 @@ function check(name, cond, hint = '') {
check('404: branded HTML', /build-pages/.test(r.body));
check('404: back-link', /back to all projects/.test(r.body));
- // 13b. /api/recent — fleet-wide recent commits
+ // 13b. /api/recent — fleet-wide recent commits, with ?since= filter
r = await fetch('/api/recent?limit=5');
check('recent: 200', r.status === 200);
check('recent: results array', /"results":\[/.test(r.body));
check('recent: hash field', /"hash":"[a-f0-9]{4,}/.test(r.body));
+ r = await fetch('/api/recent?since=24h&limit=200');
+ check('recent ?since=24h: 200', r.status === 200);
+ check('recent ?since=24h: filter', /"since":"[\d-]+T/.test(r.body));
// 13b2. fleet-wide facet endpoints (agents + skills)
for (const f of ['agents', 'skills']) {
← 552db5e home: color-coded host load badge (green <8, yellow <20, red
·
back to build-pages
·
refactor: parseSince() helper — apply ?since= filter to /api 4a5298c →