Object Storage (@wrelik/storage)
Relevant source files
The following files were used as context for generating this wiki page:
The @wrelik/storage package provides a vendor-agnostic adapter for S3-compatible object storage, specifically optimized for Cloudflare R2. It serves as a centralized interface for handling file uploads, downloads, signed URLs, and file validation across the Wrelik ecosystem.
As part of the core infrastructure, this package enforces an "adapter-first" architecture. By wrapping the underlying AWS SDK, it ensures that application-level code does not interact directly with vendor-specific SDKs, thereby reducing vendor lock-in and simplifying future migrations.
Sources: README.md:14-18, README.md:31-33, DECISIONS.md:14-17
Architecture and Design
The storage module is built on top of the AWS SDK for S3, utilizing it to communicate with Cloudflare R2 via an S3-compatible API. The package maintains a singleton S3 client that must be initialized before use.
Connection Workflow
The initialization process constructs a Cloudflare R2 endpoint using the provided account ID and configures the S3Client with the necessary credentials and region.
The diagram shows the sequence of steps taken during the initialization of the storage provider.
Sources: packages/storage/src/index.ts:16-30
Vendor Abstraction
To maintain strict architectural boundaries, the project enforces a linting rule that prevents applications from importing @aws-sdk/* directly, mandating the use of @wrelik/storage instead.
Sources: packages/eslint-config/index.js:34-37
Configuration
The module requires a specific configuration object to interface with the storage provider.
| Property | Type | Description |
|---|---|---|
accountId | string | Cloudflare Account ID used to construct the R2 endpoint. |
accessKeyId | string | S3-compatible Access Key ID. |
secretAccessKey | string | S3-compatible Secret Access Key. |
bucketName | string | The target bucket for object operations. |
region | string | Optional. Defaults to 'auto' for R2 compatibility. |
Sources: packages/storage/src/index.ts:5-11, packages/storage/src/index.ts:18-29
Core Functionality
Object Operations
The package provides wrappers for standard S3 operations, abstracting the command-based architecture of the AWS SDK into direct async functions.
- putObject: Directly uploads data (Buffer, Blob, or string) to a specific key with metadata.
- getSignedUploadUrl: Generates a presigned URL allowing clients to perform PUT requests directly to the storage.
- getSignedDownloadUrl: Generates a presigned URL for secure, time-limited access to private objects.
The sequence diagram illustrates the flow for obtaining a presigned upload URL.
Sources: packages/storage/src/index.ts:41-75
Validation Logic
The validateUpload function provides a mechanism to enforce file policies before attempting an upload. It utilizes a custom ValidationError from the @wrelik/errors package.
// Example validation usage derived from src/index.ts:77-88
export function validateUpload(
file: { contentType: string; sizeBytes: number },
policy: { maxSizeBytes: number; allowedTypes: string[] },
) {
if (file.sizeBytes > policy.maxSizeBytes) {
throw new ValidationError(`File too large. Max ${policy.maxSizeBytes} bytes.`);
}
if (!policy.allowedTypes.includes(file.contentType)) {
throw new ValidationError(`Invalid file type ${file.contentType}`);
}
return true;
}
Sources: packages/storage/src/index.ts:77-88, packages/storage/package.json:16
Implementation Details
The package is compiled using tsup into both CJS and ESM formats, ensuring compatibility with various Node.js and Next.js environments.
Dependencies
| Dependency | Purpose |
|---|---|
@aws-sdk/client-s3 | Core S3 communication. |
@aws-sdk/s3-request-presigner | Utility for generating signed URLs. |
@wrelik/errors | Provides standard ValidationError for storage failures. |
Sources: packages/storage/package.json:14-17
Summary
@wrelik/storage serves as the standard integration layer for object storage within the Wrelik ecosystem. By centralizing the logic for Cloudflare R2 integration and S3-compatible operations, it ensures consistent behavior, simplified configuration, and a reduced API surface area for application developers.