v3: code quality pass
This commit is contained in:
@@ -75,7 +75,7 @@ export interface UserRow {
|
||||
* Type Guards
|
||||
*/
|
||||
|
||||
export function isDumpRow(obj: Record<string, SQLOutputValue>): obj is DumpRow {
|
||||
export function isDumpRow(obj: unknown): obj is DumpRow {
|
||||
return !!obj &&
|
||||
typeof obj === "object" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
@@ -102,7 +102,7 @@ export function isDumpRow(obj: Record<string, SQLOutputValue>): obj is DumpRow {
|
||||
"is_private" in obj && typeof obj.is_private === "number";
|
||||
}
|
||||
|
||||
export function isUserRow(obj: Record<string, SQLOutputValue>): obj is UserRow {
|
||||
export function isUserRow(obj: unknown): obj is UserRow {
|
||||
return !!obj &&
|
||||
typeof obj === "object" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
@@ -214,18 +214,21 @@ export interface CommentRow {
|
||||
}
|
||||
|
||||
export function isCommentRow(
|
||||
obj: Record<string, SQLOutputValue>,
|
||||
obj: unknown,
|
||||
): obj is CommentRow {
|
||||
return !!obj && typeof obj === "object" &&
|
||||
typeof obj.id === "string" &&
|
||||
typeof obj.dump_id === "string" &&
|
||||
typeof obj.user_id === "string" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
"dump_id" in obj && typeof obj.dump_id === "string" &&
|
||||
"user_id" in obj && typeof obj.user_id === "string" &&
|
||||
"parent_id" in obj &&
|
||||
(typeof obj.parent_id === "string" || obj.parent_id === null) &&
|
||||
typeof obj.body === "string" &&
|
||||
typeof obj.created_at === "string" &&
|
||||
"body" in obj && typeof obj.body === "string" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"updated_at" in obj &&
|
||||
(typeof obj.updated_at === "string" || obj.updated_at === null) &&
|
||||
typeof obj.deleted === "number" &&
|
||||
typeof obj.author_username === "string" &&
|
||||
"deleted" in obj && typeof obj.deleted === "number" &&
|
||||
"author_username" in obj && typeof obj.author_username === "string" &&
|
||||
"author_avatar_mime" in obj &&
|
||||
(typeof obj.author_avatar_mime === "string" ||
|
||||
obj.author_avatar_mime === null);
|
||||
}
|
||||
@@ -259,16 +262,20 @@ export interface PlaylistRow {
|
||||
}
|
||||
|
||||
export function isPlaylistRow(
|
||||
obj: Record<string, SQLOutputValue>,
|
||||
obj: unknown,
|
||||
): obj is PlaylistRow {
|
||||
return !!obj && typeof obj.id === "string" &&
|
||||
typeof obj.user_id === "string" &&
|
||||
typeof obj.title === "string" &&
|
||||
(typeof obj.slug === "string" || obj.slug === null) &&
|
||||
return !!obj && typeof obj === "object" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
"user_id" in obj && typeof obj.user_id === "string" &&
|
||||
"title" in obj && typeof obj.title === "string" &&
|
||||
"slug" in obj && (typeof obj.slug === "string" || obj.slug === null) &&
|
||||
"description" in obj &&
|
||||
(typeof obj.description === "string" || obj.description === null) &&
|
||||
typeof obj.is_public === "number" &&
|
||||
typeof obj.created_at === "string" &&
|
||||
"is_public" in obj && typeof obj.is_public === "number" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"updated_at" in obj &&
|
||||
(typeof obj.updated_at === "string" || obj.updated_at === null) &&
|
||||
"image_mime" in obj &&
|
||||
(typeof obj.image_mime === "string" || obj.image_mime === null);
|
||||
}
|
||||
|
||||
@@ -300,15 +307,15 @@ export interface FollowRow {
|
||||
}
|
||||
|
||||
export function isFollowRow(
|
||||
obj: Record<string, SQLOutputValue>,
|
||||
obj: unknown,
|
||||
): obj is FollowRow {
|
||||
return !!obj &&
|
||||
typeof obj.id === "string" &&
|
||||
typeof obj.follower_id === "string" &&
|
||||
typeof obj.created_at === "string" &&
|
||||
(obj.followed_user_id === null ||
|
||||
return !!obj && typeof obj === "object" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
"follower_id" in obj && typeof obj.follower_id === "string" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"followed_user_id" in obj && (obj.followed_user_id === null ||
|
||||
typeof obj.followed_user_id === "string") &&
|
||||
(obj.followed_playlist_id === null ||
|
||||
"followed_playlist_id" in obj && (obj.followed_playlist_id === null ||
|
||||
typeof obj.followed_playlist_id === "string");
|
||||
}
|
||||
|
||||
@@ -326,15 +333,16 @@ export interface NotificationRow {
|
||||
}
|
||||
|
||||
export function isNotificationRow(
|
||||
obj: Record<string, SQLOutputValue>,
|
||||
obj: unknown,
|
||||
): obj is NotificationRow {
|
||||
return !!obj && typeof obj === "object" &&
|
||||
typeof obj.id === "string" &&
|
||||
typeof obj.user_id === "string" &&
|
||||
typeof obj.type === "string" &&
|
||||
typeof obj.data === "string" &&
|
||||
typeof obj.read === "number" &&
|
||||
typeof obj.created_at === "string" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
"user_id" in obj && typeof obj.user_id === "string" &&
|
||||
"type" in obj && typeof obj.type === "string" &&
|
||||
"data" in obj && typeof obj.data === "string" &&
|
||||
"read" in obj && typeof obj.read === "number" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"source_key" in obj &&
|
||||
(typeof obj.source_key === "string" || obj.source_key === null);
|
||||
}
|
||||
|
||||
@@ -360,11 +368,12 @@ export interface InviteRow {
|
||||
}
|
||||
|
||||
export function isInviteRow(
|
||||
obj: Record<string, SQLOutputValue>,
|
||||
obj: unknown,
|
||||
): obj is InviteRow {
|
||||
return !!obj && typeof obj === "object" &&
|
||||
typeof obj.token === "string" &&
|
||||
typeof obj.inviter_id === "string" &&
|
||||
typeof obj.created_at === "string" &&
|
||||
"token" in obj && typeof obj.token === "string" &&
|
||||
"inviter_id" in obj && typeof obj.inviter_id === "string" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"used_at" in obj &&
|
||||
(obj.used_at === null || typeof obj.used_at === "string");
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ export interface CreatePlaylistRequest {
|
||||
|
||||
export interface UpdatePlaylistRequest {
|
||||
title?: string;
|
||||
description?: string;
|
||||
description?: string | null;
|
||||
isPublic?: boolean;
|
||||
}
|
||||
|
||||
@@ -428,40 +428,33 @@ export function isUpdateDumpRequest(obj: unknown): obj is UpdateDumpRequest {
|
||||
* WebSockets
|
||||
*/
|
||||
|
||||
// ── Client → Server ──────────────────────────────────────────────────────────
|
||||
|
||||
export interface PingMessage {
|
||||
type: "ping";
|
||||
}
|
||||
|
||||
export interface PongMessage {
|
||||
type: "pong";
|
||||
}
|
||||
|
||||
export interface VoteCastMessage {
|
||||
type: "vote_cast";
|
||||
dumpId: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface VoteAckMessageFailure {
|
||||
type: "vote_ack";
|
||||
dumpId: string;
|
||||
success: false;
|
||||
error: APIError;
|
||||
}
|
||||
|
||||
export interface VoteAckMessageSuccess {
|
||||
type: "vote_ack";
|
||||
dumpId: string;
|
||||
action: "cast" | "remove";
|
||||
success: true;
|
||||
voteCount: number;
|
||||
error?: never;
|
||||
}
|
||||
|
||||
export type VoteAckMessage = VoteAckMessageSuccess | VoteAckMessageFailure;
|
||||
|
||||
export interface VoteRemoveMessage {
|
||||
type: "vote_remove";
|
||||
dumpId: string;
|
||||
}
|
||||
|
||||
export interface VotesUpdateMessage {
|
||||
type: "votes_update";
|
||||
dumpId: string;
|
||||
voteCount: number;
|
||||
}
|
||||
export type ClientToServerMessage =
|
||||
| PingMessage
|
||||
| PongMessage
|
||||
| VoteCastMessage
|
||||
| VoteRemoveMessage;
|
||||
|
||||
// ── Server → Client ──────────────────────────────────────────────────────────
|
||||
|
||||
export interface OnlineUser {
|
||||
userId: string;
|
||||
@@ -474,6 +467,7 @@ export interface WelcomeMessage {
|
||||
type: "welcome";
|
||||
users: OnlineUser[];
|
||||
myVotes: string[];
|
||||
unreadNotificationCount: number;
|
||||
}
|
||||
|
||||
export interface PresenceUpdateMessage {
|
||||
@@ -481,14 +475,109 @@ export interface PresenceUpdateMessage {
|
||||
users: OnlineUser[];
|
||||
}
|
||||
|
||||
export interface PingMessage {
|
||||
type: "ping";
|
||||
export interface VotesUpdateMessage {
|
||||
type: "votes_update";
|
||||
dumpId: string;
|
||||
voteCount: number;
|
||||
voterId: string;
|
||||
action: "cast" | "remove";
|
||||
}
|
||||
|
||||
export interface PongMessage {
|
||||
type: "pong";
|
||||
export interface VoteAckMessage {
|
||||
type: "vote_ack";
|
||||
dumpId: string;
|
||||
action: "cast" | "remove";
|
||||
voteCount: number;
|
||||
}
|
||||
|
||||
export interface DumpCreatedMessage {
|
||||
type: "dump_created";
|
||||
dump: Dump;
|
||||
}
|
||||
|
||||
export interface DumpUpdatedMessage {
|
||||
type: "dump_updated";
|
||||
dump: Dump;
|
||||
}
|
||||
|
||||
export interface DumpDeletedMessage {
|
||||
type: "dump_deleted";
|
||||
dumpId: string;
|
||||
}
|
||||
|
||||
export interface PlaylistCreatedMessage {
|
||||
type: "playlist_created";
|
||||
playlist: Playlist;
|
||||
}
|
||||
|
||||
export interface PlaylistUpdatedMessage {
|
||||
type: "playlist_updated";
|
||||
playlist: Playlist;
|
||||
}
|
||||
|
||||
export interface PlaylistDeletedMessage {
|
||||
type: "playlist_deleted";
|
||||
playlistId: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface PlaylistDumpsUpdatedMessage {
|
||||
type: "playlist_dumps_updated";
|
||||
playlistId: string;
|
||||
dumpIds: string[];
|
||||
}
|
||||
|
||||
export interface UserUpdatedMessage {
|
||||
type: "user_updated";
|
||||
user: Omit<User, "passwordHash">;
|
||||
}
|
||||
|
||||
export interface CommentCreatedMessage {
|
||||
type: "comment_created";
|
||||
comment: Comment;
|
||||
}
|
||||
|
||||
export interface CommentUpdatedMessage {
|
||||
type: "comment_updated";
|
||||
comment: Comment;
|
||||
}
|
||||
|
||||
export interface CommentDeletedMessage {
|
||||
type: "comment_deleted";
|
||||
commentId: string;
|
||||
dumpId: string;
|
||||
}
|
||||
|
||||
export interface NotificationCreatedMessage {
|
||||
type: "notification_created";
|
||||
notification: RawNotification;
|
||||
}
|
||||
|
||||
export interface ErrorMessage {
|
||||
type: "error";
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export type ServerToClientMessage =
|
||||
| PingMessage
|
||||
| WelcomeMessage
|
||||
| PresenceUpdateMessage
|
||||
| VotesUpdateMessage
|
||||
| VoteAckMessage
|
||||
| DumpCreatedMessage
|
||||
| DumpUpdatedMessage
|
||||
| DumpDeletedMessage
|
||||
| PlaylistCreatedMessage
|
||||
| PlaylistUpdatedMessage
|
||||
| PlaylistDeletedMessage
|
||||
| PlaylistDumpsUpdatedMessage
|
||||
| UserUpdatedMessage
|
||||
| CommentCreatedMessage
|
||||
| CommentUpdatedMessage
|
||||
| CommentDeletedMessage
|
||||
| NotificationCreatedMessage
|
||||
| ErrorMessage;
|
||||
|
||||
/**
|
||||
* Follows
|
||||
*/
|
||||
@@ -568,3 +657,8 @@ export interface Notification {
|
||||
read: boolean;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
/** Wire format — createdAt arrives as an ISO string over JSON. */
|
||||
export type RawNotification = Omit<Notification, "createdAt"> & {
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user