61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import { Router } from "express";
|
|
import { and, asc, eq } from "drizzle-orm";
|
|
import { z } from "zod";
|
|
import { db } from "../db/index.js";
|
|
import { trackWith } from "../db/queries.js";
|
|
import { albums, artists, tracks } from "../db/schema.js";
|
|
import { HttpError, asyncHandler, assertUuid, notFound, parseBody } from "../lib/http.js";
|
|
import { hasPerm } from "../lib/permissions.js";
|
|
import { albumDTO, trackDTO } from "../lib/presenters.js";
|
|
import { requireAuth } from "../middleware/auth.js";
|
|
|
|
export const albumsRouter = Router();
|
|
|
|
albumsRouter.get(
|
|
"/albums/:id",
|
|
requireAuth,
|
|
asyncHandler(async (req, res) => {
|
|
const id = assertUuid(req.params.id);
|
|
const [album] = await db.select().from(albums).where(eq(albums.id, id)).limit(1);
|
|
if (!album) throw notFound("Альбом не найден");
|
|
|
|
let artist = null;
|
|
if (album.artistId) {
|
|
[artist] = await db.select().from(artists).where(eq(artists.id, album.artistId)).limit(1);
|
|
}
|
|
|
|
const rows = await db.query.tracks.findMany({
|
|
where: and(eq(tracks.albumId, id), eq(tracks.status, "approved")),
|
|
with: trackWith,
|
|
orderBy: [asc(tracks.discNumber), asc(tracks.trackNumber), asc(tracks.title)],
|
|
});
|
|
|
|
res.json({
|
|
album: albumDTO({ ...album, artist: artist ?? null }),
|
|
tracks: rows.map((t) => trackDTO(t as never)),
|
|
canEdit: hasPerm(req.user, "canManageLibrary"),
|
|
});
|
|
}),
|
|
);
|
|
|
|
const patchSchema = z.object({
|
|
title: z.string().min(1).max(300).optional(),
|
|
artistId: z.string().uuid().nullable().optional(),
|
|
releaseDate: z.string().nullable().optional(),
|
|
coverUrl: z.string().nullable().optional(),
|
|
});
|
|
|
|
albumsRouter.patch(
|
|
"/albums/:id",
|
|
requireAuth,
|
|
asyncHandler(async (req, res) => {
|
|
if (!hasPerm(req.user, "canManageLibrary")) throw new HttpError(403, "Нет прав");
|
|
const id = assertUuid(req.params.id);
|
|
const data = parseBody(patchSchema, req.body);
|
|
await db.update(albums).set({ ...data, updatedAt: new Date() }).where(eq(albums.id, id));
|
|
const [album] = await db.select().from(albums).where(eq(albums.id, id)).limit(1);
|
|
if (!album) throw notFound("Альбом не найден");
|
|
res.json({ album: albumDTO(album) });
|
|
}),
|
|
);
|