Public: anyone can read this; the crew can change it.

A repository's label routes leave api.ts for src/http/api/labels.ts #6931

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/forge:mason/6303-a-repository-s-label-routes-leave-api-ts → main 1 commit fork

  • Merged. mason/6303-a-repository-s-label-routes-leave-api-ts was merged into main as 7da6393.

Review

Sign in to review this change.
2 files changed +52 −37
src/http/api.ts +2 −37
@@ -168,10 +168,8 @@ import { search, searchWithin } from "../actions/search.ts";
168168 import { runRepos } from "./run_gate.ts";
169169 import {
170170 commitToBranch,
171 createLabel,
172171 createRepo,
173172 createWebhook,
174 deleteLabel,
175173 deleteRepo,
176174 deleteWebhook,
177175 FORKS_PER_DAY,
@@ -208,7 +206,6 @@ import {
208206 labelsForIssues,
209207 listComments,
210208 listIssues,
211 listLabels,
212209 LIST_LIMIT,
213210 LIST_LIMIT_MAX,
214211 pageLimit,
@@ -454,6 +451,7 @@ import { frontInput, frontJson, setFront } from "../actions/front.ts";
454451 import { COPIES_PER_DAY, makeItYours } from "../actions/make_it_yours.ts";
455452 import { passportRoutes } from "./passport_edge.ts";
456453 import { egressGrantRoutes } from "./api/egress_grants.ts";
454 import { labelsRoutes } from "./api/labels.ts";
457455 import { secretRoutes } from "./api/secrets.ts";
458456 import type { Router } from "./router.ts";
459457 import { clientAddress, clientBucket } from "./peer.ts";
@@ -3174,40 +3172,7 @@ export function apiRoutes(router: Router<Handler>): void {
31743172
31753173 // ── labels ───────────────────────────────────────────────────────────
31763174
3177 router.add("GET", "/api/v1/repos/:owner/:name/labels", (ctx) => {
3178 notePhase(ctx.request, "session", takeSessionTime(ctx.request));
3179 const repo = loadRepo(ctx);
3180 if (!repo) return notFound();
3181 const labels = timePhase(ctx.request, "labels", () => listLabels(ctx.app.db, repo.id));
3182 return timePhase(ctx.request, "render", () => json(labels));
3183 });
3184
3185 router.add("POST", "/api/v1/repos/:owner/:name/labels", async (ctx) => {
3186 const denied = requireScope(ctx, "admin");
3187 if (denied) return denied;
3188 const repo = loadRepo(ctx);
3189 if (!repo) return notFound();
3190 const input = await body(ctx.request);
3191 const created = createLabel(
3192 ctx.app,
3193 ctx.auth.user,
3194 repo,
3195 str(input.name),
3196 str(input.color) || "6b7280",
3197 );
3198 if (!created.ok) return respondAccess(created.error, 422);
3199 return json(created.value, 201);
3200 });
3201
3202 router.add("DELETE", "/api/v1/repos/:owner/:name/labels/:id", (ctx) => {
3203 const denied = requireScope(ctx, "admin");
3204 if (denied) return denied;
3205 const repo = loadRepo(ctx);
3206 if (!repo) return notFound();
3207 const removed = deleteLabel(ctx.app, ctx.auth.user, repo, ctx.params.id!);
3208 if (!removed.ok) return respondAccess(removed.error, 422);
3209 return new Response(null, { status: 204 });
3210 });
3175 labelsRoutes(router);
32113176
32123177 // Replace the label set of an issue or a pull — both live in one table, so
32133178 // either number works here. Names or ids; an unknown label rejects the set.
src/http/api/labels.ts added +50
@@ -0,0 +1,50 @@
1 /**
2 * A repository's labels over the API: `GET` and `POST`
3 * `/api/v1/repos/:owner/:name/labels`, and `DELETE` `…/labels/:id`. Moved
4 * out of `api.ts` (#6303); the rules live in `actions/repos.ts`.
5 */
6
7 import { createLabel, deleteLabel } from "../../actions/repos.ts";
8 import { listLabels } from "../../core/issues.ts";
9 import { notePhase, takeSessionTime, timePhase } from "../../core/route_timing.ts";
10 import { loadRepo } from "../api.ts";
11 import type { Handler } from "../context.ts";
12 import { body, json, notFound, requireScope, respondAccess, str } from "../respond.ts";
13 import type { Router } from "../router.ts";
14
15 export function labelsRoutes(router: Router<Handler>): void {
16 router.add("GET", "/api/v1/repos/:owner/:name/labels", (ctx) => {
17 notePhase(ctx.request, "session", takeSessionTime(ctx.request));
18 const repo = loadRepo(ctx);
19 if (!repo) return notFound();
20 const labels = timePhase(ctx.request, "labels", () => listLabels(ctx.app.db, repo.id));
21 return timePhase(ctx.request, "render", () => json(labels));
22 });
23
24 router.add("POST", "/api/v1/repos/:owner/:name/labels", async (ctx) => {
25 const denied = requireScope(ctx, "admin");
26 if (denied) return denied;
27 const repo = loadRepo(ctx);
28 if (!repo) return notFound();
29 const input = await body(ctx.request);
30 const created = createLabel(
31 ctx.app,
32 ctx.auth.user,
33 repo,
34 str(input.name),
35 str(input.color) || "6b7280",
36 );
37 if (!created.ok) return respondAccess(created.error, 422);
38 return json(created.value, 201);
39 });
40
41 router.add("DELETE", "/api/v1/repos/:owner/:name/labels/:id", (ctx) => {
42 const denied = requireScope(ctx, "admin");
43 if (denied) return denied;
44 const repo = loadRepo(ctx);
45 if (!repo) return notFound();
46 const removed = deleteLabel(ctx.app, ctx.auth.user, repo, ctx.params.id!);
47 if (!removed.ok) return respondAccess(removed.error, 422);
48 return new Response(null, { status: 204 });
49 });
50 }

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs