@coko/server
Version:
Reusable server for use by Coko's projects
136 lines • 6.65 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.up = up;
const path_1 = __importDefault(require("path"));
const consumers_1 = require("stream/consumers");
const fs_extra_1 = __importDefault(require("fs-extra"));
const mime_types_1 = __importDefault(require("mime-types"));
const sharp_1 = __importDefault(require("sharp"));
const lib_storage_1 = require("@aws-sdk/lib-storage");
const config_1 = __importDefault(require("../../../configManager/config"));
const useTransaction_1 = __importDefault(require("../../useTransaction"));
const file_model_1 = __importDefault(require("../file.model"));
const filesystem_1 = require("../../../utils/filesystem");
const fileStorage_1 = __importDefault(require("../../../fileStorage"));
/**
* Some light duplication of code in this file, in order to keep it from being
* a blocker for refactoring or other changes.
* (eg. we made uploadFileHandler a private method, so it wouldn't be available here)
*/
const imageSizeConversionMapper = {
tiff: {
full: 'png',
},
tif: {
full: 'png',
},
svg: {
full: 'svg',
},
png: {
full: 'png',
},
default: {
full: 'jpeg',
},
};
const getMetadata = async (fileBuffer) => {
const originalImage = (0, sharp_1.default)(fileBuffer, { limitInputPixels: false });
const imageMetadata = await originalImage.metadata();
return imageMetadata;
};
const sharpConversionFullFilePath = async (bufferData, tempFileDir, filenameWithoutExtension, format) => {
await fs_extra_1.default.ensureDir(tempFileDir);
const tempFullFilePath = path_1.default.join(tempFileDir, `${filenameWithoutExtension}_full.${imageSizeConversionMapper[format]
? imageSizeConversionMapper[format].full
: imageSizeConversionMapper.default.full}`);
await (0, sharp_1.default)(bufferData).toFile(tempFullFilePath);
return tempFullFilePath;
};
const uploadFileHandler = async (fileStream, filename, mimetype) => {
const params = {
Bucket: fileStorage_1.default.bucket,
Key: filename, // file name you want to save as
Body: fileStream,
ContentType: mimetype,
};
const upload = new lib_storage_1.Upload({
client: fileStorage_1.default.s3,
params,
});
// upload.on('httpUploadProgress', progress => {
// console.log(progress)
// })
const data = await upload.done();
const { Key } = data;
return { key: Key };
};
async function up() {
/**
* If the app didn't use file storage before or after, this migration is unnecessary.
*
* If the app didn't use file storage before this migration, but started using
* it after, this migration is unnecessary (new files will have a full quallity version).
*
* If the app used file storage before this migration, but stopped using it
* before this migration, it is assumed that the files in file storage are
* not used any more, so this migration will be skipped.
*
* There is an edge case where the app used file storage, stopped for a while,
* in which period this migration ran, then started using it again, and the
* files are still used. In this case this migration will need to be run manually.
*/
if (!config_1.default.get('fileStorage'))
return;
try {
await (0, useTransaction_1.default)(async (trx) => {
const files = await file_model_1.default.query(trx);
const tempDir = filesystem_1.tempFolderPath;
await fs_extra_1.default.ensureDir(tempDir);
await Promise.all(files.map(async (file) => {
const mimetype = mime_types_1.default.lookup(file.name);
const fullStoredObject = file.storedObjects.find(storedObject => storedObject.type === 'full');
if (mimetype && mimetype.match(/^image\//) && !fullStoredObject) {
const tempFileDir = path_1.default.join(tempDir, file.id);
await fs_extra_1.default.ensureDir(tempFileDir);
const originalStoredObject = file.storedObjects.find(storedObject => storedObject.type === 'original');
const filenameWithoutExtension = path_1.default.parse(originalStoredObject.key).name;
const tempPath = path_1.default.join(tempFileDir, originalStoredObject.key);
await fileStorage_1.default.download(originalStoredObject.key, tempPath);
const format = originalStoredObject.extension;
const bufferData = fs_extra_1.default.readFileSync(tempPath);
const tempFullFilePath = await sharpConversionFullFilePath(bufferData, tempFileDir, filenameWithoutExtension, format);
fs_extra_1.default.unlinkSync(tempPath);
const fullImageStream = fs_extra_1.default.createReadStream(tempFullFilePath);
const full = await uploadFileHandler(fs_extra_1.default.createReadStream(tempFullFilePath), path_1.default.basename(tempFullFilePath), mime_types_1.default.lookup(tempFullFilePath));
const fullFileBuffer = await (0, consumers_1.buffer)(fullImageStream);
const { width: fWidth, height: fHeight, space: fSpace, density: fDensity, size: fSize, } = await getMetadata(fullFileBuffer);
full.imageMetadata = {
density: fDensity,
height: fHeight,
space: fSpace,
width: fWidth,
};
full.size = fSize;
full.extension = path_1.default.extname(tempFullFilePath).slice(1);
full.type = 'full';
full.mimetype = mime_types_1.default.lookup(tempFullFilePath);
file.storedObjects.push(full);
await file_model_1.default.query(trx).patchAndFetchById(file.id, {
storedObjects: file.storedObjects,
});
fs_extra_1.default.unlinkSync(tempFullFilePath);
}
}));
await fs_extra_1.default.emptyDir(tempDir);
return true;
});
}
catch (e) {
throw new Error(`'File: Add full conversion image quality to stored objects migration failed!' ${e}`);
}
}
//# sourceMappingURL=1698750314-add-full-quality-converted-object-to-storedobjects.js.map