Add public read endpoints to the extensions v2 API - #157
Merged
Conversation
v2 previously only covered submission/moderation/ownership; browsing
extensions and developers still meant using v1's API and shape. Adds
GET /extensions (list, filterable by type/developer_id), GET
/extensions/{id}, and GET /developers/{id}, all public/unauthenticated
to match v1's open CORS policy.
Designed for v2 rather than mirroring v1: extensions embed the full
public developer profile (bio/avatar_url/URL/approved) inline instead
of v1's stripped-down author shape, and contact_email is explicitly
excluded from every public response via a dedicated PublicDeveloper
type. v1's badge/version endpoints aren't replicated here since
they're display utilities with external README links, unrelated to the
author/developer shape gap this closes.
Claude-Session: https://claude.ai/code/session_01Co1bu2gU5kEHN65KooNUHN
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
api | 0aa3386 | Commit Preview URL Branch Preview URL |
Jul 26 2026, 07:08 PM |
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 6 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…liding ids, dedupe release sorting
- extensions-database.ts: COALESCE(d.id, e.author_id) so a missing
developer row (author_id isn't a hard FK) can never surface a null
developer.id, which would violate the Extension schema's contract.
- interfaces.ts: reject "claims"/"unapproved" as developer ids — those
are the only single-segment GET /developers/* static routes, and
since GET /developers/{id} is registered after them, a developer
literally named one of those words would always be shadowed by the
moderation-only route instead of getting a usable public profile.
- Extract sortReleasesDescending into lib/releases.ts, shared by v1 and
v2 instead of duplicated, and fix it to partition out non-semver tags
before sorting rather than comparing them inline — the old try/catch
comparator could report a tag as "equal" to two neighbors that
weren't equal to each other, which breaks Array#sort's assumption of
a total order and can leave later valid releases out of place.
Claude-Session: https://claude.ai/code/session_01Co1bu2gU5kEHN65KooNUHN
Contributor
There was a problem hiding this comment.
0 issues found across 6 files (changes from recent commits).
Auto-approved: Adds public read endpoints matching v1 exposure, with a fix to release sorting; all read-only, no schema changes, and contact_email stripped. Implementation reviewed.
Re-trigger cubic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /extensions/v2/extensions(list, filterable bytypeanddeveloper_id),GET /extensions/v2/extensions/{id}, andGET /extensions/v2/developers/{id}— all public/unauthenticated, closing the gap that previously forced callers who wanted browsing/read access to keep using v1.contact_emailis deliberately excluded from every public response via a dedicatedPublicDeveloperSchema/toPublicDeveloper()— not just an OpenAPI-doc distinction, actually stripped at the response boundary.