v3: code quality pass
This commit is contained in:
@@ -44,9 +44,9 @@ router.post("/api/avatars/me", authMiddleware, async (ctx) => {
|
||||
}
|
||||
updateClientAvatar(authPayload.userId, mime);
|
||||
|
||||
const user = getUserById(authPayload.userId);
|
||||
const { passwordHash: _, ...publicUser } = getUserById(authPayload.userId);
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = { success: true, data: user };
|
||||
ctx.response.body = { success: true, data: publicUser };
|
||||
});
|
||||
|
||||
router.get("/api/avatars/:userId", async (ctx) => {
|
||||
|
||||
@@ -38,7 +38,7 @@ router.get("/dumps/:dumpId/comments", async (ctx) => {
|
||||
|
||||
// POST /api/dumps/:dumpId/comments — auth required
|
||||
router.post("/dumps/:dumpId/comments", authMiddleware, async (ctx) => {
|
||||
const userId = ctx.state.user.userId as string;
|
||||
const userId = ctx.state.user.userId;
|
||||
const dump = getDump(ctx.params.dumpId, userId);
|
||||
const body = await ctx.request.body.json();
|
||||
if (!isCreateCommentRequest(body)) {
|
||||
@@ -62,8 +62,8 @@ router.post("/dumps/:dumpId/comments", authMiddleware, async (ctx) => {
|
||||
|
||||
// PATCH /api/comments/:commentId — auth required
|
||||
router.patch("/comments/:commentId", authMiddleware, async (ctx) => {
|
||||
const userId = ctx.state.user.userId as string;
|
||||
const isAdmin = (ctx.state.user.isAdmin ?? false) as boolean;
|
||||
const userId = ctx.state.user.userId;
|
||||
const isAdmin = ctx.state.user.isAdmin ?? false;
|
||||
const body = await ctx.request.body.json();
|
||||
if (!isUpdateCommentRequest(body)) {
|
||||
throw new APIException(
|
||||
@@ -85,8 +85,8 @@ router.patch("/comments/:commentId", authMiddleware, async (ctx) => {
|
||||
|
||||
// DELETE /api/comments/:commentId — auth required
|
||||
router.delete("/comments/:commentId", authMiddleware, (ctx) => {
|
||||
const userId = ctx.state.user.userId as string;
|
||||
const isAdmin = (ctx.state.user.isAdmin ?? false) as boolean;
|
||||
const userId = ctx.state.user.userId;
|
||||
const isAdmin = ctx.state.user.isAdmin ?? false;
|
||||
const { dumpId, isPrivate } = deleteComment(
|
||||
ctx.params.commentId,
|
||||
userId,
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
type FollowStatus,
|
||||
type PaginatedData,
|
||||
} from "../model/interfaces.ts";
|
||||
import { parsePagination } from "../lib/pagination.ts";
|
||||
import {
|
||||
followPlaylist,
|
||||
followUser,
|
||||
@@ -22,26 +23,16 @@ const router = new Router({ prefix: "/api/follows" });
|
||||
|
||||
// GET /api/follows/status
|
||||
router.get("/status", authMiddleware, (ctx) => {
|
||||
const status = getFollowStatus(ctx.state.user.userId as string);
|
||||
const status = getFollowStatus(ctx.state.user.userId);
|
||||
const body: APIResponse<FollowStatus> = { success: true, data: status };
|
||||
ctx.response.body = body;
|
||||
});
|
||||
|
||||
// GET /api/follows/feed/users?page=&limit=
|
||||
router.get("/feed/users", authMiddleware, (ctx) => {
|
||||
const page = Math.max(
|
||||
1,
|
||||
parseInt(ctx.request.url.searchParams.get("page") ?? "1") || 1,
|
||||
);
|
||||
const limit = Math.min(
|
||||
Math.max(
|
||||
1,
|
||||
parseInt(ctx.request.url.searchParams.get("limit") ?? "20") || 20,
|
||||
),
|
||||
100,
|
||||
);
|
||||
const { page, limit } = parsePagination(ctx.request.url.searchParams);
|
||||
const { items, total } = getFollowedUsersDumpFeed(
|
||||
ctx.state.user.userId as string,
|
||||
ctx.state.user.userId,
|
||||
page,
|
||||
limit,
|
||||
);
|
||||
@@ -56,19 +47,9 @@ router.get("/feed/users", authMiddleware, (ctx) => {
|
||||
|
||||
// GET /api/follows/feed/playlists?page=&limit=
|
||||
router.get("/feed/playlists", authMiddleware, (ctx) => {
|
||||
const page = Math.max(
|
||||
1,
|
||||
parseInt(ctx.request.url.searchParams.get("page") ?? "1") || 1,
|
||||
);
|
||||
const limit = Math.min(
|
||||
Math.max(
|
||||
1,
|
||||
parseInt(ctx.request.url.searchParams.get("limit") ?? "20") || 20,
|
||||
),
|
||||
100,
|
||||
);
|
||||
const { page, limit } = parsePagination(ctx.request.url.searchParams);
|
||||
const { items, total } = getFollowedPlaylistsDumpFeed(
|
||||
ctx.state.user.userId as string,
|
||||
ctx.state.user.userId,
|
||||
page,
|
||||
limit,
|
||||
);
|
||||
@@ -83,25 +64,25 @@ router.get("/feed/playlists", authMiddleware, (ctx) => {
|
||||
|
||||
// POST /api/follows/users/:userId
|
||||
router.post("/users/:userId", authMiddleware, (ctx) => {
|
||||
followUser(ctx.state.user.userId as string, ctx.params.userId);
|
||||
followUser(ctx.state.user.userId, ctx.params.userId);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
|
||||
// DELETE /api/follows/users/:userId
|
||||
router.delete("/users/:userId", authMiddleware, (ctx) => {
|
||||
unfollowUser(ctx.state.user.userId as string, ctx.params.userId);
|
||||
unfollowUser(ctx.state.user.userId, ctx.params.userId);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
|
||||
// POST /api/follows/playlists/:playlistId
|
||||
router.post("/playlists/:playlistId", authMiddleware, (ctx) => {
|
||||
followPlaylist(ctx.state.user.userId as string, ctx.params.playlistId);
|
||||
followPlaylist(ctx.state.user.userId, ctx.params.playlistId);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
|
||||
// DELETE /api/follows/playlists/:playlistId
|
||||
router.delete("/playlists/:playlistId", authMiddleware, (ctx) => {
|
||||
unfollowPlaylist(ctx.state.user.userId as string, ctx.params.playlistId);
|
||||
unfollowPlaylist(ctx.state.user.userId, ctx.params.playlistId);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ router.post("/", authMiddleware, async (ctx: AuthContext) => {
|
||||
router.get("/:token", async (ctx) => {
|
||||
try {
|
||||
await validateInvite(ctx.params.token);
|
||||
ctx.response.body = { success: true };
|
||||
ctx.response.body = { success: true, data: null };
|
||||
} catch {
|
||||
throw new APIException(
|
||||
APIErrorCode.NOT_FOUND,
|
||||
|
||||
@@ -2,9 +2,9 @@ import { Router } from "@oak/oak";
|
||||
import {
|
||||
APIErrorCode,
|
||||
APIException,
|
||||
type AuthPayload,
|
||||
type PaginatedData,
|
||||
} from "../model/interfaces.ts";
|
||||
import { parsePagination } from "../lib/pagination.ts";
|
||||
import { type AuthContext, authMiddleware } from "../middleware/auth.ts";
|
||||
import {
|
||||
getNotificationsForUser,
|
||||
@@ -19,17 +19,7 @@ router.get("/", authMiddleware, (ctx: AuthContext) => {
|
||||
if (!ctx.state.user) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 401, "Not authenticated");
|
||||
}
|
||||
const page = Math.max(
|
||||
1,
|
||||
parseInt(ctx.request.url.searchParams.get("page") ?? "1") || 1,
|
||||
);
|
||||
const limit = Math.min(
|
||||
Math.max(
|
||||
1,
|
||||
parseInt(ctx.request.url.searchParams.get("limit") ?? "20") || 20,
|
||||
),
|
||||
100,
|
||||
);
|
||||
const { page, limit } = parsePagination(ctx.request.url.searchParams);
|
||||
const { items, total } = getNotificationsForUser(
|
||||
ctx.state.user.userId,
|
||||
page,
|
||||
@@ -56,7 +46,7 @@ router.post("/read-all", authMiddleware, (ctx: AuthContext) => {
|
||||
|
||||
// PATCH /api/notifications/:id/read
|
||||
router.patch("/:id/read", authMiddleware, (ctx) => {
|
||||
const user = ctx.state.user as AuthPayload;
|
||||
const user = ctx.state.user;
|
||||
if (!user) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 401, "Not authenticated");
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ router.post("/register", async (ctx) => {
|
||||
|
||||
// Mark invite as used only after the user row is committed
|
||||
try {
|
||||
await redeemInvite(body.inviteToken);
|
||||
redeemInvite(body.inviteToken);
|
||||
} catch (err) {
|
||||
console.error("[register] redeemInvite failed (user created):", err);
|
||||
}
|
||||
@@ -123,11 +123,13 @@ router.get("/me", authMiddleware, (ctx: AuthContext) => {
|
||||
);
|
||||
}
|
||||
|
||||
const user = getUserById(ctx.state.user.userId);
|
||||
const { passwordHash: _, ...publicUser } = getUserById(
|
||||
ctx.state.user.userId,
|
||||
);
|
||||
|
||||
ctx.response.body = {
|
||||
success: true,
|
||||
data: user,
|
||||
data: publicUser,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
@@ -16,7 +16,10 @@ import {
|
||||
} from "../services/vote-service.ts";
|
||||
import { getUnreadCount } from "../services/notification-service.ts";
|
||||
import { getUserById } from "../services/user-service.ts";
|
||||
import { APIException } from "../model/interfaces.ts";
|
||||
import {
|
||||
APIException,
|
||||
type ClientToServerMessage,
|
||||
} from "../model/interfaces.ts";
|
||||
|
||||
const router = new Router();
|
||||
|
||||
@@ -78,7 +81,7 @@ router.get("/ws", async (ctx) => {
|
||||
});
|
||||
|
||||
socket.addEventListener("message", (event) => {
|
||||
let msg: { type: string; dumpId?: string };
|
||||
let msg: ClientToServerMessage;
|
||||
try {
|
||||
msg = JSON.parse(event.data as string);
|
||||
} catch {
|
||||
@@ -109,7 +112,7 @@ router.get("/ws", async (ctx) => {
|
||||
|
||||
function handleVote(
|
||||
client: WsClient,
|
||||
dumpId: string | undefined,
|
||||
dumpId: string,
|
||||
action: "cast" | "remove",
|
||||
): void {
|
||||
const { socket } = client;
|
||||
@@ -121,11 +124,6 @@ function handleVote(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dumpId) {
|
||||
socket.send(JSON.stringify({ type: "error", message: "Missing dumpId" }));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const newCount = action === "cast"
|
||||
? castVote(dumpId, client.userId)
|
||||
|
||||
Reference in New Issue
Block a user