import { createR2Storage } from '@mohamedhabibwork/storagekit/r2'
Cloudflare R2 implements the S3 API, so this driver uses the AWS SDK v3 packages:
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
Provide an R2 API token’s access key and secret. Pass accountId for the normal endpoint, or endpoint for a jurisdictional endpoint such as https://<account-id>.eu.r2.cloudflarestorage.com.
import { createR2Storage } from '@mohamedhabibwork/storagekit/r2';
const storage = await createR2Storage({
type: 'r2',
bucket: 'uploads',
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
},
prefix: 'production/',
});
The driver defaults region to 'auto', as required by R2, and uses virtual-hosted requests by default. Set forcePathStyle: true only when your endpoint requires it. publicUrlBase can point getUrl() at an R2 public-bucket URL or custom domain.
Uploads, downloads, lists, deletes, copies, multipart uploads, and presigned read/write/delete URLs use AWS SDK v3 S3 commands. The native option bag and native() client are therefore typed as their S3 equivalents.
await storage.upload('images/logo.png', bytes, {
contentType: 'image/png',
cacheControl: 'public, max-age=31536000, immutable',
});
const uploadUrl = await storage.getSignedUrl('incoming/avatar.png', {
action: 'write', expiresIn: 900, native: { ContentType: 'image/png' },
});
R2 does not provide S3 bucket versioning, so capabilities().versioning is false. R2’s S3 compatibility excludes several AWS-specific features such as ACLs, AWS KMS encryption, and object tagging; avoid those native options. See the Cloudflare R2 S3 compatibility matrix for current limits.