# @push.rocks/smartbucket ๐Ÿชฃ > A powerful, cloud-agnostic TypeScript library for object storage with advanced features like file locking, metadata management, and intelligent trash handling. ## Install ๐Ÿ“ฆ To install `@push.rocks/smartbucket`, run: ```bash npm install @push.rocks/smartbucket --save ``` Or if you're using pnpm (recommended): ```bash pnpm add @push.rocks/smartbucket ``` ## Usage ๐Ÿš€ ### Introduction `@push.rocks/smartbucket` provides a unified, cloud-agnostic API for object storage operations across major providers like AWS S3, Google Cloud Storage, MinIO, and more. It abstracts away provider-specific complexities while offering advanced features like metadata management, file locking, streaming operations, and intelligent trash management. ### Table of Contents 1. [๐Ÿ Getting Started](#-getting-started) 2. [๐Ÿ—‚๏ธ Working with Buckets](#๏ธ-working-with-buckets) 3. [๐Ÿ“ File Operations](#-file-operations) 4. [๐Ÿ“‚ Directory Management](#-directory-management) 5. [๐ŸŒŠ Streaming Operations](#-streaming-operations) 6. [๐Ÿ”’ File Locking](#-file-locking) 7. [๐Ÿท๏ธ Metadata Management](#๏ธ-metadata-management) 8. [๐Ÿ—‘๏ธ Trash & Recovery](#๏ธ-trash--recovery) 9. [โšก Advanced Features](#-advanced-features) 10. [โ˜๏ธ Cloud Provider Support](#๏ธ-cloud-provider-support) ### ๐Ÿ Getting Started First, set up your storage connection: ```typescript import { SmartBucket } from '@push.rocks/smartbucket'; // Initialize with your cloud storage credentials const smartBucket = new SmartBucket({ accessKey: 'your-access-key', accessSecret: 'your-secret-key', endpoint: 's3.amazonaws.com', // Or your provider's endpoint port: 443, useSsl: true, region: 'us-east-1' // Optional, defaults to 'us-east-1' }); ``` ### ๐Ÿ—‚๏ธ Working with Buckets #### Creating Buckets ```typescript // Create a new bucket const myBucket = await smartBucket.createBucket('my-awesome-bucket'); console.log(`โœ… Bucket created: ${myBucket.name}`); ``` #### Getting Existing Buckets ```typescript // Get a bucket reference const existingBucket = await smartBucket.getBucketByName('existing-bucket'); // Or use strict mode (throws if bucket doesn't exist) const bucketStrict = await smartBucket.getBucketByNameStrict('must-exist-bucket'); ``` #### Removing Buckets ```typescript // Delete a bucket (must be empty) await smartBucket.removeBucket('old-bucket'); console.log('๐Ÿ—‘๏ธ Bucket removed'); ``` ### ๐Ÿ“ File Operations #### Upload Files ```typescript const bucket = await smartBucket.getBucketByName('my-bucket'); // Simple file upload await bucket.fastPut({ path: 'documents/report.pdf', contents: Buffer.from('Your file content here') }); // Upload with string content await bucket.fastPut({ path: 'notes/todo.txt', contents: 'Buy milk\nCall mom\nRule the world' }); // Strict upload (returns File object) const uploadedFile = await bucket.fastPutStrict({ path: 'images/logo.png', contents: imageBuffer, overwrite: true // Optional: control overwrite behavior }); ``` #### Download Files ```typescript // Get file as Buffer const fileContent = await bucket.fastGet({ path: 'documents/report.pdf' }); console.log(`๐Ÿ“„ File size: ${fileContent.length} bytes`); // Get file as string const textContent = fileContent.toString('utf-8'); ``` #### Check File Existence ```typescript const exists = await bucket.fastExists({ path: 'documents/report.pdf' }); console.log(`File exists: ${exists ? 'โœ…' : 'โŒ'}`); ``` #### Delete Files ```typescript // Permanent deletion await bucket.fastRemove({ path: 'old-file.txt' }); ``` #### Copy & Move Files ```typescript // Copy file within bucket await bucket.fastCopy({ sourcePath: 'original/file.txt', destinationPath: 'backup/file-copy.txt' }); // Move file (copy + delete original) await bucket.fastMove({ sourcePath: 'temp/draft.txt', destinationPath: 'final/document.txt' }); ``` ### ๐Ÿ“‚ Directory Management SmartBucket provides powerful directory-like operations for organizing your files: ```typescript // Get base directory const baseDir = await bucket.getBaseDirectory(); // List directories and files const directories = await baseDir.listDirectories(); const files = await baseDir.listFiles(); console.log(`๐Ÿ“ Found ${directories.length} directories`); console.log(`๐Ÿ“„ Found ${files.length} files`); // Navigate subdirectories const subDir = await baseDir.getSubDirectoryByName('projects/2024'); // Create nested file await subDir.fastPut({ path: 'report.pdf', contents: reportBuffer }); // Get directory tree structure const tree = await subDir.getTreeArray(); console.log('๐ŸŒณ Directory tree:', tree); // Create empty file as placeholder await subDir.createEmptyFile('placeholder.txt'); ``` ### ๐ŸŒŠ Streaming Operations Handle large files efficiently with streaming: #### Download Streams ```typescript // Node.js stream const nodeStream = await bucket.fastGetStream( { path: 'large-video.mp4' }, 'nodestream' ); nodeStream.pipe(fs.createWriteStream('local-video.mp4')); // Web stream (for modern environments) const webStream = await bucket.fastGetStream( { path: 'large-file.zip' }, 'webstream' ); ``` #### Upload Streams ```typescript // Stream upload from file const readStream = fs.createReadStream('big-data.csv'); await bucket.fastPutStream({ path: 'uploads/big-data.csv', stream: readStream, metadata: { contentType: 'text/csv', userMetadata: { uploadedBy: 'data-team', version: '2.0' } } }); ``` #### Reactive Streams with RxJS ```typescript // Get file as ReplaySubject for reactive programming const replaySubject = await bucket.fastGetReplaySubject({ path: 'data/sensor-readings.json', chunkSize: 1024 }); replaySubject.subscribe({ next: (chunk) => processChunk(chunk), complete: () => console.log('โœ… Stream complete') }); ``` ### ๐Ÿ”’ File Locking Prevent accidental modifications with file locking: ```typescript const file = await bucket.getBaseDirectory() .getFileStrict({ path: 'important-config.json' }); // Lock file for 10 minutes await file.lock({ timeoutMillis: 600000 }); console.log('๐Ÿ”’ File locked'); // Try to modify locked file (will throw error) try { await file.delete(); } catch (error) { console.log('โŒ Cannot delete locked file'); } // Unlock when done await file.unlock(); console.log('๐Ÿ”“ File unlocked'); ``` ### ๐Ÿท๏ธ Metadata Management Attach and manage metadata for your files: ```typescript const file = await bucket.getBaseDirectory() .getFileStrict({ path: 'document.pdf' }); // Get metadata handler const metadata = await file.getMetaData(); // Set custom metadata await metadata.setCustomMetaData({ key: 'author', value: 'John Doe' }); await metadata.setCustomMetaData({ key: 'department', value: 'Engineering' }); // Retrieve metadata const author = await metadata.getCustomMetaData({ key: 'author' }); console.log(`๐Ÿ“ Author: ${author}`); // Get all metadata const allMeta = await metadata.getAllCustomMetaData(); console.log('๐Ÿ“‹ All metadata:', allMeta); ``` ### ๐Ÿ—‘๏ธ Trash & Recovery SmartBucket includes an intelligent trash system for safe file deletion: ```typescript const file = await bucket.getBaseDirectory() .getFileStrict({ path: 'important-data.xlsx' }); // Move to trash instead of permanent deletion await file.delete({ mode: 'trash' }); console.log('๐Ÿ—‘๏ธ File moved to trash'); // Access trash const trash = await bucket.getTrash(); const trashDir = await trash.getTrashDir(); const trashedFiles = await trashDir.listFiles(); console.log(`๐Ÿ“ฆ ${trashedFiles.length} files in trash`); // Restore from trash const trashedFile = await bucket.getBaseDirectory() .getFileStrict({ path: 'important-data.xlsx', getFromTrash: true }); await trashedFile.restore({ useOriginalPath: true }); console.log('โ™ป๏ธ File restored successfully'); // Permanent deletion from trash await trash.emptyTrash(); console.log('๐Ÿงน Trash emptied'); ``` ### โšก Advanced Features #### File Statistics ```typescript // Get detailed file statistics const stats = await bucket.fastStat({ path: 'document.pdf' }); console.log(`๐Ÿ“Š Size: ${stats.size} bytes`); console.log(`๐Ÿ“… Last modified: ${stats.lastModified}`); console.log(`๐Ÿท๏ธ ETag: ${stats.etag}`); ``` #### Magic Bytes Detection ```typescript // Read first bytes for file type detection const magicBytes = await bucket.getMagicBytes({ path: 'mystery-file', length: 16 }); // Or from a File object const file = await bucket.getBaseDirectory() .getFileStrict({ path: 'image.jpg' }); const magic = await file.getMagicBytes({ length: 4 }); console.log(`๐Ÿ”ฎ Magic bytes: ${magic.toString('hex')}`); ``` #### JSON Data Operations ```typescript const file = await bucket.getBaseDirectory() .getFileStrict({ path: 'config.json' }); // Read JSON data const config = await file.getJsonData(); console.log('โš™๏ธ Config loaded:', config); // Update JSON data config.version = '2.0'; config.updated = new Date().toISOString(); await file.writeJsonData(config); console.log('๐Ÿ’พ Config updated'); ``` #### Directory & File Type Detection ```typescript // Check if path is a directory const isDir = await bucket.isDirectory({ path: 'uploads/' }); // Check if path is a file const isFile = await bucket.isFile({ path: 'uploads/document.pdf' }); console.log(`Is directory: ${isDir ? '๐Ÿ“' : 'โŒ'}`); console.log(`Is file: ${isFile ? '๐Ÿ“„' : 'โŒ'}`); ``` #### Clean Bucket Contents ```typescript // Remove all files and directories (use with caution!) await bucket.cleanAllContents(); console.log('๐Ÿงน Bucket cleaned'); ``` ### โ˜๏ธ Cloud Provider Support SmartBucket works seamlessly with: - โœ… **AWS S3** - Full compatibility with S3 API - โœ… **Google Cloud Storage** - Via S3-compatible API - โœ… **MinIO** - Self-hosted S3-compatible storage - โœ… **DigitalOcean Spaces** - S3-compatible object storage - โœ… **Backblaze B2** - Cost-effective cloud storage - โœ… **Wasabi** - High-performance S3-compatible storage - โœ… **Any S3-compatible provider** The library automatically handles provider quirks and optimizes operations for each platform while maintaining a consistent API. ### ๐Ÿ”ง Advanced Configuration ```typescript // Configure with custom options const smartBucket = new SmartBucket({ accessKey: process.env.S3_ACCESS_KEY, accessSecret: process.env.S3_SECRET_KEY, endpoint: process.env.S3_ENDPOINT, port: 443, useSsl: true, region: 'eu-central-1', // Additional S3 client options can be passed through }); // Environment-based configuration import { Qenv } from '@push.rocks/qenv'; const qenv = new Qenv('./', './.nogit/'); const smartBucket = new SmartBucket({ accessKey: await qenv.getEnvVarOnDemandStrict('S3_ACCESS_KEY'), accessSecret: await qenv.getEnvVarOnDemandStrict('S3_SECRET'), endpoint: await qenv.getEnvVarOnDemandStrict('S3_ENDPOINT'), }); ``` ### ๐Ÿงช Testing SmartBucket is thoroughly tested. Run tests with: ```bash pnpm test ``` ### ๐Ÿค Best Practices 1. **Always use strict mode** for critical operations to catch errors early 2. **Implement proper error handling** for network and permission issues 3. **Use streaming** for large files to optimize memory usage 4. **Leverage metadata** for organizing and searching files 5. **Enable trash mode** for important data to prevent accidental loss 6. **Lock files** during critical operations to prevent race conditions 7. **Clean up resources** properly when done ## License and Legal Information This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. ### Trademarks This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH. ### Company Information Task Venture Capital GmbH Registered at District court Bremen HRB 35230 HB, Germany For any legal inquiries or if you require further information, please contact us via email at hello@task.vc. By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.