Releases: maximseshuk/payload-storage-bunny
Release list
v3.0.0
A full rewrite of the plugin: per-collection zones and libraries, browser-direct uploads, S3-compatible storage, IP-locked signed URLs, a setup wizard, and a new documentation site.
Requires Payload CMS 3.83+ and Node.js 22+.
Important
Read this before upgrading. Four things change behavior — one of them touches your data, one of them sends a request from your server.
- Stream metadata moved into a stored
bunnyDatafield, replacingbunnyVideoId/bunnyVideoMeta. Existing projects must run the data migration: on Postgres and SQLite the legacy columns are dropped the moment the v3 schema is pushed, so migrate before that. Skipping it means broken thumbnails, missing resolutions, andvideoIdqueries returning nothing. - Config keys were renamed or removed. Most of them throw at boot with a targeted message, so a v2 config fails fast instead of behaving oddly:
apiKey→accountApiKey,stream.tus.uploadTimeout→stream.tus.expiresIn,stream.tus.mimeTypes→stream.mimeTypes,purge.apiKeyandadminThumbnailremoved,experimentaldropped. Full table. - Anonymous telemetry is on by default. It reports boolean feature flags, plugin and runtime versions, and a salted one-way project hash — no names, paths, URLs, or keys, and the server never reads your IP. Turn it off with
telemetry: false,DO_NOT_TRACK=1, Payload's own opt-out, or by running in CI. Exactly what is sent. - The in-plugin media preview UI is gone. Video preview now lives in the separate media-preview plugin; this package ships only a thin adapter on the
./media-previewsubpath.
Step-by-step: Upgrade guide · Reference: Docs
⚠️ Breaking Changes
- Stream metadata stored in
bunnyData, with a migration helper on the./migrationssubpath (e21e81a, 4574b6a, b59bd73, f214e81) - Config renames and removals, each with a boot-time error pointing at the new key (649006e, b8fc2c7, 8583a25, dd644e6, 9f88174)
- Opt-out anonymous telemetry, disclosed on first run (dc4a5ad)
- In-plugin media preview UI removed in favor of an external plugin plus an adapter (a754038, d59cee7)
🚀 Features
- Per-collection zones and libraries — a collection can point at its own storage zone or stream library, every setting is overridable per collection, and storage or stream can be switched off for one collection (2b9752e, df67c58, 30e42b3, eff125f)
- Client-direct uploads — the browser sends files straight to Bunny, bypassing your server. The transport is chosen automatically: presigned S3 when the zone has
storage.s3, otherwise a deployed Edge Script (9af1403, 4b98063) - S3-compatible storage backend — SigV4 upload and delete through a tiny dependency instead of the AWS SDK (28986f4)
- Signed URLs with per-client IP locking and absolute expiry — a link can be bound to one IPv4 address and to a fixed moment, not just a sliding window (ce6bc52)
- CLI —
initprovisions Bunny resources and prints your plugin config plus.envlines;bunny:deploy-edge-scriptdeploys the upload Edge Script with per-zone secrets (8fe56c8) - Smaller additions — dynamic per-document prefix, animated WebP thumbnails for Stream,
stream.refererfor referrer-blocked libraries, and OpenAPI metadata consumed by payload-plugin-openapi (7c3e570, 6b52335, 1a0fa1d)
🐛 Bug Fixes
- Signed URLs — the client IP is appended last in the token hash, matching Bunny's own order; IP-locked links were rejected before (4e9e5d4)
- Upload responses —
urlandthumbnailURLsurvivehandleUpload, and emptybunnyDatacollapses tonullinstead of leaking an empty group (e6e7662, b259dcc) - Validation — webhook signatures are checked for version and algorithm, per-collection
signedUrlsandpurgefail at boot when their key is missing, and the SQL migration survives a missing legacy column (a4a3dd7, edeeed6, 032867c) - Overrides and TUS — per-collection config inherits the global one correctly, and the TUS cleanup task no longer leaves stale sessions behind (6bc48af, 823610b)
🛠 Internals
src/is grouped by runtime and dependency direction —shared → server → payload, one module owning the Bunny HTTP API, one ky client for every outbound request. The boundaries are enforced by lint rules rather than convention (dc4a5ad, 8a0fecd, 59ea19b)- Toolchain moved to oxlint, oxfmt, tsdown and tsx; tests split into unit, integration, and live end-to-end runs against real Bunny resources (28127d5, 25cdb35, ae95fc8)
📚 Documentation
The docs were rewritten from scratch and now live at payload-storage-bunny.seshuk.im — configuration reference, guides, an API reference, and a step-by-step upgrade guide (cc5d237, 3c7210c).
Thanks to Mintlify for their open-source program and for the access that made this documentation site possible.
This release took a while to put together. If the plugin saves you time, a star or a coffee is always appreciated — and issues and pull requests are just as welcome.
Full Changelog: v2.2.0...v3.0.0
v2.2.0
This is the final v2.x release before v3.0.0.
🚀 New Features
- TUS
checkAccessBody: The TUScheckAccesscallback now receives the parsed auth request body as a second argument (collection,filename,filetype,filesize), so you can gate uploads before the video is created (#17 - Thanks to @madaxen86) - Dynamic Upload Prefix: The storage prefix can now be set per-document via
data.prefixfrom a collection hook (for example, per-tenant folders); uploads without it are unchanged (#18 - Thanks to @mengidd)
🐛 Bug Fixes
- URL Transform: Fixed
applyUrlTransformthrowing on relative (access-controlled) URLs, and existing query parameters are now preserved - Storage Query Parameters: Request query parameters are now preserved when proxying storage files through Payload (for example, Bunny Image Optimizer parameters with access control enabled)
- TUS Save Detection: Fixed post-upload "saved" detection that compared the document update event by object identity instead of its
updatedAt - Non-Upload Collections: The plugin now fails fast with a clear error when a configured collection has no
uploadconfig
🛠️ Development
- CI:
test-buildnow runs on push and pull requests; workflow actions updated to their latest versions, pnpm is resolved from thepackageManagerfield, and npm provenance is enabled for publishing
Full Changelog: v2.1.1...v2.2.0
v2.1.1
🐛 Bug Fixes
- Collection Hooks: Fixed issue where user's collection hooks (beforeChange, afterRead,
afterDelete, etc.) were being lost when the plugin initialized - Thumbnail Config: Fixed bug where setting
thumbnail: falseat the collection level wasn't
working properly
🌍 Translations
- Tamil: Added Tamil (ta) language support
🛠️ Development
- Dependencies Update: Updated development dependencies to Payload 3.57
Full Changelog: v2.1.0...v2.1.1
v2.1.0
Users upgrading from v2.0.x should follow the Migration Guide to update their configuration.
🚀 New Features
- Stream-Only Support: Plugin now supports using only Bunny Stream without Bunny Storage configuration
- Thumbnail Config Rename:
adminThumbnailconfiguration renamed tothumbnailfor better clarity and consistency
🐛 Bug Fixes
- Thumbnail Time Validation: Fixed issue where
thumbnailTime: 0was incorrectly treated as invalid value (#12 - Thanks to @christophemenager for reporting)
🛠️ Improvements
- Backward Compatibility: Old
adminThumbnailconfig still supported with deprecation warning (will be removed in v2.2.0)
📝 Documentation
- GitHub Callouts: Enhanced documentation with proper GitHub callouts
- Stream-Only Examples: Added configuration examples for stream-only setups
Full Changelog: v2.0.2...v2.1.0
v2.0.2
🛠️ Improvements
- Build Configuration: Improved build configuration with
resolveFully: trueoption for better module resolution
📝 Documentation
- Added Bunny.net referral banner and partnership disclosure to README
Full Changelog: v2.0.1...v2.0.2
v2.0.1
🚀 New Features
- Admin Thumbnail Size Selection: Enhanced admin thumbnail handler with
sizeNameparameter support for using specific upload sizes - Multi-Language Support: Complete internationalization with translations for all 43 PayloadCMS supported languages
🐛 Bug Fixes
- Signed URL Generation: Fixed URL decoding in signed URL generation for proper path handling
📝 Documentation
- Improved consistency across documentation and better onboarding experience
Full Changelog: v2.0.0...v2.0.1
v2.0.0
⚠️ Breaking Changes
This is a major version upgrade with breaking changes:
- Payload CMS Version: Requires Payload CMS 3.53.0 or higher
- Configuration Structure:
- Removed
optionswrapper - move all configs to top level stream.libraryIdnow requires number instead of stringstream.mp4Fallbackis now boolean instead of{ enabled: boolean }purge.enabledremoved - purging enabled by presence ofapiKey
- Removed
- Removed Features:
experimental.replaceSaveButtonComponentno longer needed or supported
Users upgrading from v1.x must follow the Migration Guide to update their configuration.
🚀 New Features
- TUS Resumable Uploads: Support for resumable uploads using TUS protocol
- Signed URLs: Secure file access with geo-restrictions and expiration
- Advanced URL Transform: Customize file URLs with query parameters or custom functions
- Stream Cleanup: Automatic cleanup of failed upload sessions
See README.md for detailed configuration examples and usage.
🛠️ Improvements
- Simplified Configuration: Flattened configuration structure for better developer experience
- Code Reorganization: Split handlers into separate modules for better maintenance and performance
Full Changelog: v1.2.2...v2.0.0
v1.2.2
✨ New Features
-
Experimental Features: Added experimental options to address Payload CMS issues. Introduced
experimental.replaceSaveButtonComponentoption as a temporary workaround for Payload CMS issue #13182 that causes unnecessary file re-downloads during field updates.
🛠️ Development
- Development Environment: Added Payload CMS development playground
Full Changelog: v1.2.1...v1.2.2
v1.2.1
🐛 Bug Fixes
-
Fixed Upload Hanging Issue: Resolved issue where image uploads would get stuck in loading state with submitting indicator (#6 - Thanks to @alexisoney and @jsc604 for reporting and providing detailed investigation)
- Pinned
kydependency to version 1.7.5 to avoid hanging bug in 1.8.1 on Node versions below 22 - Ensures compatibility with Node versions below 22
- Pinned
-
Fixed Main Filename Assignment: Resolved issue where main filename was randomly being set to one of the 'sizes' filenames instead of the original filename (#7 - Thanks to @DavidOliver and @alexisoney for reporting and providing solution)
- Removed filename mutation in upload handler following S3 adapter pattern
- Fixed filename handling logic to ensure main image retains correct filename
- Improved filename consistency across different image sizes
🛠️ Improvements
- Code Quality: Minor code formatting improvements and refactoring for better maintainability
- Updated Prettier configuration and ignore rules
- Improved code consistency across the codebase
Full Changelog: v1.2.0...v1.2.1
v1.2.0
🚀 New Features
- Automatic CDN Cache Purging for Storage Files
- Automatically purge CDN cache after file uploads and deletions
- Configurable with options for async operation
- Ensures visitors always see the most up-to-date content
🛠️ Improvements
- Admin Thumbnail Configuration: Enhanced documentation for using existing
appendTimestampoption with Bunny CDN's Vary Cache settings
🐛 Bug Fixes
- Error with cropping or replacing images (#3 - Thanks to @PP-Tom for reporting)
- Can't update metadata on an existing image (#4 - Thanks to @wongdigital for reporting)
📝 Documentation
- Added new "CDN Cache Management" section explaining both purging and how to properly configure Bunny CDN's Vary Cache to work with timestamp parameters
- Updated examples with cache purging configuration
- Clearer instructions for obtaining and using the Bunny API key
Full Changelog: v1.1.0...v1.2.0