@bernierllc/content-type-image
v1.2.0
Published
Base image content type with file upload, local storage, and URL publishing
Readme
@bernierllc/content-type-image
Base image content type providing file upload, local storage, and URL publishing with extensibility for specialized image types (Instagram posts, thumbnails, galleries).
Installation
npm install @bernierllc/content-type-imageUsage
import { ImageContentType } from '@bernierllc/content-type-image';
import * as fs from 'fs/promises';
// Initialize with default configuration
const imageType = new ImageContentType();
// Or with custom configuration
const customImageType = new ImageContentType({
uploadDirectory: './uploads/images',
publicUrlBase: '/images',
maxFileSize: 10 * 1024 * 1024, // 10MB
allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
});
// Register with content type registry
await imageType.register();
// Upload an image
const imageBuffer = await fs.readFile('photo.jpg');
const result = await imageType.upload(
imageBuffer,
'photo.jpg',
'image/jpeg',
'A beautiful photo'
);
if (result.success) {
console.log('Image uploaded:', result.data.publicUrl);
console.log('Metadata:', result.data.metadata);
}
// Retrieve an image
const image = await imageType.get(result.data.localPath);
// Get public URL
const url = imageType.getPublicUrl(result.data.localPath);
// Check if image exists
const exists = await imageType.exists(result.data.localPath);
// Delete an image
const deleted = await imageType.delete(result.data.localPath);API Reference
ImageContentType
Main class for handling image content type operations.
Constructor
constructor(config?: Partial<ImageContentTypeConfig>)Configuration Options:
uploadDirectory(string): Directory for storing uploaded images (default:'./uploads/images')publicUrlBase(string): Base URL for public image access (default:'/images')maxFileSize(number): Maximum file size in bytes (default:10485760- 10MB)allowedMimeTypes(string[]): Allowed MIME types (default:['image/jpeg', 'image/png', 'image/gif', 'image/webp'])
Methods
register(): Promise<void>
Register the image content type with the content type registry.
upload(file: Buffer, filename: string, mimeType: string, alt?: string): Promise<ImageUploadResult>
Upload an image file.
Parameters:
file- Image file bufferfilename- Original filenamemimeType- MIME type of the imagealt- Optional alt text for accessibility
Returns:
{
success: boolean;
data?: {
localPath: string;
publicUrl: string;
metadata: ImageMetadata;
};
error?: string;
}validate(file: Buffer, mimeType: string): Promise<ImageValidationResult>
Validate an image file without uploading.
Returns:
{
valid: boolean;
error?: string;
metadata?: Partial<ImageMetadata>;
}get(localPath: string): Promise<Buffer | null>
Retrieve an uploaded image by local path.
delete(localPath: string): Promise<boolean>
Delete an uploaded image.
exists(localPath: string): Promise<boolean>
Check if an image exists.
getPublicUrl(localPath: string): string
Get the public URL for an image.
Configuration
Environment Variables
# Maximum file size in bytes (default: 10485760)
IMAGE_MAX_FILE_SIZE=10485760
# Upload directory (default: ./uploads/images)
IMAGE_UPLOAD_DIR=./uploads/images
# Public URL base path (default: /images)
IMAGE_PUBLIC_URL_BASE=/images
# Allowed MIME types (comma-separated, default: image/jpeg,image/png,image/gif,image/webp)
IMAGE_ALLOWED_TYPES=image/jpeg,image/png,image/gif,image/webpConfiguration Precedence
- Environment variables (lowest priority)
- Constructor options (highest priority)
Types
ImageMetadata
interface ImageMetadata {
filename: string;
mimeType: 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';
size: number;
width: number;
height: number;
alt?: string;
uploadedAt?: Date;
}ImageContent
interface ImageContent {
localPath: string;
publicUrl?: string;
metadata: ImageMetadata;
}Integration Status
- Logger: not-applicable - Core content type package with standard error handling
- Docs-Suite: ready - Complete TypeDoc API documentation
- NeverHub: not-applicable - Core package; services using this handle NeverHub integration
Examples
Basic Upload
import { ImageContentType } from '@bernierllc/content-type-image';
import * as fs from 'fs/promises';
const imageType = new ImageContentType();
const photo = await fs.readFile('profile.jpg');
const result = await imageType.upload(photo, 'profile.jpg', 'image/jpeg', 'Profile photo');
if (result.success) {
console.log('Uploaded to:', result.data.publicUrl);
}Validation Before Upload
const imageType = new ImageContentType({
maxFileSize: 5 * 1024 * 1024, // 5MB limit
});
const photo = await fs.readFile('large-photo.jpg');
const validation = await imageType.validate(photo, 'image/jpeg');
if (validation.valid) {
const result = await imageType.upload(photo, 'large-photo.jpg', 'image/jpeg');
console.log('Upload successful:', result.data.publicUrl);
} else {
console.error('Validation failed:', validation.error);
}Complete Workflow
const imageType = new ImageContentType();
// Upload
const photo = await fs.readFile('photo.jpg');
const uploadResult = await imageType.upload(photo, 'photo.jpg', 'image/jpeg', 'Vacation');
if (uploadResult.success) {
const { localPath, publicUrl, metadata } = uploadResult.data;
// Retrieve
const image = await imageType.get(localPath);
// Check existence
const exists = await imageType.exists(localPath);
// Delete
await imageType.delete(localPath);
}Custom Storage Configuration
const imageType = new ImageContentType({
uploadDirectory: '/var/www/uploads/images',
publicUrlBase: 'https://cdn.example.com/images',
maxFileSize: 20 * 1024 * 1024, // 20MB
allowedMimeTypes: ['image/jpeg', 'image/png'],
});
const result = await imageType.upload(imageBuffer, 'photo.jpg', 'image/jpeg');
// Public URL: https://cdn.example.com/images/1234567890-abc123.jpgError Handling
const imageType = new ImageContentType();
const result = await imageType.upload(imageBuffer, 'photo.bmp', 'image/bmp');
if (!result.success) {
console.error('Upload failed:', result.error);
// "Invalid MIME type: image/bmp. Allowed: image/jpeg, image/png, image/gif, image/webp"
}Extensibility
This package serves as the foundation for specialized image content types:
- @bernierllc/content-type-instagram-post - Extends with Instagram validation
- @bernierllc/content-type-facebook-post - Uses for image attachments
- @bernierllc/content-type-thumbnail - Specialized thumbnail generation
- @bernierllc/content-type-gallery - Multi-image galleries
Extending ImageContentType
import { ImageContentType } from '@bernierllc/content-type-image';
class InstagramImageType extends ImageContentType {
async upload(file: Buffer, filename: string, mimeType: string, alt?: string) {
// Instagram-specific validation
const validation = await this.validateForInstagram(file);
if (!validation.valid) {
return { success: false, error: validation.error };
}
// Use parent upload
return super.upload(file, filename, mimeType, alt);
}
private async validateForInstagram(file: Buffer) {
// Instagram-specific dimension/aspect ratio checks
return { valid: true };
}
}See Also
- @bernierllc/content-type-registry - Content type registration and management
- @bernierllc/content-type-instagram-post - Instagram post content type
- @bernierllc/content-type-facebook-post - Facebook post content type
- @bernierllc/content-management-suite - Complete content management system
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
