@venturekit/storage
Installation
Section titled “Installation”npm install @venturekit/storageWhat It Provides
Section titled “What It Provides”S3 Configuration
Section titled “S3 Configuration”import { createS3Config, DEFAULT_S3_CONFIG, buildS3Config } from '@venturekit/storage';
const config = createS3Config({ bucketName: 'my-uploads', versioned: true, cdn: true });Storage Client
Section titled “Storage Client”import { createStorageClientFromEnv, sanitizeFilename } from '@venturekit/storage';
const storage = createStorageClientFromEnv(); // bucket + endpoint from the storage intent's env varsconst key = `uploads/${ctx.tenant!.id}/${sanitizeFilename(file.name)}`;
await storage.put(key, buffer, { contentType: file.type });const url = await storage.getSignedUrl(key, { expiresIn: 900 });Size-Capped Browser Uploads
Section titled “Size-Capped Browser Uploads”A presigned PUT URL cannot limit how many bytes the client sends; a presigned POST form signs a policy that S3 enforces itself, content-length-range included:
const { url, fields } = await storage.presignUploadPost(key, { contentType: 'image/jpeg', maxSize: 5 * 1024 * 1024, // S3 rejects anything larger — not the client's word expiresIn: 600,});// browser: FormData with `fields` in order, then the file, POSTed to `url` → 204The policy also pins the key and content type, so a leaked form cannot be repurposed. Passing maxSize to getSignedUploadUrl now throws instead of being ignored — see the API reference.
Image Optimisation
Section titled “Image Optimisation”putImage() shrinks a picture once, on the way in — never upscaled, same format in and out, format sniffed from the bytes rather than trusted from the filename — and stores the original when re-encoding would not make it smaller:
const result = await storage.putImage(`avatars/${userId}`, bytes, { maxDimension: 512, jpegQuality: 82 });// result.outcome: 'reduced' | 'kept' | 'passthrough', result.contentType, result.bytes vs result.originalBytesoptimizeImage() and sniffImageFormat() are exported for use outside the client. Re-encoding needs the optional sharp peer; projects that never store images carry no native binary.
- Storage bucket, lifecycle, CDN, and CORS configuration types
StorageClient,PutOptions,PutImageOptions,PutImageResult,OptimizeImageOptions,OptimizedImage,ImageFormat— client typesSignedUploadPostOptions,PresignedPostUpload,PresignedUrl,BuildPresignedPostInput,PresignedPostForm— presigned upload typesS3Outputs,S3InfraConfig— infrastructure types
Storage Purposes
Section titled “Storage Purposes”| Purpose | Description |
|---|---|
uploads | User-uploaded files |
assets | Static assets with CDN |
backups | Database and app backups |
logs | Application logs |
Dependencies
Section titled “Dependencies”@venturekit/core— required@aws-sdk/client-s3/@aws-sdk/s3-request-presigner— storage clientsharp— optional peer (image re-encoding)
Related
Section titled “Related”- Storage Guide — setup walkthrough
@venturekit/data/files— upload metadata (owner, purpose, checksum, retention) alongside the bytes- Infrastructure Intents — declaring storage
- API Reference — full type documentation