1/** The compatibility endpoint delegates to the same application write operation. */
2import * as Git from "alchemy/Git";
3import * as Effect from "effect/Effect";
4import * as Schema from "effect/Schema";
5import * as HttpRouter from "effect/http/HttpRouter";
6import * as HttpApiBuilder from "effect/http-api/HttpApiBuilder";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8import { AppApi } from "./api.ts";
9import { mergePull } from "./ref-writes.ts";
10
11const MergeBody = Schema.Struct({
12 commit_message: Schema.optional(Schema.String),
13 sha: Schema.optional(Schema.String),
14 merge_method: Schema.optional(Schema.String),
15});
16
17export const GitHubLive = HttpApiBuilder.group(AppApi, "github", (h) =>
18 Effect.gen(function* () {
19 const defaults = yield* Git.Handlers;
20 const git = yield* Git.Engine;
21 const { mergePull: _, ...rest } = defaults.github;
22 return h.handleAll(rest).handleRaw("mergePull", ({ request }) =>
23 Effect.gen(function* () {
24 const params = yield* HttpRouter.params;
25 const number = Number(params.number);
26 if (!Number.isSafeInteger(number) || number <= 0)
27 return HttpServerResponse.empty({ status: 404 });
28 const body = yield* request.json.pipe(
29 Effect.flatMap(Schema.decodeUnknownEffect(MergeBody)),
30 );
31 if (body.merge_method !== undefined && body.merge_method !== "merge")
32 return HttpServerResponse.jsonUnsafe(
33 { message: "Merge method is not supported" },
34 { status: 405 },
35 );
36 const result = yield* mergePull(
37 git,
38 { owner: params.owner ?? "", repo: params.repo ?? "", number },
39 { message: body.commit_message, expectedHeadOid: body.sha },
40 );
41 return HttpServerResponse.jsonUnsafe({
42 sha: result.oid,
43 merged: true,
44 message: "Pull Request successfully merged",
45 });
46 }).pipe(
47 Effect.catch((error) =>
48 Effect.succeed(
49 HttpServerResponse.jsonUnsafe(
50 { message: error._tag },
51 {
52 status:
53 error._tag === "PushDenied"
54 ? 403
55 : error._tag === "Unauthorized"
56 ? 401
57 : error._tag === "RepoNotFound" ||
58 error._tag === "PullNotFound"
59 ? 404
60 : error._tag === "SchemaError" ||
61 error._tag === "HttpServerError"
62 ? 400
63 : 409,
64 },
65 ),
66 ),
67 ),
68 ),
69 );
70 }),
71);