real featured inventions

This commit is contained in:
Devin Zuczek
2026-08-05 15:30:50 -04:00
parent 1f615bab4f
commit ae3bef4cc4
3 changed files with 23 additions and 11 deletions
+7 -3
View File
@@ -377,8 +377,13 @@ export async function getTopInventions(
/** /**
* The featured feed — published inventions flagged `IsFeatured`, newest first. * The featured feed — published inventions flagged `IsFeatured`, newest first.
* Selected on the indexed `is_featured` column rather than by parsing every public * Selected on the indexed `is_featured` column rather than by parsing every public
* invention. Nothing sets that flag yet, so this falls back to the top feed rather * invention.
* than handing the client an empty shelf; once inventions are curated it serves them. *
* Curated means curated: when nothing is flagged this serves an EMPTY list rather than
* standing in the top feed. It used to fall back, from when no invention could be
* featured at all, but a fallback makes the shelf lie — the client labels these as
* hand-picked, and a feed that silently becomes "top today" hides the fact that nobody
* has picked anything.
*/ */
export async function getFeaturedInventions( export async function getFeaturedInventions(
db: D1Database, db: D1Database,
@@ -386,7 +391,6 @@ export async function getFeaturedInventions(
take: number take: number
): Promise<SavedInvention[]> { ): Promise<SavedInvention[]> {
const featured = await publicInventions(db, true) const featured = await publicInventions(db, true)
if (featured.length === 0) return getTopInventions(db, skip, take)
return featured return featured
.sort((a, b) => b.CreatedAt.localeCompare(a.CreatedAt) || b.InventionId - a.InventionId) .sort((a, b) => b.CreatedAt.localeCompare(a.CreatedAt) || b.InventionId - a.InventionId)
.slice(skip, skip + take) .slice(skip, skip + take)
+5 -4
View File
@@ -643,16 +643,17 @@ export const avatarRoutes = new Hono<App>({ strict: false })
} }
) )
// The featured invention feed — curated (`IsFeatured`) inventions, falling back // The featured invention feed — the curated (`IsFeatured`) inventions and nothing
// to the top feed while nothing is curated. Bare array, like toptoday. // else, newest first. Empty until someone flags one. Bare array, like toptoday.
.get( .get(
'/api/inventions/v1/featured', '/api/inventions/v1/featured',
describeRoute({ describeRoute({
tags: ['Inventions'], tags: ['Inventions'],
summary: 'The featured feed', summary: 'The featured feed',
description: description:
'Curated (`IsFeatured`) inventions, falling back to the top feed while nothing is ' + 'Curated (`IsFeatured`) inventions, newest first — published and non-hidden only. ' +
'curated — so this is never empty just because no one has picked favourites.', 'Serves an empty list while nothing is flagged rather than standing in the top ' +
'feed: the client presents these as hand-picked, so a fallback would be a lie.',
parameters: pageParams(50), parameters: pageParams(50),
responses: { 200: json(InventionDto.array(), 'The featured inventions') }, responses: { 200: json(InventionDto.array(), 'The featured inventions') },
}), }),
+11 -4
View File
@@ -1138,12 +1138,14 @@ describe('public endpoints', () => {
const ids = async (res: Response): Promise<number[]> => const ids = async (res: Response): Promise<number[]> =>
((await res.json()) as SavedInvention[]).map((i) => i.InventionId) ((await res.json()) as SavedInvention[]).map((i) => i.InventionId)
// Nothing is flagged IsFeatured yet featured falls back to the top feed. // Nothing is flagged IsFeatured yet, so featured is EMPTY — it does not stand in the
// top feed, which by now has published inventions in it.
const beforeTop = await ids(await exports.default.fetch(`${ORIGIN}/api/inventions/v1/toptoday`)) const beforeTop = await ids(await exports.default.fetch(`${ORIGIN}/api/inventions/v1/toptoday`))
expect(beforeTop.length).toBeGreaterThan(0)
const beforeFeatured = await ids( const beforeFeatured = await ids(
await exports.default.fetch(`${ORIGIN}/api/inventions/v1/featured`) await exports.default.fetch(`${ORIGIN}/api/inventions/v1/featured`)
) )
expect(beforeFeatured).toEqual(beforeTop) expect(beforeFeatured).toEqual([])
const feedInvention = ( const feedInvention = (
id: number, id: number,
@@ -1187,13 +1189,18 @@ describe('public endpoints', () => {
expect(top).not.toContain(204) expect(top).not.toContain(204)
expect(top).not.toContain(205) expect(top).not.toContain(205)
// Featured: only the flagged, visible inventions — newest first. // Featured: only the flagged, visible inventions — newest first. 201 is published but
// unflagged, so it stays out however popular it is.
const featured = await ids(await exports.default.fetch(`${ORIGIN}/api/inventions/v1/featured`)) const featured = await ids(await exports.default.fetch(`${ORIGIN}/api/inventions/v1/featured`))
expect(featured).toEqual([203, 202]) expect(featured).toEqual([203, 202])
// skip/take paginate the top feed. // skip/take paginate both feeds.
const page = await exports.default.fetch(`${ORIGIN}/api/inventions/v1/toptoday?skip=1&take=1`) const page = await exports.default.fetch(`${ORIGIN}/api/inventions/v1/toptoday?skip=1&take=1`)
expect(await ids(page)).toEqual([203]) expect(await ids(page)).toEqual([203])
const featuredPage = await exports.default.fetch(
`${ORIGIN}/api/inventions/v1/featured?skip=1&take=1`
)
expect(await ids(featuredPage)).toEqual([202])
}) })
test('POST /api/sanitize/v1 echoes the value; isPure reports true', async () => { test('POST /api/sanitize/v1 echoes the value; isPure reports true', async () => {