{"_id":"@allegria/aws-file-manager","_rev":"4-cb2c92049b6cec5db2158ed9a887bcc2","name":"@allegria/aws-file-manager","dist-tags":{"latest":"1.0.3"},"versions":{"0.0.1":{"name":"@allegria/aws-file-manager","version":"0.0.1","keywords":["aws","s3","file-upload","file-manager","typescript"],"author":"","license":"MIT","_id":"@allegria/aws-file-manager@0.0.1","maintainers":[{"name":"ryansukale","email":"ryansukale@gmail.com"}],"dist":{"shasum":"0b98e768214646c6b098190e0533a5751432691d","tarball":"https://registry.npmjs.org/@allegria/aws-file-manager/-/aws-file-manager-0.0.1.tgz","fileCount":6,"integrity":"sha512-lADYJf5Mui4ZvGRO8Y50Daub+3H0+O0kthKQEDeYQJqlxeH7EZXgQWiPTZneMLRzp1ROnw/5Bra+cTSy0OWD7g==","signatures":[{"sig":"MEQCIHsws0FHGmLEV4cdilEerCAiPt7DsbUfQSn2jZK1icvoAiBRBWCCdlpfWccWq1itZ9NOXJaiEXKwF/MYo0mYMGfX7w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":18986},"main":"dist/lib/aws-file-manager.js","type":"module","types":"dist/lib/aws-file-manager.d.ts","gitHead":"460de442a7110ea0c45abc2b597c86b772bc0846","scripts":{"build":"tsc","start":"pnpm run build","prepare":"pnpm run build","preinstall":"npx only-allow pnpm","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"ryansukale","email":"ryansukale@gmail.com"},"_npmVersion":"9.6.7","description":"TypeScript library for managing files in AWS S3","directories":{},"_nodeVersion":"18.17.0","dependencies":{"jszip":"^3.10.1","dotenv":"^16.3.1","multer":"^1.4.5-lts.1","express":"^4.18.2","@aws-sdk/client-s3":"^3.445.0","@aws-sdk/s3-request-presigner":"^3.445.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ts-node":"^10.9.1","typescript":"^5.2.2","@types/node":"^20.9.0","@types/multer":"^1.4.10","@types/express":"^4.17.21"},"_npmOperationalInternal":{"tmp":"tmp/aws-file-manager_0.0.1_1744589711294_0.061745186317312184","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@allegria/aws-file-manager","version":"1.0.1","keywords":["aws","s3","file-upload","file-manager"],"author":{"name":"Ryan Sukale","email":"ryansukale@gmail.com"},"license":"MIT","_id":"@allegria/aws-file-manager@1.0.1","maintainers":[{"name":"ryansukale","email":"ryansukale@gmail.com"}],"homepage":"https://github.com/ryansukale/aws-file-manager#readme","bugs":{"url":"https://github.com/ryansukale/aws-file-manager/issues"},"dist":{"shasum":"ed612d99a0b620613074475234256c687f284a93","tarball":"https://registry.npmjs.org/@allegria/aws-file-manager/-/aws-file-manager-1.0.1.tgz","fileCount":45,"integrity":"sha512-B5vadXEcugVjzbr+3LgLtXlPQSyngcxn5NFDgNAnLCqsgmtRFUDmwfYTuvyZ0oPcEhuwDWkzvKcKpJzB41rAag==","signatures":[{"sig":"MEUCIGM8SbAn6eBcCpSW15+izrRtaR2FzEfv9mkj0EkXPurzAiEAsi92Rcr0PPGTQCqax3u0kbTAszE3rfwOYN99ZbNauXA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":129841},"main":"dist/lib/aws-file-manager.js","type":"module","_from":"file:allegria-aws-file-manager-1.0.1.tgz","types":"dist/lib/aws-file-manager.d.ts","scripts":{"test":"vitest run","build":"tsc","start":"pnpm run build","preinstall":"npx only-allow pnpm","test:watch":"vitest"},"_npmUser":{"name":"ryansukale","email":"ryansukale@gmail.com"},"_resolved":"/tmp/5950e35303621aaeb3ba817a419a254d/allegria-aws-file-manager-1.0.1.tgz","_integrity":"sha512-B5vadXEcugVjzbr+3LgLtXlPQSyngcxn5NFDgNAnLCqsgmtRFUDmwfYTuvyZ0oPcEhuwDWkzvKcKpJzB41rAag==","repository":{"url":"git+https://github.com/ryansukale/aws-file-manager.git","type":"git"},"_npmVersion":"11.6.2","description":"TypeScript library for managing files in AWS S3","directories":{},"_nodeVersion":"25.2.0","dependencies":{"jszip":"^3.10.1","dotenv":"^16.3.1","multer":"^1.4.5-lts.1","express":"^4.18.2","@aws-sdk/client-s3":"^3.445.0","@aws-sdk/s3-request-presigner":"^3.445.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.18","ts-node":"^10.9.1","typescript":"^5.2.2","@types/node":"^20.9.0","@types/multer":"^1.4.10","@types/express":"^4.17.21"},"_npmOperationalInternal":{"tmp":"tmp/aws-file-manager_1.0.1_1771788960979_0.4544148717018268","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@allegria/aws-file-manager","version":"1.0.2","keywords":["aws","s3","file-upload","file-manager"],"author":{"name":"Ryan Sukale","email":"ryansukale@gmail.com"},"license":"MIT","_id":"@allegria/aws-file-manager@1.0.2","maintainers":[{"name":"ryansukale","email":"ryansukale@gmail.com"}],"homepage":"https://github.com/ryansukale/aws-file-manager#readme","bugs":{"url":"https://github.com/ryansukale/aws-file-manager/issues"},"dist":{"shasum":"fc3521393906aa8fd1ab6c5677631b7603cdffb6","tarball":"https://registry.npmjs.org/@allegria/aws-file-manager/-/aws-file-manager-1.0.2.tgz","fileCount":49,"integrity":"sha512-v2pqBV6Zy924NQIiHxDN4SWrqbcoAE88fezaRYEl99yn6KN4NtvjK4tXla1C3o1h6owsRZvgSl0wpFqoPCqPBQ==","signatures":[{"sig":"MEQCIBR85PgYNYphlVPBcReOPNx9pmnGfkEkVvD1r2gqWkWAAiBZnT+11fSvkkcU5/Arm5BRgewJfFr6XrNN5qCAjHVTGg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":167006},"main":"dist/cjs/aws-file-manager.js","type":"module","types":"dist/lib/aws-file-manager.d.ts","module":"dist/lib/aws-file-manager.js","exports":{".":{"import":{"types":"./dist/lib/aws-file-manager.d.ts","default":"./dist/lib/aws-file-manager.js"},"require":{"types":"./dist/cjs/aws-file-manager.d.ts","default":"./dist/cjs/aws-file-manager.js"}}},"gitHead":"a70676d0c5835d94d85cad532426fa4e365987b1","scripts":{"test":"vitest run","build":"tsc && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}, null, 2))\"","start":"pnpm run build","prepare":"pnpm run build","preinstall":"npx only-allow pnpm","test:watch":"vitest","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"ryansukale","email":"ryansukale@gmail.com"},"repository":{"url":"git+https://github.com/ryansukale/aws-file-manager.git","type":"git"},"_npmVersion":"11.6.2","description":"TypeScript library for managing files in AWS S3","directories":{},"_nodeVersion":"25.2.0","dependencies":{"jszip":"^3.10.1","dotenv":"^16.3.1","multer":"^1.4.5-lts.1","express":"^4.18.2","@aws-sdk/client-s3":"^3.445.0","@aws-sdk/s3-request-presigner":"^3.445.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.18","ts-node":"^10.9.1","typescript":"^5.2.2","@types/node":"^20.9.0","@types/multer":"^1.4.10","@types/express":"^4.17.21"},"_npmOperationalInternal":{"tmp":"tmp/aws-file-manager_1.0.2_1771985499874_0.6444689016401863","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@allegria/aws-file-manager","version":"1.0.3","description":"TypeScript library for managing files in AWS S3","main":"dist/cjs/aws-file-manager.js","module":"dist/lib/aws-file-manager.js","types":"dist/lib/aws-file-manager.d.ts","exports":{".":{"import":{"types":"./dist/lib/aws-file-manager.d.ts","default":"./dist/lib/aws-file-manager.js"},"require":{"types":"./dist/cjs/aws-file-manager.d.ts","default":"./dist/cjs/aws-file-manager.js"}}},"type":"module","scripts":{"build":"tsc && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}, null, 2))\"","start":"pnpm run build","prepare":"pnpm run build","prepublishOnly":"pnpm run build","test":"vitest run","test:watch":"vitest"},"keywords":["aws","s3","file-upload","file-manager"],"author":{"name":"Ryan Sukale","email":"ryansukale@gmail.com"},"repository":{"type":"git","url":"git+https://github.com/ryansukale/aws-file-manager.git"},"license":"MIT","publishConfig":{"access":"public"},"dependencies":{"@aws-sdk/client-s3":"^3.445.0","@aws-sdk/s3-request-presigner":"^3.445.0","dotenv":"^16.3.1","express":"^4.18.2","jszip":"^3.10.1","multer":"^1.4.5-lts.1"},"devDependencies":{"@types/express":"^4.17.21","@types/multer":"^1.4.10","@types/node":"^20.9.0","ts-node":"^10.9.1","typescript":"^5.2.2","vitest":"^4.0.18"},"volta":{"node":"20.20.0","pnpm":"9.1.0"},"_id":"@allegria/aws-file-manager@1.0.3","gitHead":"6b191f7b4ef58487062e54bbb85bcfa125d0003c","bugs":{"url":"https://github.com/ryansukale/aws-file-manager/issues"},"homepage":"https://github.com/ryansukale/aws-file-manager#readme","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-vWQimEjnAW9I8eK3E8FKWKVnbRnkCom1lghCFMLbBCuml7/YQM9Tt1/X3k9XsWdnXnc+3OxyBhVBhpl/bIphaQ==","shasum":"338a4c22593bef7507ff0a7fd600033a703e757b","tarball":"https://registry.npmjs.org/@allegria/aws-file-manager/-/aws-file-manager-1.0.3.tgz","fileCount":19,"unpackedSize":102432,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDOMj88ja64zaULRVkW0MtBj4PehLDsd+D+gyvWLWJG0QIhANOKEfcw4l351Qf3jaK1w1xehI39N5Shf68U7COzcPbH"}]},"_npmUser":{"name":"ryansukale","email":"ryansukale@gmail.com"},"directories":{},"maintainers":[{"name":"ryansukale","email":"ryansukale@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aws-file-manager_1.0.3_1772598088429_0.9290524967316303"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-14T00:15:11.229Z","modified":"2026-03-04T04:21:28.712Z","0.0.1":"2025-04-14T00:15:11.494Z","1.0.1":"2026-02-22T19:36:01.122Z","1.0.2":"2026-02-25T02:11:40.032Z","1.0.3":"2026-03-04T04:21:28.578Z"},"bugs":{"url":"https://github.com/ryansukale/aws-file-manager/issues"},"author":{"name":"Ryan Sukale","email":"ryansukale@gmail.com"},"license":"MIT","homepage":"https://github.com/ryansukale/aws-file-manager#readme","keywords":["aws","s3","file-upload","file-manager"],"repository":{"type":"git","url":"git+https://github.com/ryansukale/aws-file-manager.git"},"description":"TypeScript library for managing files in AWS S3","maintainers":[{"name":"ryansukale","email":"ryansukale@gmail.com"}],"readme":"# AWS File Manager\n\nA TypeScript library for managing files in AWS S3. Handles uploads, signed URL generation, downloads, deletes, copies, and bucket listing — with full TypeScript types and a clean API designed for server-side Node.js applications.\n\n## Installation\n\n```bash\nnpm install @allegria/aws-file-manager\n```\n\n## Why this library\n\n- **No ACL footgun.** ACL headers are omitted by default, which is correct for all buckets created after April 2023 (BucketOwnerEnforced). Passing an ACL to such a bucket throws a hard AWS error.\n- **UUID filenames.** `generateUniqueFileName: true` replaces the original filename with a UUID while preserving the extension. Timestamps collide under concurrent uploads; UUIDs don't.\n- **Keys and signed URLs are separate.** `upload()` returns only the S3 key (persist this to your database). `getSignedUrl()` is a separate call you make at request time — signed URLs expire and must never be stored.\n\n## Quick start\n\n```ts\nimport { AwsFileManager, fromMulterFile } from \"@allegria/aws-file-manager\";\n\nconst fileManager = new AwsFileManager({\n  region: \"us-east-1\",\n  bucketName: \"my-app-uploads\",\n  basePath: \"uploads\",          // optional: namespaces all keys under this prefix\n});\n\n// In an Express/multer route:\nconst fileInput = fromMulterFile(req.file);\n\nconst result = await fileManager.upload(fileInput, {\n  folder: \"avatars\",\n  generateUniqueFileName: true,\n});\n\n// Persist result.key to your database — not the URL\n// await db.files.create({ s3Key: result.key });\n\n// Generate a signed URL on demand (e.g. when serving the file to a client)\nconst url = await fileManager.getSignedUrl(result.key, {\n  disposition: \"inline\",\n});\n```\n\n## Core concepts\n\n### FileInput and adapters\n\n`upload()` takes a `FileInput` — a normalised object with `buffer`, `originalName`, `mimeType`, and `size`. Use the provided adapters to construct one:\n\n```ts\n// Express + multer (server-side)\nimport { fromMulterFile } from \"@allegria/aws-file-manager\";\nconst fileInput = fromMulterFile(req.file);\n\n// Next.js App Router / Web API File (browser or edge)\nimport { fromWebFile } from \"@allegria/aws-file-manager\";\nconst fileInput = await fromWebFile(formData.get(\"file\") as File);\n\n// Or build it directly\nconst fileInput: FileInput = {\n  buffer: myBuffer,\n  originalName: \"photo.jpg\",\n  mimeType: \"image/jpeg\",\n  size: myBuffer.length,\n};\n```\n\n### Keys vs signed URLs\n\n| What | Where to store | Lifetime |\n|---|---|---|\n| S3 key (`result.key`) | Your database | Permanent |\n| Signed URL | Never store | Minutes to hours |\n\nThe S3 key is the stable identifier for a file. Generate a signed URL at request time when you need to give a client access to a private file.\n\n### basePath namespacing\n\nSet `basePath` in the constructor to prefix every key with a sub-folder:\n\n```ts\nconst fm = new AwsFileManager({ ..., basePath: \"uploads\" });\n// upload to folder 'avatars' → key: 'uploads/avatars/<filename>'\n```\n\n## API reference\n\n### Constructor\n\n```ts\nnew AwsFileManager(config: AwsFileManagerConfig)\n```\n\nSee [Configuration reference](#configuration-reference) below.\n\n### Methods\n\n| Method | Signature | Returns | Notes |\n|---|---|---|---|\n| `upload` | `(file: FileInput, options?: UploadOptions)` | `Promise<UploadResult>` | Stores the file; returns key + metadata |\n| `getSignedUrl` | `(key: string, options?: SignedUrlOptions)` | `Promise<string>` | Short-lived presigned URL for private objects |\n| `download` | `(key: string, mode?: 'buffer' \\| 'stream')` | `Promise<DownloadResult \\| null>` | Returns `null` when key not found |\n| `delete` | `(key: string)` | `Promise<void>` | Idempotent — missing key does not throw |\n| `deleteMany` | `(keys: string[])` | `Promise<void>` | Chunks at 1 000 keys per S3 request |\n| `copy` | `(sourceKey, destKey, options?)` | `Promise<void>` | Server-side copy within the bucket |\n| `list` | `(options?: ListOptions)` | `Promise<ListResult>` | Paginated via `continuationToken` |\n| `exists` | `(key: string)` | `Promise<boolean>` | Lightweight key existence check |\n| `getS3Client` | `()` | `S3Client` | Access the underlying client for advanced use |\n\n### Adapter functions\n\n| Function | Signature | Notes |\n|---|---|---|\n| `fromMulterFile` | `(multerFile) => FileInput` | Sync — for Express + multer |\n| `fromWebFile` | `(webFile: File) => Promise<FileInput>` | Async — for Web API File / Next.js App Router |\n\n## Examples\n\nThe `examples/` directory contains runnable TypeScript snippets for every method:\n\n| File | Description |\n|---|---|\n| [01-setup.ts](examples/01-setup.ts) | Instantiation: explicit credentials, env vars, IAM role |\n| [02-upload-multer.ts](examples/02-upload-multer.ts) | Upload from Express + multer |\n| [03-upload-web.ts](examples/03-upload-web.ts) | Upload from Next.js App Router (Web API File) |\n| [04-signed-urls.ts](examples/04-signed-urls.ts) | Inline, attachment, and custom-TTL signed URLs |\n| [05-download.ts](examples/05-download.ts) | Download as Buffer or stream; pipe to HTTP response |\n| [06-delete.ts](examples/06-delete.ts) | Delete single file or all variants at once |\n| [07-copy.ts](examples/07-copy.ts) | Copy / move objects (server-side, no re-upload) |\n| [08-list-paginated.ts](examples/08-list-paginated.ts) | Paginated listing for reconciliation jobs |\n| [09-exists.ts](examples/09-exists.ts) | Key existence check for integrity validation |\n\n## Configuration reference\n\n```ts\ninterface AwsFileManagerConfig {\n  region: string;                // AWS region, e.g. 'us-east-1'\n  bucketName: string;            // S3 bucket name\n  accessKeyId?: string;          // Omit to use environment/IAM resolution\n  secretAccessKey?: string;      // Omit to use environment/IAM resolution\n  basePath?: string;             // Prefix for all keys, e.g. 'uploads'\n  urlExpirationSeconds?: number; // Signed URL TTL (default: 3600)\n  storageClass?: StorageClass;   // Default storage class (default: INTELLIGENT_TIERING)\n}\n```\n\n**Credential resolution order** (when `accessKeyId`/`secretAccessKey` are omitted):\n\n1. `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables\n2. `~/.aws/credentials` file\n3. EC2/ECS/Lambda instance metadata (IAM role) — recommended for production\n\n## Notes\n\n**ACL behaviour.** No ACL is sent with `PutObjectCommand`. This is correct for all S3 buckets created after April 2023, which use `BucketOwnerEnforced` by default. If your bucket predates that change and requires legacy ACLs, call `getS3Client()` and issue the command directly.\n\n**Storage class.** The default storage class is `INTELLIGENT_TIERING`, which automatically moves objects between access tiers based on usage patterns. Override per-upload via `UploadOptions.storageClass`, or change the instance default via `AwsFileManagerConfig.storageClass`.\n\n**`deleteMany` chunking.** The S3 batch delete API accepts at most 1 000 keys per request. `deleteMany` splits larger arrays into 1 000-key chunks and sends them in parallel automatically.\n\n## Development\n\n```bash\npnpm test          # run tests once\npnpm test:watch    # run tests in watch mode\npnpm build         # compile TypeScript\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}