
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A comprehensive TypeScript library for generating thumbnails from images, PDFs, videos, office documents, and archives.
A comprehensive TypeScript library for generating thumbnails from various file formats including images, PDFs, videos, office documents, and archives.
npm install universal-thumbnail-generator
The package requires some peer dependencies based on what file types you want to support:
# For basic image and PDF support (always required)
npm install sharp canvas pdfjs-dist
# For video thumbnail support (optional)
npm install ffmpeg-static
# For office document support (optional)
npm install libreoffice-convert
import { UniversalThumbnailGenerator } from "universal-thumbnail-generator";
const generator = new UniversalThumbnailGenerator({
width: 300,
height: 300,
quality: 90,
format: "jpeg",
});
// Generate thumbnail from file path
const result = await generator.generate("./path/to/image.jpg");
// Generate thumbnail from buffer
const fileBuffer = await fs.readFile("./document.pdf");
const result = await generator.generate(fileBuffer, "document.pdf");
// Save the thumbnail
await fs.writeFile(result.fileName, result.fileBuffer);
interface ThumbnailConfig {
width?: number; // Default: 200
height?: number; // Default: 200
quality?: number; // Default: 80 (1-100)
suffix?: string; // Default: '_thumb'
format?: "jpeg" | "png" | "webp" | "avif"; // Default: 'jpeg'
fit?: "cover" | "contain" | "fill" | "inside" | "outside"; // Default: 'inside'
withoutEnlargement?: boolean; // Default: true
background?: {
// Default: white
r: number;
g: number;
b: number;
alpha: number;
};
position?: string; // Default: 'center'
}
import { UniversalThumbnailGenerator } from "universal-thumbnail-generator";
const generator = new UniversalThumbnailGenerator();
// From file path
const thumbnail = await generator.generate("./image.jpg");
// From buffer with filename
const buffer = await fs.readFile("./document.pdf");
const thumbnail = await generator.generate(buffer, "document.pdf");
// From FileInput object
const thumbnail = await generator.generate({
buffer: fileBuffer,
fileName: "presentation.pptx",
});
const generator = new UniversalThumbnailGenerator({
width: 400,
height: 300,
quality: 95,
format: "webp",
fit: "cover",
background: { r: 240, g: 240, b: 240, alpha: 1 },
suffix: "_preview",
});
const thumbnail = await generator.generate("./video.mp4");
const files = [
"./image1.jpg",
"./document.pdf",
{ buffer: videoBuffer, fileName: "video.mp4" },
];
const batchResult = await generator.generateBatch(files, {
width: 150,
height: 150,
});
console.log(`Generated ${batchResult.results.length} thumbnails`);
console.log(`Failed: ${batchResult.errors.length} files`);
// Process results
batchResult.results.forEach(async (result) => {
await fs.writeFile(`./thumbnails/${result.fileName}`, result.fileBuffer);
});
// Handle errors
batchResult.errors.forEach((error) => {
console.error(`Error processing ${error.fileName}: ${error.error}`);
});
const generator = new UniversalThumbnailGenerator();
// Override config for specific generation
const thumbnail = await generator.generate("./image.jpg", undefined, {
width: 500,
height: 500,
format: "png",
});
// Update global config
generator.updateConfig({
quality: 100,
format: "avif",
});
// Reset to defaults
generator.resetConfig();
new UniversalThumbnailGenerator(options?: ThumbnailConfig)
generate(input, fileName?, options?)Generate a single thumbnail.
Parameters:
input: Buffer | string | FileInput - File buffer, path, or FileInput objectfileName?: string - Required when input is Bufferoptions?: Partial<ThumbnailConfig> - Override default configReturns: Promise<ThumbnailResult>
generateBatch(files, options?)Generate multiple thumbnails.
Parameters:
files: Array<string | FileInput> - Array of file paths or FileInput objectsoptions?: Partial<ThumbnailConfig> - Override default configReturns: Promise<BatchResult>
isSupported(fileName)Check if file type is supported.
Parameters:
fileName: string - File name with extensionReturns: boolean
getFileType(fileName)Get file type category.
Parameters:
fileName: string - File name with extensionReturns: FileType - 'image' | 'document' | 'video' | 'office' | 'archive' | 'unsupported'
getSupportedTypes()Get all supported file extensions grouped by category.
Returns: SupportedTypes
getSupportedExtensions()Get flat array of all supported extensions.
Returns: string[]
updateConfig(newConfig)Update configuration.
Parameters:
newConfig: Partial<ThumbnailConfig> - New configuration optionsgetConfig()Get current configuration.
Returns: Required<ThumbnailConfig>
resetConfig()Reset configuration to defaults.
interface ThumbnailResult {
fileName: string; // Generated thumbnail filename
originalFileName: string; // Original file name
fileBuffer: Buffer; // Thumbnail image buffer
fileSizeInBytes: number; // Thumbnail file size
mimeType: string; // Output MIME type
md5Hash: string; // MD5 hash of thumbnail
fileType: FileType; // File type category
dimensions: {
// Thumbnail dimensions
width: number;
height: number;
};
quality: number; // Quality setting used
createdAt: string; // ISO timestamp
isThumbnail: boolean; // Always true
metadata?: Record<string, any>; // Additional metadata
}
interface BatchResult {
results: ThumbnailResult[];
errors: Array<{
index: number;
fileName?: string;
error: string;
}>;
}
The library provides detailed error messages for different failure scenarios:
try {
const thumbnail = await generator.generate("./invalid-file.xyz");
} catch (error) {
if (error.message.includes("Unsupported file type")) {
console.log("File type not supported");
} else if (error.message.includes("generation failed")) {
console.log("Processing error:", error.message);
}
}
generateBatch() for multiple files to improve performanceimport express from "express";
import multer from "multer";
import { UniversalThumbnailGenerator } from "universal-thumbnail-generator";
const app = express();
const upload = multer();
const generator = new UniversalThumbnailGenerator({
width: 200,
height: 200,
quality: 80,
});
app.post("/upload", upload.single("file"), async (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ error: "No file uploaded" });
}
const thumbnail = await generator.generate(
req.file.buffer,
req.file.originalname
);
res.json({
success: true,
thumbnail: {
fileName: thumbnail.fileName,
size: thumbnail.fileSizeInBytes,
dimensions: thumbnail.dimensions,
},
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
import { UniversalThumbnailGenerator } from "universal-thumbnail-generator";
import { promises as fs } from "fs";
import path from "path";
async function processDirectory(inputDir: string, outputDir: string) {
const generator = new UniversalThumbnailGenerator({
width: 300,
height: 300,
quality: 85,
format: "webp",
});
const files = await fs.readdir(inputDir);
const supportedFiles = files.filter((file) => generator.isSupported(file));
console.log(`Processing ${supportedFiles.length} supported files...`);
const filePaths = supportedFiles.map((file) => path.join(inputDir, file));
const batchResult = await generator.generateBatch(filePaths);
// Save thumbnails
for (const result of batchResult.results) {
const outputPath = path.join(outputDir, result.fileName);
await fs.writeFile(outputPath, result.fileBuffer);
console.log(`✓ Generated: ${result.fileName}`);
}
// Report errors
for (const error of batchResult.errors) {
console.error(`✗ Failed: ${error.fileName} - ${error.error}`);
}
console.log(
`\nCompleted: ${batchResult.results.length} thumbnails generated`
);
}
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter any issues or have questions, please file an issue on the GitHub repository.
FAQs
A comprehensive TypeScript library for generating thumbnails from images, PDFs, videos, office documents, and archives.
We found that thumbkit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.