Uh oh!
There was an error while loading. Please reload this page.
feat(api/v2): ✨ Implement BuildTeam routes - #137
Open
kyanvde wants to merge 1 commit into
Open
Conversation
Adds the root section: the public team list, a single team by ID or slug, the two modpack projections, and an update scoped to the authenticated team that queues a website revalidation for the pages it just made stale. BuildTeamsController owns / and /:teamId, and that wildcard matches any top level path, so BuildTeamsModule is registered last and the ordering is pinned by tests, including one that the Swagger docs still resolve. The token and webhook columns are never selected into a public response; a team only reads back the webhook it configured itself. Closes#58 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nudelsuppe42
approved these changes
Aug 29, 2026
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 freeto 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.
Closes#58.
Routes
GET /GET /:teamId?slug=true,?members=true,?showcases=trueGET /modpackGET /:teamId/modpack?slug=truePUT /andPUT /:teamIdThe root wildcard
This section is the one that could break every other one.
GET /:teamIdmatches a single segment, so it matches/claims,/socials,/applications,/auth,/health,/versionand/docsjust as happily as a team ID. Express resolves that by registration order, which means:BuildTeamsModuleis registered last inAppModule, with a comment saying why.modpackis declared before:teamIdin the controller, and:teamIdis declared last of all.main.tswires it onto the HTTP adapter before the controller routes are registered.None of that is visible from the controller, so it is pinned by tests rather than left to a comment:
buildteams.routes.spec.tsasserts that/v2/claims,/v2/socials,/v2/health,/v2/version,/v2/authandPUT /v2/socialsstill reach their own controllers, and a newdocs-routes.spec.tsbuilds the app the waymain.tsdoes and asserts/v2/docs.jsonand/v2/docs.yamlstill answer the OpenAPI document instead of a 404 from a team lookup.Secrets
token(the client secret a team exchanges for an access token) andwebhookare never selected into a public response. They are left out of the select rather than deleted from the result afterwards, so a column added to the model later has to be listed on purpose before it becomes public — and there is a test asserting neither appears in the select.A team authenticated as itself does get its own
webhookback onGET /:teamIdand onPUT, since it needs to read back what it configured.tokenis not settable throughPUTat all; the request is rejected as an unknown field.Other notes
PUTqueuesREVALIDATE_WEBSITEfor the team pages, which is what v1 did inline viarerenderFrontend. When the slug changed, the pages under the old slug are revalidated too, or the team keeps being served under a URL that no longer resolves.P2002is caught in the service; unrelated database errors are re-thrown untouched.slugis validated against^[a-z0-9]+(?:-[a-z0-9]+)*$— it becomes a public URL segment./modpackis an unpaginated map keyed by team ID, matching v1, because the modpack loads it once at startup and looks teams up by ID.ipis stored as one semicolon-separated string and served as a list, also matching v1.sortBy=membersis mapped to it explicitly.Testing
yarn ws api-v2 test— 33 suites, 282 tests, all passing. 50 are new:buildteams.service.spec.ts— sorting (including the relation count), pagination, slug resolution, the optional embeds, webhook visibility in both directions, the modpack projections, the 409 on a taken slug, and that revalidation covers the old slug after a rename.buildteams.routes.spec.ts— the wildcard collision cases above, plus the:teamIdprefix rejecting another team,tokenbeing refused in a body, and an invalid slug being refused.docs-routes.spec.ts— the Swagger routes.yarn ws api-v2 buildpasses.yarn ws api-v2 lintreports the 6 pre-existingunbound-methoderrors documented in CLAUDE.md and nothing new.🤖 Generated with Claude Code