const router = require('express-promise-router')() const db = require('../db') const ensureAdmin = require('./middleware/ensureAdmin') const fs = require('fs'); const path = require('path'); const cacheRoot = path.join(__dirname, '../cache/images') fs.promises.mkdir(cacheRoot, {recursive: true}) .catch(() => console.error("Could not create image cache dir: " + cacheRoot)); const memCache = {}; async function writeImageFile(uuid, size, data) { if(size !== 'thumb' && size !== 'large') throw new Error(`Unknown image size ${size}`); await fs.promises.writeFile(path.join(cacheRoot, `${uuid}-${size}`), data); } async function getImage(uuid, size) { // If we've already stored a mime type, that means we've written the file to disk if(memCache[`${uuid}-${size}`]?.mime_type) { return { file: fs.createReadStream(path.join(cacheRoot, `${uuid}-${size}`)), mime_type: memCache[`${uuid}-${size}`].mime_type } } // If we've stored a promise, that means we're currently retrieving it from the db if(memCache[`${uuid}-${size}`]?.dbPromise) { return await memCache[`${uuid}-${size}`]?.dbPromise; } // Otherwise, retrieve it from the DB, and then write it to disk const record = memCache[`${uuid}-${size}`] = {}; record.dbPromise = db.item.getImage(uuid, size); const image = await record.dbPromise; await writeImageFile(uuid, size, image.file); record.mime_type = image.mime_type; delete record.dbPromise; return image; } router.get('/:uuid/:size', async (req, res) => { const image = await getImage(req.params.uuid, req.params.size) const cacheSeconds = 60 * 60 * 24; res.set('Cache-Control', cacheSeconds); res.set('Content-Type', image.mime_type) if(Buffer.isBuffer(image.file)) res.end(image.file) else if (typeof image.file.pipe === 'function') image.file.pipe(res) else throw new Error("Unable to send file to user"); }) router.post('/:uuid/featured', ensureAdmin, async (req, res) => { const item = await db.item.setFeatured(req.params.uuid) res.json(item) }) router.delete('/:uuid', ensureAdmin, async (req, res) => { const item = await db.item.removeImage(req.params.uuid) res.json(item) }) module.exports = router