Skip to content

Commit 26bf835

Browse files
committed
feat(friends): Add endpoint to accept and decline friend requests.
1 parent 882f065 commit 26bf835

File tree

4 files changed

+80
-12
lines changed

4 files changed

+80
-12
lines changed

server/api/v1/user/friends/index.get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default defineEventHandler(async (event) => {
1717
const param: GetFriendParam = {user_id: user.id};
1818

1919
const {data, error}: {
20-
data: GetFriendsResponse | null,
20+
data: GetFriendsResponse[] | null,
2121
error: FriendError | null
2222
} = await client.rpc('get_friends', param as never);
2323

server/api/v1/user/friends/index.post.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {SendFriendRequestParam} from "~/types/api/user.friends";
55

66
const userSchema = z.object({
77
receiver_id: z.string().uuid()
8-
})
8+
}).readonly()
99

1010
export default defineEventHandler(async (event) => {
1111
// validate post-request body
Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,53 @@
1-
// accept or decline friend request
1+
import {z} from "zod";
2+
import {FriendAction} from "~/types/api/user.friends";
3+
import {serverSupabaseServiceRole, serverSupabaseUser} from "#supabase/server";
4+
import type {FriendActionParam} from "~/types/api/user.friends";
5+
import type {PostgrestError} from "@supabase/postgrest-js";
6+
7+
const friendActionSchema = z.object({
8+
friendship_id: z.bigint().positive(),
9+
action: z.nativeEnum(FriendAction)
10+
}).readonly()
11+
12+
export default defineEventHandler(async (event) => {
13+
// validate post-request body
14+
const result = await readValidatedBody(event, body => friendActionSchema.safeParse(body))
15+
if (!result.success) {
16+
setResponseStatus(event, 400);
17+
return {error: result.error.issues};
18+
}
19+
20+
// Require user to be authenticated
21+
const user = await serverSupabaseUser(event);
22+
if (!user?.id) {
23+
setResponseStatus(event, 401);
24+
return {error: 'unauthenticated'};
25+
}
26+
27+
// Send request
28+
const client = serverSupabaseServiceRole(event);
29+
const param: FriendActionParam = {friendship_id: result.data.friendship_id};
30+
31+
let error: PostgrestError | null = null;
32+
switch (result.data.action) {
33+
case FriendAction.ACCEPT: {
34+
const {error: acceptErr} = await client.rpc('accept_friend_request', param as never);
35+
error = acceptErr;
36+
error = acceptErr;
37+
break;
38+
}
39+
case FriendAction.DECLINE: {
40+
const {error: declineErr} = await client.rpc('decline_friend_request', param as never);
41+
error = declineErr;
42+
break;
43+
}
44+
}
45+
46+
// Handle errors
47+
if (error) {
48+
setResponseStatus(event, 500);
49+
return {error: error.message};
50+
}
51+
52+
return {};
53+
});

types/api/user.friends.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
export interface GetFriendsResponse {
2-
friendship_id: bigint,
3-
friend_id: string,
4-
created_at: string
5-
updated_at: string
6-
status: "pending" | "accepted"
7-
}
8-
1+
// ----- Internal Types -----
92
export interface FriendError {
103
message: string
114
}
@@ -17,4 +10,27 @@ export interface GetFriendParam {
1710
export interface SendFriendRequestParam {
1811
sender_id: string,
1912
receiver_id: string
20-
}
13+
}
14+
15+
export interface FriendActionParam {
16+
friendship_id: bigint,
17+
}
18+
19+
// ----- For API Consumer -----
20+
export interface GetFriendsResponse {
21+
friendship_id: bigint,
22+
friend_id: string,
23+
created_at: string
24+
updated_at: string
25+
status: "pending" | "accepted"
26+
}
27+
28+
export enum FriendAction {
29+
ACCEPT = "accept",
30+
DECLINE = "decline"
31+
}
32+
33+
export interface FriendActionRequest {
34+
action: FriendAction,
35+
friendship_id: bigint
36+
}

0 commit comments

Comments
 (0)