{"id":31946384,"url":"https://github.com/profullstack/storage-service","last_synced_at":"2026-03-04T06:03:27.667Z","repository":{"id":292679977,"uuid":"981598099","full_name":"profullstack/storage-service","owner":"profullstack","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-15T09:02:28.000Z","size":118,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-23T11:53:40.003Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/profullstack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-11T13:26:16.000Z","updated_at":"2025-05-15T09:02:31.000Z","dependencies_parsed_at":"2025-05-11T15:19:29.211Z","dependency_job_id":"9869738c-d49c-4351-96f1-c79a9f620410","html_url":"https://github.com/profullstack/storage-service","commit_stats":null,"previous_names":["profullstack/storage-service"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/profullstack/storage-service","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profullstack%2Fstorage-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profullstack%2Fstorage-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profullstack%2Fstorage-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profullstack%2Fstorage-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/profullstack","download_url":"https://codeload.github.com/profullstack/storage-service/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/profullstack%2Fstorage-service/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30073697,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T05:31:57.858Z","status":"ssl_error","status_checked_at":"2026-03-04T05:31:38.462Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-14T11:15:46.260Z","updated_at":"2026-03-04T06:03:27.635Z","avatar_url":"https://github.com/profullstack.png","language":"JavaScript","readme":"# @profullstack/storage-service\n\nA flexible storage service abstraction for file storage, retrieval, and metadata management.\n\n## Features\n\n- **Multiple Adapters**: Support for memory, filesystem, S3, and Supabase storage\n- **Bucket Management**: Create, list, and delete storage buckets\n- **File Operations**: Upload, download, copy, move, and delete files\n- **Metadata Management**: Store and retrieve custom metadata with files\n- **Content Type Detection**: Automatic content type detection from file data\n- **URL Generation**: Generate public and signed URLs for file access\n- **Search Capabilities**: Search files by path prefix and metadata\n- **Customizable**: Configurable filename generation, content types, and more\n\n## Installation\n\n```bash\nnpm install @profullstack/storage-service\n```\n\n## Basic Usage\n\n```javascript\nimport { createStorageService, MemoryAdapter } from '@profullstack/storage-service';\n\n// Create a storage service with in-memory adapter\nconst storage = createStorageService({\n  adapter: new MemoryAdapter(),\n  defaultBucket: 'documents'\n});\n\n// Create a bucket\nawait storage.createBucket('documents', {\n  public: false,\n  fileSizeLimit: 10 * 1024 * 1024, // 10MB\n  allowedMimeTypes: ['application/pdf', 'text/plain']\n});\n\n// Upload a file\nconst uploadResult = await storage.uploadFile({\n  bucketName: 'documents',\n  path: 'hello.txt',\n  data: Buffer.from('Hello, world!'),\n  contentType: 'text/plain',\n  metadata: {\n    description: 'A simple text file',\n    author: 'ProFullStack'\n  }\n});\n\nconsole.log(`File uploaded: ${uploadResult.path}`);\n\n// Download a file\nconst downloadResult = await storage.downloadFile({\n  bucketName: 'documents',\n  path: 'hello.txt',\n  responseType: 'text'\n});\n\nconsole.log(`File content: ${downloadResult.data}`);\n```\n\n## API Reference\n\n### Creating a Storage Service\n\n```javascript\nimport { createStorageService, MemoryAdapter } from '@profullstack/storage-service';\n\nconst storage = createStorageService({\n  // Storage adapter (required)\n  adapter: new MemoryAdapter(),\n  \n  // Default bucket name (default: 'default')\n  defaultBucket: 'documents',\n  \n  // Bucket configuration (optional)\n  bucketConfig: {\n    documents: {\n      public: false,\n      fileSizeLimit: 10 * 1024 * 1024, // 10MB\n      allowedMimeTypes: ['application/pdf', 'text/plain']\n    }\n  },\n  \n  // Metadata options (optional)\n  metadataOptions: {\n    reservedKeys: ['contentType', 'size', 'createdAt', 'updatedAt'],\n    defaultMetadata: {\n      application: 'my-app'\n    }\n  },\n  \n  // Whether to generate unique filenames (default: true)\n  generateUniqueFilenames: true,\n  \n  // Custom filename generator (optional)\n  filenameGenerator: (originalPath) =\u003e {\n    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n    return `${originalPath}_${timestamp}`;\n  }\n});\n```\n\n### Bucket Management\n\n#### Creating a Bucket\n\n```javascript\nawait storage.createBucket('images', {\n  public: true,\n  fileSizeLimit: 5 * 1024 * 1024, // 5MB\n  allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif']\n});\n```\n\n#### Listing Buckets\n\n```javascript\nconst buckets = await storage.listBuckets();\nconsole.log('Buckets:', buckets.map(bucket =\u003e bucket.name));\n```\n\n#### Deleting a Bucket\n\n```javascript\n// Delete a bucket (must be empty)\nawait storage.deleteBucket('temp');\n\n// Force delete a bucket (even if not empty)\nawait storage.deleteBucket('temp', { force: true });\n```\n\n### File Operations\n\n#### Uploading a File\n\n```javascript\n// Upload a text file\nconst textUploadResult = await storage.uploadFile({\n  bucketName: 'documents',\n  path: 'notes/hello.txt',\n  data: Buffer.from('Hello, world!'),\n  contentType: 'text/plain',\n  metadata: {\n    description: 'A simple text file',\n    author: 'ProFullStack',\n    tags: ['example', 'text']\n  },\n  upsert: false, // Don't overwrite if exists (default)\n  public: false // Not publicly accessible (default)\n});\n\n// Upload a JSON file\nconst jsonUploadResult = await storage.uploadFile({\n  bucketName: 'documents',\n  path: 'config.json',\n  data: Buffer.from(JSON.stringify({ key: 'value' })),\n  contentType: 'application/json'\n});\n\n// Upload an image file\nconst imageData = await fs.readFile('image.jpg');\nconst imageUploadResult = await storage.uploadFile({\n  bucketName: 'images',\n  path: 'profile.jpg',\n  data: imageData,\n  contentType: 'image/jpeg',\n  metadata: {\n    width: 800,\n    height: 600\n  },\n  public: true // Make publicly accessible\n});\n```\n\n#### Downloading a File\n\n```javascript\n// Download as buffer (default)\nconst bufferResult = await storage.downloadFile({\n  bucketName: 'documents',\n  path: 'hello.txt'\n});\n\n// Download as text\nconst textResult = await storage.downloadFile({\n  bucketName: 'documents',\n  path: 'hello.txt',\n  responseType: 'text'\n});\n\n// Download as JSON\nconst jsonResult = await storage.downloadFile({\n  bucketName: 'documents',\n  path: 'config.json',\n  responseType: 'json'\n});\n\n// Download as stream\nconst streamResult = await storage.downloadFile({\n  bucketName: 'documents',\n  path: 'large-file.pdf',\n  responseType: 'stream'\n});\n```\n\n#### Getting File Information\n\n```javascript\nconst fileInfo = await storage.getFileInfo({\n  bucketName: 'documents',\n  path: 'hello.txt'\n});\n\nconsole.log(`File: ${fileInfo.path}`);\nconsole.log(`Size: ${fileInfo.size} bytes`);\nconsole.log(`Content Type: ${fileInfo.contentType}`);\nconsole.log(`Created At: ${fileInfo.createdAt}`);\nconsole.log(`Metadata: ${JSON.stringify(fileInfo.metadata)}`);\n```\n\n#### Listing Files\n\n```javascript\n// List all files in a bucket\nconst allFiles = await storage.listFiles({\n  bucketName: 'documents',\n  limit: 100\n});\n\n// List files with a prefix\nconst noteFiles = await storage.listFiles({\n  bucketName: 'documents',\n  prefix: 'notes/',\n  limit: 100\n});\n\n// List files with pagination\nconst firstPage = await storage.listFiles({\n  bucketName: 'documents',\n  limit: 10\n});\n\nconst secondPage = await storage.listFiles({\n  bucketName: 'documents',\n  limit: 10,\n  cursor: firstPage.cursor\n});\n```\n\n#### Copying Files\n\n```javascript\nconst copyResult = await storage.copyFile({\n  sourceBucket: 'documents',\n  sourcePath: 'hello.txt',\n  destinationBucket: 'backup',\n  destinationPath: 'hello-backup.txt',\n  overwrite: false // Don't overwrite if exists (default)\n});\n```\n\n#### Moving Files\n\n```javascript\nconst moveResult = await storage.moveFile({\n  sourceBucket: 'documents',\n  sourcePath: 'draft.txt',\n  destinationBucket: 'documents',\n  destinationPath: 'published/final.txt',\n  overwrite: true // Overwrite if exists\n});\n```\n\n#### Deleting Files\n\n```javascript\nconst deleted = await storage.deleteFile({\n  bucketName: 'documents',\n  path: 'temp.txt'\n});\n```\n\n### Metadata Management\n\n#### Updating Metadata\n\n```javascript\nconst updatedMetadata = await storage.updateMetadata({\n  bucketName: 'documents',\n  path: 'hello.txt',\n  metadata: {\n    description: 'Updated description',\n    version: '1.1.0',\n    tags: ['updated', 'example']\n  },\n  merge: true // Merge with existing metadata (default)\n});\n```\n\n### URL Generation\n\n#### Getting a Public URL\n\n```javascript\n// Only works for files in public buckets or with public=true\nconst publicUrl = await storage.getFileUrl({\n  bucketName: 'images',\n  path: 'profile.jpg'\n});\n```\n\n#### Getting a Signed URL\n\n```javascript\n// Get a signed URL for reading a file\nconst readUrl = await storage.getSignedUrl({\n  bucketName: 'documents',\n  path: 'private.pdf',\n  expiresIn: 3600, // 1 hour\n  action: 'read'\n});\n\n// Get a signed URL for writing a file\nconst writeUrl = await storage.getSignedUrl({\n  bucketName: 'documents',\n  path: 'uploads/new-file.txt',\n  expiresIn: 3600, // 1 hour\n  action: 'write'\n});\n```\n\n### Searching Files\n\n```javascript\n// Search by prefix\nconst prefixResults = await storage.searchFiles({\n  bucketName: 'documents',\n  prefix: 'notes/',\n  limit: 100\n});\n\n// Search by metadata\nconst metadataResults = await storage.searchFiles({\n  bucketName: 'documents',\n  metadata: {\n    author: 'ProFullStack',\n    tags: ['example']\n  },\n  limit: 100\n});\n\n// Combined search\nconst combinedResults = await storage.searchFiles({\n  bucketName: 'documents',\n  prefix: 'notes/',\n  metadata: {\n    author: 'ProFullStack'\n  },\n  limit: 100\n});\n```\n\n## Storage Adapters\n\n### Memory Adapter\n\nStores files in memory. Suitable for development or testing.\n\n```javascript\nimport { createStorageService, MemoryAdapter } from '@profullstack/storage-service';\n\nconst storage = createStorageService({\n  adapter: new MemoryAdapter()\n});\n```\n\n### Filesystem Adapter\n\nStores files on the local filesystem. Suitable for server-side applications.\n\n```javascript\nimport { createStorageService, FilesystemAdapter } from '@profullstack/storage-service';\n\nconst storage = createStorageService({\n  adapter: new FilesystemAdapter({\n    rootDir: '/path/to/storage'\n  })\n});\n```\n\n### S3 Adapter\n\nStores files in Amazon S3 or compatible services. Suitable for production use.\n\n```javascript\nimport { createStorageService, S3Adapter } from '@profullstack/storage-service';\n\nconst storage = createStorageService({\n  adapter: new S3Adapter({\n    region: 'us-west-2',\n    credentials: {\n      accessKeyId: 'YOUR_ACCESS_KEY',\n      secretAccessKey: 'YOUR_SECRET_KEY'\n    },\n    endpoint: 'https://s3.amazonaws.com' // Optional for non-AWS S3-compatible services\n  })\n});\n```\n\n### Supabase Adapter\n\nStores files in Supabase Storage. Suitable for applications using Supabase.\n\n```javascript\nimport { createStorageService, SupabaseAdapter } from '@profullstack/storage-service';\nimport { createClient } from '@supabase/supabase-js';\n\nconst supabaseClient = createClient(\n  'https://your-project.supabase.co',\n  'your-supabase-key'\n);\n\nconst storage = createStorageService({\n  adapter: new SupabaseAdapter({\n    client: supabaseClient\n  })\n});\n```\n\n## Creating Custom Adapters\n\nYou can create custom adapters by implementing the adapter interface:\n\n```javascript\nclass CustomAdapter {\n  async createBucket(bucketName, options) { /* ... */ }\n  async listBuckets() { /* ... */ }\n  async deleteBucket(bucketName, options) { /* ... */ }\n  async uploadFile(options) { /* ... */ }\n  async downloadFile(options) { /* ... */ }\n  async getFileInfo(options) { /* ... */ }\n  async listFiles(options) { /* ... */ }\n  async deleteFile(options) { /* ... */ }\n  async copyFile(options) { /* ... */ }\n  async moveFile(options) { /* ... */ }\n  async getFileUrl(options) { /* ... */ }\n  async getSignedUrl(options) { /* ... */ }\n  async updateMetadata(options) { /* ... */ }\n  async searchFiles(options) { /* ... */ }\n}\n```\n\n## Examples\n\nSee the [examples](./examples) directory for complete usage examples.\n\n## License\n\nMIT","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprofullstack%2Fstorage-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprofullstack%2Fstorage-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprofullstack%2Fstorage-service/lists"}