UNPKG

fast-back-blaze

Version:

A Node.js module to simplify BackBlaze R2 interactions, providing an instance-based API for uploads, deletions, and URL generation.

138 lines (126 loc) 6.97 kB
// src/index.js const { S3Client, PutObjectCommand, DeleteObjectCommand } = require('@aws-sdk/client-s3'); const BackblazeB2Error = require('./utils/errorHandling'); // Import custom error handler, renamed from R2Error /** * Creates an instance of the Backblaze B2 client with methods for file operations. * @param {object} options - Configuration options for Backblaze B2. * @param {string} options.accessKeyId - Your Backblaze B2 Application Key ID. * @param {string} options.secretAccessKey - Your Backblaze B2 Application Key. * @param {string} options.bucketName - The name of your Backblaze B2 bucket. * @param {string} options.endpoint - The S3 compatible endpoint URL for your Backblaze B2 bucket (e.g., 'https://s3.us-west-001.backblazeb2.com'). * @param {string} [options.region] - The region for your Backblaze B2 bucket (e.g., 'us-west-001'). This is used for constructing the endpoint if not provided. * @returns {object} An object containing uploadFile, deleteFile, and getFileUrl methods. */ function createBackblazeB2({ accessKeyId, secretAccessKey, bucketName, endpoint, region }) { // Validate required options if (!accessKeyId || !secretAccessKey || !bucketName) { throw new BackblazeB2Error('Backblaze B2: accessKeyId, secretAccessKey, and bucketName are required to create an instance.'); } // Determine the B2 endpoint let b2Endpoint = endpoint; if (!b2Endpoint) { if (!region) { throw new BackblazeB2Error('Backblaze B2: Either endpoint or region must be provided.'); } b2Endpoint = `https://s3.${region}.backblazeb2.com`; } // Initialize the S3Client configured for Backblaze B2 const b2 = new S3Client({ region: region || 'us-west-001', // Backblaze B2 requires a specific region, even if endpoint is provided endpoint: b2Endpoint, credentials: { accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, }, // Backblaze B2 typically uses path-style access forcePathStyle: true, }); /** * Uploads a file to the configured Backblaze B2 bucket. * Provides comprehensive information about the uploaded file upon success. * @param {Buffer} fileBuffer - The binary data of the file to upload. * @param {string} fileName - The desired key (path and name) for the file in B2 (e.g., 'users/123/profile.jpg'). * @param {string} contentType - The MIME type of the file (e.g., 'image/jpeg', 'video/mp4'). * @returns {Promise<object>} A promise that resolves to an object with upload details: * { Key: string, ETag: string, Bucket: string, Location: string (public URL), ContentType: string, Size: number } * @throws {BackblazeB2Error} If the upload operation fails. */ const uploadFile = async (fileBuffer, fileName, contentType) => { const params = { Bucket: bucketName, Key: fileName, Body: fileBuffer, ContentType: contentType, }; try { const command = new PutObjectCommand(params); const data = await b2.send(command); // Construct the public URL. This assumes your B2 bucket is configured for public access. // For private buckets, you would typically generate a pre-signed URL here or on demand. // Backblaze B2 public URLs are typically in the format: // https://f00X.backblazeb2.com/file/yourBucketName/yourFileName // The `s3Endpoint` is not used for public URLs directly in this fashion. // You will need to know your friendly URL or use the B2 native download URL structure. // For simplicity, we'll construct a URL based on the S3 endpoint for now, but // be aware that Backblaze B2's public URLs are different. // A more robust solution might involve retrieving the friendly URL from B2 API or // having it configured externally. const publicUrl = `${b2Endpoint}/${bucketName}/${fileName}`; // This might not be the actual public URL return { Key: fileName, ETag: data.ETag ? data.ETag.replace(/"/g, '') : undefined, // Remove quotes from ETag if present Bucket: bucketName, Location: publicUrl, // The full public URL of the uploaded file (needs refinement for true B2 public URL) ContentType: contentType, Size: fileBuffer.length // Size of the uploaded content in bytes }; } catch (error) { console.error(`Error uploading file '${fileName}' to Backblaze B2 bucket '${bucketName}':`, error); throw new BackblazeB2Error(`Failed to upload file '${fileName}'.`, error); } }; /** * Deletes a file from the configured Backblaze B2 bucket. * @param {string} fileName - The key (path and name) of the file to delete from B2. * @returns {Promise<void>} A promise that resolves upon successful deletion. * @throws {BackblazeB2Error} If the deletion operation fails. */ const deleteFile = async (fileName) => { const params = { Bucket: bucketName, Key: fileName, }; try { const command = new DeleteObjectCommand(params); await b2.send(command); } catch (error) { console.error(`Error deleting file '${fileName}' from Backblaze B2 bucket '${bucketName}':`, error); throw new BackblazeB2Error(`Failed to delete file '${fileName}'.`, error); } }; /** * Generates the public URL for a file in the configured Backblaze B2 bucket. * This function assumes the B2 bucket is configured for public access. * For private buckets, you would need to generate a pre-signed URL. * IMPORTANT: This method constructs a URL based on the S3 compatible endpoint. * For true public download URLs from Backblaze B2, you often need to use the B2 native * download URL format (e.g., https://f00X.backblazeb2.com/file/yourBucketName/yourFileName) * which typically requires knowing your "friendly URL" or making an additional B2 API call. * This function provides the S3-compatible URL. * @param {string} fileName - The key (path and name) of the file. * @returns {string} The public URL of the file. */ const getFileUrl = (fileName) => { if (!fileName) { throw new BackblazeB2Error('File name is required to generate a URL.'); } return `${b2Endpoint}/${bucketName}/${fileName}`; }; // Return the public API of the Backblaze B2 client instance return { uploadFile, deleteFile, getFileUrl, }; } module.exports = createBackblazeB2;