Skip to content

Commit

Permalink
Implementing the server side API endpoints for managing friends
Browse files Browse the repository at this point in the history
  • Loading branch information
dejanvasic85 committed Jan 19, 2025
1 parent a919d16 commit 4a02287
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/lib/browserFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function tryFetch<T>(
});

if (response.ok) {
const shouldParse = options?.shouldParse ?? true;
const shouldParse = options?.shouldParse ?? false;
if (shouldParse) {
const data = await response.json();
return some(data) as Maybe<T>;
Expand Down
1 change: 1 addition & 0 deletions src/lib/server/mapApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ApiError, ServerError } from '$lib/types';

export const mapToApiError = <T extends ServerError>(err: T): ApiError => {
console.error(err);
switch (err._tag) {
case 'DatabaseError':
case 'SendEmailError':
Expand Down
4 changes: 2 additions & 2 deletions src/routes/api/board/[id]/+server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RequestHandler } from '@sveltejs/kit';
import { json } from '@sveltejs/kit';
import { json, error } from '@sveltejs/kit';

import { taskEither as TE } from 'fp-ts';
import { pipe } from 'fp-ts/lib/function';
Expand All @@ -25,7 +25,7 @@ export const PATCH: RequestHandler = async ({ locals, params, request }) => {
TE.flatMap(({ changes, board }) => updateBoard({ ...board, ...changes })),
TE.mapLeft(mapToApiError),
TE.match(
(err) => json({ message: err.message }, { status: err.status }),
(err) => error(err.status, { message: err.message }),
(board) => json(board)
)
)();
Expand Down
19 changes: 19 additions & 0 deletions src/routes/api/connections/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { type RequestHandler, json, error } from '@sveltejs/kit';
import { pipe } from 'fp-ts/lib/function';
import { taskEither as TE } from 'fp-ts';
import { mapToApiError } from '$lib/server/mapApi';
import { acceptInvite } from '$lib/server/services/friendService';

export const POST: RequestHandler = async ({ locals, request }) => {
const user = locals.user!;
const body = await request.json();

return pipe(
acceptInvite(body.inviteId, { id: user.id, email: user.email! }),
TE.mapLeft(mapToApiError),
TE.match(
(err) => error(err.status, { message: err.message }),
(connection) => json(connection)
)
)();
};
4 changes: 1 addition & 3 deletions src/routes/api/friends/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ export const GET: RequestHandler = ({ locals }) => {
TE.bind('friends', () => getFriends(user.id)),
TE.mapLeft(mapToApiError),
TE.match(
(err) => {
throw error(err.status, err.message);
},
(err) => error(err.status, { message: err.message }),
({ friends, pendingReceivedInvites, pendingSentInvites }) =>
json({
friends,
Expand Down
22 changes: 22 additions & 0 deletions src/routes/api/friends/[id]/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { error, type RequestHandler } from '@sveltejs/kit';
import { pipe } from 'fp-ts/lib/function';
import { taskEither as TE } from 'fp-ts';

import { mapToApiError } from '$lib/server/mapApi';
import { removeConnection } from '$lib/server/services/friendService';

export const DELETE: RequestHandler = ({ locals, params }) => {
if (!locals.user) {
return error(401, { message: 'Unauthorized' });
}

const friendId = params.id!;
return pipe(
removeConnection(locals.user!.id, friendId),
TE.mapLeft(mapToApiError),
TE.match(
(err) => error(err.status, { message: err.message }),
() => new Response(null, { status: 204 })
)
)();
};
21 changes: 21 additions & 0 deletions src/routes/api/invites/[id]/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { error, type RequestHandler } from '@sveltejs/kit';
import { pipe } from 'fp-ts/lib/function';
import { taskEither as TE } from 'fp-ts';
import { mapToApiError } from '$lib/server/mapApi';
import { cancelInvite } from '$lib/server/services/friendService';

export const DELETE: RequestHandler = ({ locals, params }) => {
if (!locals.user) {
return error(401, { message: 'Unauthorized' });
}

const inviteId = params.id!;
return pipe(
cancelInvite(inviteId),
TE.mapLeft(mapToApiError),
TE.match(
(err) => error(err.status, { message: err.message }),
() => new Response(null, { status: 204 })
)
)();
};
4 changes: 2 additions & 2 deletions src/routes/api/notes/+server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { json, type RequestHandler } from '@sveltejs/kit';
import { json, error, type RequestHandler } from '@sveltejs/kit';

import { pipe } from 'fp-ts/lib/function';
import { taskEither as TE } from 'fp-ts/lib';
Expand Down Expand Up @@ -27,7 +27,7 @@ export const POST: RequestHandler = async ({ locals, request }) => {
TE.flatMap(({ note }) => createNote({ ...note, boardId: note.boardId! })),
TE.mapLeft(mapToApiError),
TE.match(
(error) => json(error, { status: error.status }),
(err) => error(err.status, { message: err.message }),
(note) => json(note, { status: 201 })
)
)();
Expand Down
8 changes: 4 additions & 4 deletions src/routes/api/notes/[id]/+server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { json, type RequestHandler } from '@sveltejs/kit';
import { json, error, type RequestHandler } from '@sveltejs/kit';

import { taskEither as TE } from 'fp-ts';
import { pipe } from 'fp-ts/lib/function';
Expand All @@ -19,7 +19,7 @@ export const GET: RequestHandler = ({ locals, params }) => {
TE.flatMap(({ user, note }) => isNoteOwner({ user, note })),
TE.mapLeft(mapToApiError),
TE.match(
(err) => json({ message: err.message }, { status: err.status }),
(err) => error(err.status, { message: err.message }),
(note) => json(note)
)
)();
Expand All @@ -37,7 +37,7 @@ export const PATCH: RequestHandler = async ({ locals, params, request }) => {
TE.flatMap(({ noteInput, note }) => updateNote({ ...note, ...noteInput })),
TE.mapLeft(mapToApiError),
TE.match(
(err) => json({ message: err.message }, { status: err.status }),
(err) => error(err.status, { message: err.message }),
(note) => json(note)
)
)();
Expand All @@ -64,7 +64,7 @@ export const DELETE: RequestHandler = async ({ locals, params }) => {
),
TE.mapLeft(mapToApiError),
TE.match(
(err) => json({ message: err.message }, { status: err.status }),
(err) => error(err.status, { message: err.message }),
() => new Response(null, { status: 204 })
)
)();
Expand Down
4 changes: 2 additions & 2 deletions src/routes/api/notes/[id]/editors/+server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type RequestHandler, json } from '@sveltejs/kit';
import { type RequestHandler, json, error } from '@sveltejs/kit';

import { pipe } from 'fp-ts/lib/function.js';
import { taskEither as TE } from 'fp-ts';
Expand All @@ -18,7 +18,7 @@ export const POST: RequestHandler = async ({ request, params }) => {
TE.flatMap((data) => updateNoteEditor(data)),
TE.mapLeft(mapToApiError),
TE.match(
(err) => json({ message: err.message }, { status: err.status }),
(err) => error(err.status, { message: err.message }),
(data) => json(data)
)
)();
Expand Down
11 changes: 9 additions & 2 deletions src/routes/my/friends/v2/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
async function handleCancelInvite(id: string) {
const [index, invite] = friendsState.cancelInvite(id);
const result = await tryFetch(`/api/friends/invite/${id}`, { method: 'DELETE' });
const result = await tryFetch(`/api/invites/${id}`, { method: 'DELETE' });
if (result.type === 'error') {
toastMessages.addMessage({
type: 'error',
Expand All @@ -74,14 +74,21 @@
async function handleAcceptInvite(id: string) {
const [index, invite] = friendsState.acceptInvite(id);
const result = await tryFetch(`/api/friends/accept/${id}`, { method: 'POST' });
const result = await tryFetch(`/api/connections`, {
method: 'POST',
body: JSON.stringify({
inviteId: id
})
});
if (result.type === 'error') {
toastMessages.addMessage({
type: 'error',
message: 'There was a problem removing the friend. Try again.'
});
friendsState.addReceivedInviteAtIndex(index, invite);
friendsState.removeFriend(invite.userId);
} else {
console.log('accepted invite', result.value);
}
}
Expand Down

0 comments on commit 4a02287

Please sign in to comment.