{"_rev":"32-a6cc0320e71d5ef5cc664d5d73a7846b","time":{"created":"2026-02-12T01:21:18.588Z","modified":"2026-02-12T01:21:19.855Z","0.1.0":"2026-01-19T19:17:28.578Z","0.1.1":"2026-01-19T19:55:56.277Z","0.1.2":"2026-01-19T21:14:36.978Z","0.1.3":"2026-01-19T21:27:30.052Z","0.1.4":"2026-01-20T02:45:44.909Z","0.1.5":"2026-01-25T07:48:01.978Z","0.1.6":"2026-01-25T16:04:30.421Z","0.1.7":"2026-01-25T16:42:28.638Z","0.1.8":"2026-01-25T16:47:14.785Z","0.1.9":"2026-01-25T17:38:48.909Z","0.1.10":"2026-01-25T18:20:28.307Z","0.1.11":"2026-01-25T19:34:04.737Z","0.1.12":"2026-01-25T23:50:33.878Z","0.1.13":"2026-01-26T00:07:37.738Z","0.1.14":"2026-01-26T00:11:15.237Z","0.1.15":"2026-01-26T00:14:40.400Z","0.1.16":"2026-01-26T00:18:47.148Z","0.1.17":"2026-01-26T00:40:13.952Z","0.1.18":"2026-01-26T00:52:54.393Z","0.1.19":"2026-01-26T00:57:07.682Z","0.1.21":"2026-01-26T01:17:38.078Z","0.1.22":"2026-01-26T01:22:05.320Z","0.1.23":"2026-01-26T01:43:07.886Z","0.1.24":"2026-01-26T02:17:50.988Z","0.1.25":"2026-01-26T02:26:14.142Z","0.4.0":"2026-02-12T01:21:19.508Z"},"_id":"@teliagen/plugin-storage","name":"@teliagen/plugin-storage","dist-tags":{"latest":"0.4.0"},"versions":{"0.4.0":{"name":"@teliagen/plugin-storage","version":"0.4.0","private":false,"publishConfig":{"access":"restricted"},"description":"Unified storage plugin for Teliagen Framework","main":"dist/index.js","types":"dist/index.d.ts","type":"module","author":{"name":"Teliagen Team","email":"contact@teliagen.org"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/teliagen/teliagen-plugin.git","directory":"packages/plugin-storage"},"homepage":"https://docs.teliagen.org","bugs":{"url":"https://github.com/teliagen/teliagen-framework/issues"},"exports":{".":{"import":"./dist/index.js","require":"./dist/index.js","types":"./dist/index.d.ts"},"./common/drivers":{"import":"./dist/common/drivers/index.js","require":"./dist/common/drivers/index.js","types":"./dist/common/drivers/index.d.ts"},"./common/tokens":{"import":"./dist/common/tokens/index.js","require":"./dist/common/tokens/index.js","types":"./dist/common/tokens/index.d.ts"},"./common/types":{"import":"./dist/common/types/index.js","require":"./dist/common/types/index.js","types":"./dist/common/types/index.d.ts"},"./modules/storage/actions":{"import":"./dist/modules/storage/actions/index.js","require":"./dist/modules/storage/actions/index.js","types":"./dist/modules/storage/actions/index.d.ts"},"./modules/storage/entities":{"import":"./dist/modules/storage/entities/index.js","require":"./dist/modules/storage/entities/index.js","types":"./dist/modules/storage/entities/index.d.ts"},"./modules/storage/services":{"import":"./dist/modules/storage/services/index.js","require":"./dist/modules/storage/services/index.js","types":"./dist/modules/storage/services/index.d.ts"}},"dependencies":{"@teliagen/commons":"^0.4.0","@teliagen/logger":"^0.4.0","@teliagen/persistence":"^0.4.0","fs-extra":"^11.1.0","mime-types":"^2.1.35"},"devDependencies":{"@aws-sdk/client-s3":"^3.962.0","@aws-sdk/lib-storage":"^3.962.0","@aws-sdk/s3-request-presigner":"^3.962.0","@types/fs-extra":"^11.0.1","@types/mime-types":"^2.1.1","@types/node":"^20.0.0","cloudinary":"^2.8.0","typescript":"^5.0.0"},"peerDependencies":{"cloudinary":"^2.0.0","@aws-sdk/client-s3":"^3.0.0","@aws-sdk/lib-storage":"^3.0.0","@aws-sdk/s3-request-presigner":"^3.0.0"},"peerDependenciesMeta":{"cloudinary":{"optional":true},"@aws-sdk/client-s3":{"optional":true},"@aws-sdk/lib-storage":{"optional":true},"@aws-sdk/s3-request-presigner":{"optional":true}},"scripts":{"build":"tsc","dev":"tsc -w","test":"vitest"},"_id":"@teliagen/plugin-storage@0.4.0","_integrity":"sha512-jxLfXvj+0u0CGbTrZHtMxZBNSCp7NN/iBf+ZBTIezms9mvgsAteiWch+9CLYM8q22wBDQ5jL9Ex4vXNFPiyLqQ==","_resolved":"C:\\Users\\ABDOUL~1\\AppData\\Local\\Temp\\eb2e820eb1fe9564da1a19488856a998\\teliagen-plugin-storage-0.4.0.tgz","_from":"file:teliagen-plugin-storage-0.4.0.tgz","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-jxLfXvj+0u0CGbTrZHtMxZBNSCp7NN/iBf+ZBTIezms9mvgsAteiWch+9CLYM8q22wBDQ5jL9Ex4vXNFPiyLqQ==","shasum":"ddf3d91670d0f4b71e97d399c6a4b63bbf65d3f2","tarball":"https://registry.npmjs.org/@teliagen/plugin-storage/-/plugin-storage-0.4.0.tgz","fileCount":45,"unpackedSize":53797,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDPTuT2NAM7CkEW8KXuI7RqLssRnEte8XQvL4mclreWjAIhANrzKOV+sMaAZJZwzJu+skE4QMcMQVe8LG/A9eAOFI1G"}]},"_npmUser":{"name":"teliagen_off","email":"admin@teliagen.org"},"directories":{},"maintainers":[{"name":"teliagen_off","email":"admin@teliagen.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/plugin-storage_0.4.0_1770859279353_0.6726004251273463"},"_hasShrinkwrap":false}},"maintainers":[{"name":"teliagen_off","email":"admin@teliagen.org"}],"description":"Unified storage plugin for Teliagen Framework","homepage":"https://docs.teliagen.org","repository":{"type":"git","url":"git+https://github.com/teliagen/teliagen-plugin.git","directory":"packages/plugin-storage"},"author":{"name":"Teliagen Team","email":"contact@teliagen.org"},"bugs":{"url":"https://github.com/teliagen/teliagen-framework/issues"},"license":"MIT","readme":"# @teliagen/plugin-storage\r\n\r\n> File storage plugin for the Teliagen Framework.\r\n\r\n[![npm version](https://img.shields.io/npm/v/@teliagen/plugin-storage.svg)](https://www.npmjs.com/package/@teliagen/plugin-storage)\r\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\n## Overview\r\n\r\n`@teliagen/plugin-storage` provides unified file storage operations:\r\n\r\n- **Multiple Drivers** – Local filesystem, AWS S3, MinIO\r\n- **Disk Abstraction** – Configure multiple storage \"disks\"\r\n- **File Actions** – Upload, download, delete, list files\r\n- **Stream Support** – Efficient large file handling\r\n- **URL Generation** – Public and signed URLs\r\n- **MIME Type Detection** – Automatic content type handling\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @teliagen/plugin-storage\r\n# or\r\npnpm add @teliagen/plugin-storage\r\n```\r\n\r\nFor S3/MinIO:\r\n```bash\r\nnpm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner\r\n```\r\n\r\n## Quick Start\r\n\r\n```typescript\r\nimport { TeliagenApp } from '@teliagen/server';\r\nimport { StoragePlugin } from '@teliagen/plugin-storage';\r\n\r\nconst app = new TeliagenApp();\r\nawait app.initialize();\r\n\r\nconst storagePlugin = StoragePlugin({\r\n  name: 'storage',\r\n  default: 'local',\r\n  disks: {\r\n    local: {\r\n      driver: 'local',\r\n      root: './uploads',\r\n      publicPath: '/files'\r\n    }\r\n  }\r\n});\r\n\r\nawait app.registerPlugins([storagePlugin]);\r\nawait app.start();\r\n```\r\n\r\n## Configuration\r\n\r\n```typescript\r\ninterface StoragePluginOptions {\r\n  name: string;              // Plugin instance name\r\n  default: string;           // Default disk name\r\n  disks: Record<string, DiskConfig>;\r\n}\r\n\r\n// Local Disk\r\ninterface LocalDiskConfig {\r\n  driver: 'local';\r\n  root: string;              // Directory path\r\n  publicPath?: string;       // URL prefix for serving\r\n}\r\n\r\n// S3 Disk\r\ninterface S3DiskConfig {\r\n  driver: 's3';\r\n  bucket: string;\r\n  region: string;\r\n  accessKeyId: string;\r\n  secretAccessKey: string;\r\n  endpoint?: string;         // For S3-compatible (MinIO, DigitalOcean, etc.)\r\n  forcePathStyle?: boolean;  // Required for MinIO\r\n  publicUrl?: string;        // Base URL for public files\r\n}\r\n\r\n// MinIO Disk\r\ninterface MinioDiskConfig {\r\n  driver: 'minio';\r\n  bucket: string;\r\n  endpoint: string;          // e.g., 'http://localhost:9000'\r\n  accessKey: string;\r\n  secretKey: string;\r\n  useSSL?: boolean;\r\n  publicUrl?: string;\r\n}\r\n```\r\n\r\n## Complete Example\r\n\r\n```typescript\r\nconst storagePlugin = StoragePlugin({\r\n  name: 'storage',\r\n  default: 'local',\r\n  disks: {\r\n    // Local filesystem\r\n    local: {\r\n      driver: 'local',\r\n      root: './uploads',\r\n      publicPath: '/uploads'\r\n    },\r\n    \r\n    // AWS S3\r\n    s3: {\r\n      driver: 's3',\r\n      bucket: 'my-app-files',\r\n      region: 'us-east-1',\r\n      accessKeyId: process.env.AWS_ACCESS_KEY_ID!,\r\n      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!\r\n    },\r\n    \r\n    // DigitalOcean Spaces\r\n    spaces: {\r\n      driver: 's3',\r\n      bucket: 'my-space',\r\n      region: 'nyc3',\r\n      endpoint: 'https://nyc3.digitaloceanspaces.com',\r\n      accessKeyId: process.env.DO_ACCESS_KEY!,\r\n      secretAccessKey: process.env.DO_SECRET_KEY!,\r\n      publicUrl: 'https://my-space.nyc3.cdn.digitaloceanspaces.com'\r\n    },\r\n    \r\n    // MinIO (self-hosted)\r\n    minio: {\r\n      driver: 'minio',\r\n      bucket: 'uploads',\r\n      endpoint: 'http://minio:9000',\r\n      accessKey: process.env.MINIO_ACCESS_KEY!,\r\n      secretKey: process.env.MINIO_SECRET_KEY!,\r\n      useSSL: false\r\n    }\r\n  }\r\n});\r\n```\r\n\r\n## StorageService API\r\n\r\n```typescript\r\nconst storage = storagePlugin.Service;\r\n\r\n// Use default disk\r\nawait storage.put('avatars/user-123.jpg', buffer);\r\nawait storage.put('documents/report.pdf', stream);\r\n\r\n// Use specific disk\r\nawait storage.disk('s3').put('backups/data.zip', buffer);\r\n\r\n// Read file\r\nconst content = await storage.get('avatars/user-123.jpg');\r\nconst stream = await storage.getStream('videos/large.mp4');\r\n\r\n// Delete file\r\nawait storage.delete('temp/file.txt');\r\nawait storage.deleteMany(['temp/a.txt', 'temp/b.txt']);\r\n\r\n// Check existence\r\nconst exists = await storage.exists('avatars/user-123.jpg');\r\n\r\n// List files\r\nconst files = await storage.list('documents/');\r\nconst files = await storage.list('documents/', { recursive: true });\r\n\r\n// Get file info\r\nconst meta = await storage.metadata('file.pdf');\r\n// { size: 1024, mimeType: 'application/pdf', lastModified: Date }\r\n\r\n// URLs\r\nconst publicUrl = await storage.url('public/image.jpg');\r\nconst signedUrl = await storage.signedUrl('private/doc.pdf', { expiresIn: 3600 });\r\n\r\n// Copy/Move\r\nawait storage.copy('source.jpg', 'dest.jpg');\r\nawait storage.move('old-path.jpg', 'new-path.jpg');\r\n\r\n// Disk operations\r\nawait storage.disk('s3').put('file.txt', content);\r\nconst s3Files = await storage.disk('s3').list('/');\r\n```\r\n\r\n## Actions\r\n\r\nThe plugin registers the following actions:\r\n\r\n| Action | Description |\r\n|--------|-------------|\r\n| `uploadFile` | Upload a file (stream) |\r\n| `downloadFile` | Download a file |\r\n| `deleteFile` | Delete a file |\r\n| `listFiles` | List files in directory |\r\n| `getFileUrl` | Get public/signed URL |\r\n| `getFileMetadata` | Get file information |\r\n\r\n## Using in Actions\r\n\r\n```typescript\r\nimport { Action, ActionProvider, Stream, Input } from '@teliagen/commons';\r\nimport { Readable } from 'stream';\r\n\r\n@ActionProvider('files', 'FileActions')\r\nclass FileActions {\r\n  @Action('uploadAvatar', { transport: 'stream' })\r\n  async uploadAvatar(\r\n    @User() user: any,\r\n    @Stream() stream: Readable,\r\n    @Input() input: { filename: string }\r\n  ) {\r\n    const storage = storagePlugin.Service;\r\n    const path = `avatars/${user.id}/${input.filename}`;\r\n    \r\n    await storage.put(path, stream);\r\n    const url = await storage.url(path);\r\n    \r\n    return { path, url };\r\n  }\r\n\r\n  @Action('getDocument')\r\n  async getDocument(@Input() input: { path: string }) {\r\n    const storage = storagePlugin.Service;\r\n    \r\n    if (!await storage.exists(input.path)) {\r\n      throw new Error('File not found');\r\n    }\r\n    \r\n    const signedUrl = await storage.signedUrl(input.path, {\r\n      expiresIn: 3600  // 1 hour\r\n    });\r\n    \r\n    return { url: signedUrl };\r\n  }\r\n}\r\n```\r\n\r\n## File Upload Helpers\r\n\r\n```typescript\r\n// With multipart/form-data\r\n@Action('uploadFiles', { transport: 'form-data' })\r\nasync uploadFiles(@Input() input: { files: UploadedFile[] }) {\r\n  const storage = storagePlugin.Service;\r\n  const results = [];\r\n  \r\n  for (const file of input.files) {\r\n    const path = `uploads/${Date.now()}-${file.originalname}`;\r\n    await storage.put(path, file.buffer);\r\n    results.push({ path, size: file.size });\r\n  }\r\n  \r\n  return results;\r\n}\r\n```\r\n\r\n## Path Helpers\r\n\r\n```typescript\r\nimport { StoragePlugin } from '@teliagen/plugin-storage';\r\n\r\n// Generate unique paths\r\nconst path = storagePlugin.helpers.uniquePath('avatars', 'jpg');\r\n// avatars/550e8400-e29b-41d4-a716-446655440000.jpg\r\n\r\nconst path = storagePlugin.helpers.datePath('documents', 'pdf');\r\n// documents/2024/01/15/550e8400-e29b-41d4-a716-446655440000.pdf\r\n\r\n// Sanitize filenames\r\nconst safe = storagePlugin.helpers.sanitize('My File (1).pdf');\r\n// my-file-1.pdf\r\n```\r\n\r\n## Events\r\n\r\n```typescript\r\nimport { EventBus } from '@teliagen/commons';\r\n\r\nEventBus.on('storage:uploaded', async ({ disk, path, size }) => {\r\n  console.log(`File uploaded to ${disk}: ${path} (${size} bytes)`);\r\n});\r\n\r\nEventBus.on('storage:deleted', async ({ disk, path }) => {\r\n  console.log(`File deleted from ${disk}: ${path}`);\r\n});\r\n```\r\n\r\n## Requirements\r\n\r\n- **Node.js** >= 18.0.0\r\n- **@teliagen/server** >= 0.1.0\r\n\r\n## Related Packages\r\n\r\n- **[@teliagen/plugin-mail](../plugin-mail)** – Email sending\r\n\r\n## Documentation\r\n\r\nFor full documentation, visit [docs.teliagen.org](https://docs.teliagen.org).\r\n\r\n## License\r\n\r\nMIT © Teliagen Contributors\r\n\r\n---\r\n\r\n<p align=\"center\">\r\n  <strong>Part of the <a href=\"https://github.com/teliagen/teliagen-framework\">Teliagen Framework</a></strong>\r\n</p>\r\n","readmeFilename":"README.md"}