u
This commit is contained in:
118
src/store/attributevalue/addImage.js
Normal file
118
src/store/attributevalue/addImage.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import {
|
||||
ADD as MSSQL_ADD_AVPIC,
|
||||
DELETE_BY_ATTRIBUTE_VALUE as MSSQL_DELETE_AVPIC,
|
||||
} from '../../providers/mssql/queries/attributevaluepic.js';
|
||||
import {
|
||||
ADD as SQLITE_ADD_AVPIC,
|
||||
DELETE_BY_ATTRIBUTE_VALUE as SQLITE_DELETE_AVPIC,
|
||||
} from '../../providers/sqlite3/queries/attributevaluepic.js';
|
||||
import { CREATE as MSSQL_CREATE_PIC } from '../../providers/mssql/queries/pic.js';
|
||||
import { CREATE as SQLITE_CREATE_PIC } from '../../providers/sqlite3/queries/pic.js';
|
||||
import processAvifImage from '../../util/processAvifImage.js';
|
||||
import newFullHash from '../../util/newFullHash.js';
|
||||
import resolveAttributeValueAccess from './resolveAttributeValueAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function addImage(provider) {
|
||||
const access = resolveAttributeValueAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
|
||||
const deleteAvPicSql = isSqlite ? SQLITE_DELETE_AVPIC : MSSQL_DELETE_AVPIC;
|
||||
const createPicSql = isSqlite ? SQLITE_CREATE_PIC : MSSQL_CREATE_PIC;
|
||||
const addAvPicSql = isSqlite ? SQLITE_ADD_AVPIC : MSSQL_ADD_AVPIC;
|
||||
|
||||
/**
|
||||
* Adds an image to an attribute value, processing full, thumb, and 32px-edge small-thumb AVIF variants.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} attributeValueId - The id of the attribute value.
|
||||
* @param {Buffer} image - The source image buffer.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number, fullHash: string, thumbW: number, thumbH: number, thumbHash: string, smallThumbW: number, smallThumbH: number, pics: Array<object>}>}
|
||||
*/
|
||||
return async (googleAuthId, attributeValueId, image, tx) => {
|
||||
const runAdd = async (runner) => {
|
||||
await access(googleAuthId, attributeValueId, runner);
|
||||
|
||||
const processed = await processAvifImage(image);
|
||||
|
||||
// Clean existing attributevaluepic so the attribute value has 1 primary image
|
||||
await runner.query(deleteAvPicSql, { attributeValueId });
|
||||
|
||||
const sort = 0;
|
||||
const fullHash = newFullHash(processed.full.buffer);
|
||||
|
||||
let picId;
|
||||
const existingPic = await runner.query(
|
||||
'SELECT id FROM pic WHERE hash = @fullHash',
|
||||
{ fullHash },
|
||||
);
|
||||
|
||||
if (existingPic.rows[0]) {
|
||||
picId = existingPic.rows[0].id;
|
||||
} else {
|
||||
if (isSqlite) {
|
||||
if (runner.writePicFull) {
|
||||
await runner.writePicFull(fullHash, processed.full.buffer);
|
||||
await runner.writePicThumb(fullHash, processed.thumb.buffer);
|
||||
} else if (provider?.writePicFull) {
|
||||
await provider.writePicFull(fullHash, processed.full.buffer);
|
||||
await provider.writePicThumb(fullHash, processed.thumb.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
const picResult = await runner.query(createPicSql, {
|
||||
w: processed.full.w,
|
||||
h: processed.full.h,
|
||||
size: processed.full.size,
|
||||
hash: fullHash,
|
||||
thumbw: processed.thumb.w,
|
||||
thumbh: processed.thumb.h,
|
||||
thumbhash: processed.thumb.hash,
|
||||
smallthumbw: processed.smallThumb.w,
|
||||
smallthumbh: processed.smallThumb.h,
|
||||
smallthumbbinary: processed.smallThumb.buffer,
|
||||
source: '',
|
||||
fullbinary: processed.full.buffer,
|
||||
thumbbinary: processed.thumb.buffer,
|
||||
});
|
||||
|
||||
picId = picResult.rows[0]?.id ?? picResult.insertId;
|
||||
}
|
||||
|
||||
await runner.query(addAvPicSql, {
|
||||
attributeValueId,
|
||||
picId,
|
||||
sort,
|
||||
});
|
||||
|
||||
const picObj = {
|
||||
fullHash,
|
||||
thumbW: processed.thumb.w,
|
||||
thumbH: processed.thumb.h,
|
||||
thumbHash: processed.thumb.hash,
|
||||
smallThumbW: processed.smallThumb.w,
|
||||
smallThumbH: processed.smallThumb.h,
|
||||
};
|
||||
|
||||
return {
|
||||
id: attributeValueId,
|
||||
fullHash,
|
||||
thumbW: processed.thumb.w,
|
||||
thumbH: processed.thumb.h,
|
||||
thumbHash: processed.thumb.hash,
|
||||
smallThumbW: processed.smallThumb.w,
|
||||
smallThumbH: processed.smallThumb.h,
|
||||
pics: [picObj],
|
||||
};
|
||||
};
|
||||
|
||||
if (tx) {
|
||||
return runAdd(makeRunner(provider, tx));
|
||||
}
|
||||
if (typeof provider?.transaction === 'function') {
|
||||
return provider.transaction(runAdd);
|
||||
}
|
||||
return runAdd(makeRunner(provider));
|
||||
};
|
||||
}
|
||||
37
src/store/attributevalue/deleteImage.js
Normal file
37
src/store/attributevalue/deleteImage.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { DELETE_BY_ATTRIBUTE_VALUE as MSSQL_DELETE } from '../../providers/mssql/queries/attributevaluepic.js';
|
||||
import { DELETE_BY_ATTRIBUTE_VALUE as SQLITE_DELETE } from '../../providers/sqlite3/queries/attributevaluepic.js';
|
||||
import resolveAttributeValueAccess from './resolveAttributeValueAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function deleteImage(provider) {
|
||||
const access = resolveAttributeValueAccess(provider);
|
||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
|
||||
/**
|
||||
* Deletes the image of an attribute value.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} attributeValueId - The id of the attribute value.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<{id: number, thumbW: null, thumbH: null, thumbHash: null, pics: Array}>}
|
||||
* @throws {Error} If attribute value not found or image not found.
|
||||
*/
|
||||
return async (googleAuthId, attributeValueId, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
await access(googleAuthId, attributeValueId, runner);
|
||||
|
||||
const result = await runner.query(sql, { attributeValueId });
|
||||
|
||||
if (!result.rowsAffected) {
|
||||
throw new Error('Image not found');
|
||||
}
|
||||
|
||||
return {
|
||||
id: attributeValueId,
|
||||
thumbW: null,
|
||||
thumbH: null,
|
||||
thumbHash: null,
|
||||
pics: [],
|
||||
};
|
||||
};
|
||||
}
|
||||
22
src/store/attributevalue/resolveAttributeValueAccess.js
Normal file
22
src/store/attributevalue/resolveAttributeValueAccess.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { GET_BY_ID_AND_COMPANY as MSSQL_GET } from '../../providers/mssql/queries/attributevalue.js';
|
||||
import { GET_BY_ID_AND_COMPANY as SQLITE_GET } from '../../providers/sqlite3/queries/attributevalue.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function resolveAttributeValueAccess(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_GET : MSSQL_GET;
|
||||
|
||||
return async (googleAuthId, attributeValueId, tx) => {
|
||||
if (!Number.isFinite(attributeValueId) || attributeValueId <= 0) {
|
||||
throw new Error('Attribute value not found');
|
||||
}
|
||||
const { companyId } = await access(googleAuthId, tx);
|
||||
const runner = makeRunner(provider, tx);
|
||||
const result = await runner.query(sql, { id: attributeValueId, companyId });
|
||||
if (!result.rows[0]) {
|
||||
throw new Error('Attribute value not found');
|
||||
}
|
||||
return { companyId, attributeValue: result.rows[0] };
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user