// Copyright (c) 2020 Jan Kaßel // Copyright (c) 2022 Gerben // // SPDX-License-Identifier: MIT import db from '../db.js'; import { Container, PagedContainer, sendPage, sendContainer, expandAnnotation, } from '../ldp.js'; import { getPrefixedEntries } from '../util.js'; import type { Request, Response } from 'express'; export interface CollectionInfo { name: string, label: string, } export async function createCollection(req: Request, res: Response) { if (!req.body?.name) { res.status(400).send('Bad request'); return; } const { name, label } = req.body; const collectionKey = `${req.params.user}/${name}`; try { await db.get(collectionKey); res.status(409).send('Conflict'); return; } catch (err: any) { if (!err.notFound) { console.error(req.method, req.path, err); res.status(500).send('Internal server error'); return; } const collection: CollectionInfo = { name, label, }; await db.put(collectionKey, collection); res.format({ html: () => { res.redirect(303, `${req.baseUrl}/${collectionKey}/`); }, default: () => { res .status(201) .header('Location', `${req.baseUrl}/${collectionKey}/`) .header('Content-Location', `${req.baseUrl}/${collectionKey}/`); req.params.collection = name; getCollection(req, res); } }); } } export async function getCollection(req: Request, res: Response) { const collectionKey = `${req.params.user}/${req.params.collection}`; let collectionInfo: CollectionInfo; try { collectionInfo = await db.get(collectionKey); } catch (err: any) { if (err.notFound) { res.status(404).send('Not found'); } else { console.error(req.method, req.path, err); res.status(500).send('Internal server error'); } return; } const pageNumber = req.query.page ? Number.parseInt(req.query.page as string) : null; const iris = req.query.iris === '1'; const containerInfo = new Container(req, collectionKey, collectionInfo); try { const annotations = ( await getPrefixedEntries(db, `${collectionKey}/`, true) ).map(([_, value]) => value); // Sort most recent first (based on annotations’ self-reported modified/created date). annotations.sort((a, b) => (a.modified ?? a.created ?? '') < (b.modified ?? b.created ?? '') ? 1 : -1, ); const collection = new PagedContainer( req, collectionKey, collectionInfo, annotations.map((annotation) => expandAnnotation(annotation, containerInfo), ), ); if (pageNumber !== null) { sendPage(res, collection, pageNumber, iris); } else { // Embed the first page unless the client prefers otherwise. const embedFirstPage = req.headers.prefer?.includes( 'http://www.w3.org/ns/ldp#PreferMinimalContainer', ) ? false : true; sendContainer(req, res, collection, iris, embedFirstPage); } } catch (err: any) { if (err.notFound) { res.status(404).send('Not found'); } else { console.error(req.method, req.path, err); res.status(500).send('Internal server error'); } } } export async function deleteCollection(req: Request, res: Response) { const collectionKey = `${req.params.user}/${req.params.collection}`; try { await db.get(collectionKey); const entries = await getPrefixedEntries(db, `${collectionKey}/`); for (const [key, _] of entries) { await db.del(key); } await db.del(collectionKey); res.status(204).send(); } catch (err: any) { if (err.notFound) { res.status(404).send('Not found'); } else { console.error(req.method, req.path, err); res.status(500).send('Internal server error'); } return; } }