tx-agent-kit
Packages

Storage

Cloudflare R2 object storage with S3-compatible presigned URL generation and Effect service layer.

Storage (packages/infra/storage)

The storage package provides an Effect service layer over Cloudflare R2 using the AWS S3 SDK. It handles presigned URL generation, object deletion, listing, and metadata retrieval.

Usage

import { Storage, StorageLive } from '@tx-agent-kit/storage'
import { Effect } from 'effect'

const program = Effect.gen(function* () {
  const storage = yield* Storage

  const uploadUrl = yield* storage.generateUploadUrl('org/file.png', 'image/png')
  const downloadUrl = yield* storage.generateDownloadUrl('org/file.png')
  const keys = yield* storage.listObjects('org/')
  const metadata = yield* storage.getObjectMetadata('org/file.png')
  yield* storage.deleteObject('org/old-file.png')

  return { uploadUrl, downloadUrl, keys, metadata }
})

// Provide the live layer
Effect.runPromise(program.pipe(Effect.provide(StorageLive)))

Service interface

MethodParametersReturnsDescription
generateUploadUrlkey, contentType, expiresIn?stringPresigned PUT URL
generateDownloadUrlkey, expiresIn?stringPresigned GET URL
deleteObjectkeyvoidDelete a stored object
listObjectsprefix?readonly string[]List object keys
getObjectMetadatakeyObjectMetadataContent type, size, etag, last modified

All methods return Effect.Effect<T, StorageError>.

Effect integration

The package exports a Storage Context.Tag and a StorageLive Layer:

// In server-lib.ts or activity code
import { StorageLive } from '@tx-agent-kit/storage'

// Add to port dependencies
const PortDependenciesLive = Layer.mergeAll(
  // ... other ports
  StorageLive
)

StorageLive uses Layer.effect for lazy initialization. The S3 client is created on first use, not at import time. This allows test files to import the package without needing R2 credentials.

Environment configuration

VariableRequiredDefaultDescription
R2_ACCESS_KEY_IDYesnoneS3-compatible access key
R2_SECRET_ACCESS_KEYYesnoneS3-compatible secret key
R2_BUCKET_NAMENooctospark-devTarget bucket
R2_ENDPOINTNoR2 S3 API URLS3 endpoint
R2_ACCOUNT_IDNoAccount IDCloudflare account

Testing

Unit tests mock the S3 client. Integration tests run against the real R2 dev bucket:

# Unit tests (no credentials needed)
pnpm --filter @tx-agent-kit/storage test

# Integration tests (requires R2 credentials)
op run --env-file=.env.dev -- pnpm --filter @tx-agent-kit/storage test:integration
PageDescription
Storage OverviewArchitecture and upload flow
Storage ConfigurationEnvironment variables and 1Password
Storage API EndpointsHTTP routes

On this page