import { GET_CATEGORY_ID_BY_SKU } from '../../sql/article.js'; import { ADD as ADD_ARTICLEPIC, GET_NEXT_SORT } from '../../sql/articlepic.js'; import { CREATE as CREATE_PIC } from '../../sql/pic.js'; import processAvifImage from '../../util/processAvifImage.js'; import newFullHash from '../../util/newFullHash.js'; import resolveCategoryAccess from '../category/resolveCategoryAccess.js'; import request from '../request.js'; export default function addImage(pool) { const access = resolveCategoryAccess(pool); return async (googleAuthId, sku, image) => { const categoryLookup = await pool .request() .input('sku', sku) .query(GET_CATEGORY_ID_BY_SKU); const row = categoryLookup.recordset[0]; if (!row?.categoryId || !row?.articleId) { throw new Error('Article not found'); } await access(googleAuthId, row.categoryId); const processed = await processAvifImage(image); const tx = pool.transaction(); await tx.begin(); try { const sortResult = await request(pool, tx) .input('articleId', row.articleId) .query(GET_NEXT_SORT); const sort = sortResult.recordset[0].sort; const fullHash = newFullHash(); const picResult = await request(pool, tx) .input('w', processed.full.w) .input('h', processed.full.h) .input('size', processed.full.size) .input('hash', fullHash) .input('thumbw', processed.thumb.w) .input('thumbh', processed.thumb.h) .input('thumbhash', processed.thumb.hash) .input('source', '') .input('fullbinary', processed.full.buffer) .input('thumbbinary', processed.thumb.buffer) .query(CREATE_PIC); const picId = picResult.recordset[0].id; await request(pool, tx) .input('articleId', row.articleId) .input('picId', picId) .input('sort', sort) .query(ADD_ARTICLEPIC); await tx.commit(); return { picId, sort, full: { w: processed.full.w, h: processed.full.h, size: processed.full.size, }, thumb: { w: processed.thumb.w, h: processed.thumb.h, }, fullHash, thumbHash: processed.thumb.hash, }; } catch (err) { try { await tx.rollback(); } catch { // ignore } throw err; } }; }