v1 feature: added playlists
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import { DatabaseSync, type SQLOutputValue } from "node:sqlite";
|
||||
import { Dump, type RichContent, type User } from "./interfaces.ts";
|
||||
import {
|
||||
Dump,
|
||||
type Playlist,
|
||||
type RichContent,
|
||||
type User,
|
||||
} from "./interfaces.ts";
|
||||
|
||||
export const db = new DatabaseSync("api/sql/gerbeur.db");
|
||||
db.exec("PRAGMA foreign_keys = ON;");
|
||||
@@ -133,3 +138,37 @@ export function userApiToRow(user: User): UserRow {
|
||||
avatar_mime: user.avatarMime ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
export interface PlaylistRow {
|
||||
id: string;
|
||||
user_id: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
is_public: number;
|
||||
created_at: string;
|
||||
image_mime: string | null;
|
||||
[key: string]: SQLOutputValue;
|
||||
}
|
||||
|
||||
export function isPlaylistRow(
|
||||
obj: Record<string, SQLOutputValue>,
|
||||
): obj is PlaylistRow {
|
||||
return !!obj && typeof obj.id === "string" &&
|
||||
typeof obj.user_id === "string" &&
|
||||
typeof obj.title === "string" &&
|
||||
typeof obj.is_public === "number" &&
|
||||
typeof obj.created_at === "string";
|
||||
}
|
||||
|
||||
export function playlistRowToApi(row: PlaylistRow): Playlist {
|
||||
return {
|
||||
id: row.id,
|
||||
userId: row.user_id,
|
||||
title: row.title,
|
||||
description: row.description ?? undefined,
|
||||
isPublic: Boolean(row.is_public),
|
||||
createdAt: new Date(row.created_at),
|
||||
imageMime: row.image_mime ?? undefined,
|
||||
dumpCount: typeof row.dump_count === "number" ? row.dump_count : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -141,6 +141,74 @@ export class APIException extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Playlists
|
||||
*/
|
||||
|
||||
export interface Playlist {
|
||||
id: string;
|
||||
userId: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
isPublic: boolean;
|
||||
createdAt: Date;
|
||||
imageMime?: string;
|
||||
dumpCount?: number;
|
||||
}
|
||||
|
||||
export interface PlaylistWithDumps extends Playlist {
|
||||
dumps: Dump[];
|
||||
}
|
||||
|
||||
export interface PlaylistMembership {
|
||||
playlist: Playlist;
|
||||
hasDump: boolean;
|
||||
}
|
||||
|
||||
export interface CreatePlaylistRequest {
|
||||
title: string;
|
||||
description?: string;
|
||||
isPublic: boolean;
|
||||
}
|
||||
|
||||
export interface UpdatePlaylistRequest {
|
||||
title?: string;
|
||||
description?: string;
|
||||
isPublic?: boolean;
|
||||
}
|
||||
|
||||
export interface ReorderPlaylistRequest {
|
||||
dumpIds: string[];
|
||||
}
|
||||
|
||||
export function isCreatePlaylistRequest(
|
||||
obj: unknown,
|
||||
): obj is CreatePlaylistRequest {
|
||||
return !!obj && typeof obj === "object" &&
|
||||
"title" in obj && typeof obj.title === "string" &&
|
||||
(!("description" in obj) || typeof obj.description === "string" ||
|
||||
obj.description === null) &&
|
||||
"isPublic" in obj && typeof obj.isPublic === "boolean";
|
||||
}
|
||||
|
||||
export function isUpdatePlaylistRequest(
|
||||
obj: unknown,
|
||||
): obj is UpdatePlaylistRequest {
|
||||
return !!obj && typeof obj === "object" &&
|
||||
(!("title" in obj) || typeof obj.title === "string") &&
|
||||
(!("description" in obj) || typeof obj.description === "string" ||
|
||||
obj.description === null) &&
|
||||
(!("isPublic" in obj) || typeof obj.isPublic === "boolean");
|
||||
}
|
||||
|
||||
export function isReorderPlaylistRequest(
|
||||
obj: unknown,
|
||||
): obj is ReorderPlaylistRequest {
|
||||
return !!obj && typeof obj === "object" &&
|
||||
"dumpIds" in obj && Array.isArray(obj.dumpIds) &&
|
||||
(obj.dumpIds as unknown[]).every((id) => typeof id === "string");
|
||||
}
|
||||
|
||||
/**
|
||||
* Request DTOs
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user