All checks were successful
Deploy production / deploy (push) Successful in 1m11s
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
// Public cover images for the catalogue (covers only, never book files).
|
|
import { error } from '@sveltejs/kit';
|
|
import { and, eq, isNull } from 'drizzle-orm';
|
|
import { isOwner } from '#lib/server/owner.js';
|
|
import { db } from '#lib/server/db/index.js';
|
|
import { bookWorks } from '#lib/server/db/schema/index.js';
|
|
import { safeResolve, streamFile } from '#lib/server/books/files.js';
|
|
import type { RequestHandler } from './$types';
|
|
|
|
export const GET: RequestHandler = async (event) => {
|
|
const [work] = await db
|
|
.select({ coverPath: bookWorks.coverPath })
|
|
.from(bookWorks)
|
|
.where(
|
|
and(
|
|
eq(bookWorks.id, Number(event.params.id)),
|
|
isOwner(event) ? undefined : isNull(bookWorks.archivedAt)
|
|
)
|
|
)
|
|
.limit(1);
|
|
const resolved = work?.coverPath ? await safeResolve('covers', work.coverPath) : null;
|
|
if (!resolved) error(404, 'Not Found');
|
|
const response = await streamFile(resolved, event.request, {
|
|
'cache-control': 'public, max-age=86400, stale-while-revalidate=604800',
|
|
'x-content-type-options': 'nosniff'
|
|
});
|
|
if (!response.headers.get('content-type')?.startsWith('image/')) error(404, 'Not Found');
|
|
return response;
|
|
};
|