php-plug-storage/CLAUDE.md
Snider cbab99877d docs: add CLAUDE.md project instructions
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-13 13:38:02 +00:00

2.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

This is lthn/php-plug-storage, a Composer library providing storage provider integrations for the Plug framework. It depends on lthn/php (the core framework) and wraps Bunny CDN's storage API behind a driver-based abstraction.

Commands

composer install          # Install dependencies

There are no tests, linting, or build steps in this package.

Architecture

Namespace: Core\Plug\Storage\ (PSR-4 autoloaded from src/)

Contract Layer (src/Contract/)

Four interfaces define storage operations. All return Core\Plug\Response (from the core framework):

  • Uploadable — file and content uploads
  • Downloadable — content retrieval and file downloads
  • Deletable — single and bulk file deletion
  • Browseable — directory listing, existence checks, file size

Bunny Implementation (src/Bunny/)

Each contract has a corresponding Bunny CDN implementation (Upload, Download, Delete, Browse). They share a common pattern:

  • Constructor accepts optional credentials or reads from config (cdn.bunny.{zone}.api_key, cdn.bunny.{zone}.storage_zone, cdn.bunny.{zone}.region)
  • Lazy-initialized Bunny\Storage\Client
  • isConfigured() guard before operations
  • BuildsResponse trait for consistent ok()/error() responses
  • Static public()/private() factory methods for zone selection

VBucket (src/Bunny/VBucket.php) provides workspace-isolated storage. It hashes a domain via Core\Crypt\LthnHash::vBucketId() and prefixes all paths with the resulting ID. It combines upload, download, delete, list, and exists operations in one class rather than implementing the individual contracts.

StorageManager (src/StorageManager.php)

Factory that resolves operations by driver name. Configured via cdn.storage_driver config key (defaults to bunny). Supports zone switching and custom driver registration via extend().

Key Patterns

  • All storage operations return Core\Plug\Response, never throw — errors are wrapped via BuildsResponse::error().
  • Zone (public/private) is threaded through constructors, not set after instantiation.
  • Adding a new storage provider means: implement the four contracts, then register via StorageManager::extend().