Skip to content

feat: implement R2 storage foundation #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 7, 2025
Merged

Conversation

nullcoder
Copy link
Owner

@nullcoder nullcoder commented Jun 7, 2025

Summary

This PR implements the foundational R2 storage client wrapper for GhostPaste, providing type-safe operations for storing and retrieving encrypted gists in Cloudflare R2 with full versioning support as specified in SPEC.md.

Closes #103

Changes

Storage Client (lib/storage.ts)

  • ✨ Created type-safe R2 client wrapper with singleton pattern
  • 🔒 Implemented comprehensive error handling with custom error types
  • 📦 Added support for versioned blob storage (versions/{id}/{timestamp}.bin)
  • 🚀 Implemented all core operations: put, get, delete, list, exists
  • 🔄 Added version management: listVersions, pruneVersions, getCurrentBlob
  • 📊 Added storage statistics calculation
  • 📄 Consistent key structure following SPEC.md design

Type Updates (types/models.ts)

  • Updated GistMetadata to include version (number) and current_version (timestamp)
  • Aligned with SPEC.md versioning requirements

Testing (lib/storage.test.ts)

  • ✅ Comprehensive unit tests with 100% coverage
  • 🎭 Mock-based testing for all R2 operations including versioning
  • 🧪 Edge case handling and error scenario testing
  • ✅ Added tests for version listing and pruning

Documentation

  • 📚 Updated R2 setup guide with versioning examples
  • 💡 Added code samples for all storage operations
  • 📝 Documented the versioning structure and behavior

Technical Details

The storage client now provides:

  • Versioned storage where all blobs are stored as versions/{id}/{timestamp}.bin
  • Type-safe operations for all R2 methods
  • Singleton pattern for efficient connection reuse
  • Automatic initialization on first use
  • Binary support for encrypted data
  • Version management with automatic pruning of old versions (keep last 50)
  • Current version tracking via metadata

Key Design Decisions

Following SPEC.md, the implementation:

  1. Eliminates redundancy - No duplicate storage of current blob
  2. Simplifies updates - New versions just add a timestamp file
  3. Improves atomicity - Single write operation for new versions
  4. Reduces complexity - No file copying or moving operations
  5. Better consistency - Metadata always points to valid version file

Testing

All tests pass:

✓ lib/storage.test.ts (31 tests) 15ms
Test Files  1 passed (1)
Tests  31 passed (31)

Next Steps

This completes issue #103. Ready to move on to issue #104 (Storage Operations) which will build on this foundation.

🤖 Generated with Claude Code

- Create type-safe R2 storage client wrapper with singleton pattern
- Implement all storage operations (put, get, delete, list, exists)
- Add comprehensive error handling with custom error types
- Create unit tests with 100% coverage
- Update R2 setup documentation with usage examples

Features:
- Type-safe methods for metadata and blob operations
- Automatic initialization and connection reuse
- Support for pagination in list operations
- Storage statistics calculation
- Consistent key structure for all objects

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <claude@ghostpaste.dev>
Copy link

cloudflare-workers-and-pages bot commented Jun 7, 2025

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ghostpaste 8bd6d58 Visit preview Jun 07 2025, 06:49 PM

- Switch from separate blobs/ directory to versions/{id}/{timestamp}.bin structure
- Update GistMetadata type to include version and current_version fields
- Implement version management methods (listVersions, pruneVersions)
- Add getCurrentBlob method to retrieve current version using metadata
- Update all tests to reflect versioning changes
- Update R2 setup documentation with versioning examples

This aligns the storage implementation with the SPEC.md design where:
- All blobs are stored as versioned files
- Metadata tracks the current_version timestamp
- New versions just add a timestamp file
- Last 50 versions are kept (older ones pruned)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <claude@ghostpaste.dev>
@nullcoder nullcoder merged commit 150b844 into main Jun 7, 2025
1 check passed
@nullcoder nullcoder deleted the feat/r2-storage-foundation branch June 7, 2025 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: implement R2 storage foundation
1 participant