This directory contains community-contributed VFS backends that are not officially supported as part of the core VFS library.
| Backend | Scheme | Description |
|---|---|---|
| Dropbox | dbx:// |
Dropbox cloud storage |
Community backends are not automatically registered. You must explicitly import them:
import (
"github.com/c2fo/vfs/v7/vfssimple"
_ "github.com/c2fo/vfs/contrib/backend/dropbox" // registers dbx:// scheme
)
func main() {
// Now dbx:// URIs work with vfssimple
file, err := vfssimple.NewFile("dbx:///path/to/file.txt")
// ...
}Want to contribute a backend? Follow these guidelines:
Create a new directory under contrib/backend/:
contrib/backend/yourbackend/
├── go.mod # Separate module (see versioning below)
├── go.sum
├── README.md # Documentation for your backend
├── doc.go # Package documentation
├── fileSystem.go # vfs.FileSystem implementation
├── fileSystem_test.go # Unit tests
├── location.go # vfs.Location implementation
├── location_test.go
├── file.go # vfs.File implementation
├── file_test.go
├── options.go # Configuration options
├── conformance_test.go # Integration tests (see Testing Requirements)
└── mocks/ # Generated mocks for testing
└── Client.go
Each contrib backend has its own go.mod for independent versioning:
module github.com/c2fo/vfs/contrib/backend/yourbackend
go 1.24
require (
github.com/c2fo/vfs/v7 v7.13.0 // Depend on core VFS
// ... your backend's dependencies
)This allows:
- Independent release cycles
- Isolated dependencies (your backend's deps don't affect core VFS)
- Clear compatibility requirements
Implement the core VFS interfaces:
vfs.FileSystem- Factory for locations and filesvfs.Location- Directory/path operationsvfs.File- File operations (implementsio.Reader,io.Writer,io.Seeker,io.Closer)
Register your backend in init():
func init() {
backend.Register(Scheme, NewFileSystem())
}- Use
testify.Suitewith mocked dependencies - Use Mockery for generating mocks: add entry to root
.mockery.yaml
The backend/testsuite package provides conformance tests that verify your backend correctly implements the VFS interfaces. This is critical for ensuring consistent behavior across all backends.
See the full documentation: docs/conformance_tests.md
What's tested:
RunConformanceTests— FileSystem, Location, and File interface complianceRunIOTests— 18 different Read/Write/Seek sequences
Example conformance test:
//go:build vfsintegration
package yourbackend
import (
"os"
"testing"
"github.com/c2fo/vfs/v7/backend/testsuite"
)
func TestConformance(t *testing.T) {
token := os.Getenv("YOUR_TOKEN")
if token == "" {
t.Skip("YOUR_TOKEN not set, skipping integration tests")
}
fs := NewFileSystem(WithAccessToken(token))
location, err := fs.NewLocation("", "/vfs-test/")
if err != nil {
t.Fatalf("failed to create location: %v", err)
}
// Configure options for backend-specific limitations
opts := testsuite.ConformanceOptions{
SkipTouchTimestampTest: true, // if backend has timestamp limitations
SkipFTPSpecificTests: false,
}
testsuite.RunConformanceTests(t, location, opts)
}
func TestIOConformance(t *testing.T) {
token := os.Getenv("YOUR_TOKEN")
if token == "" {
t.Skip("YOUR_TOKEN not set, skipping integration tests")
}
fs := NewFileSystem(WithAccessToken(token))
location, _ := fs.NewLocation("", "/vfs-test/")
testsuite.RunIOTests(t, location)
}Run with:
YOUR_TOKEN=xxx go test -v -tags=vfsintegration ./... -run TestConformanceConformanceOptions:
| Option | When to Use |
|---|---|
SkipTouchTimestampTest |
Backend doesn't update LastModified on identical content |
SkipFTPSpecificTests |
Backend has FTP-like IO limitations |
Your README should include:
- Installation instructions
- Authentication/configuration
- Usage examples
- API limitations and workarounds
- Performance considerations
Follow the existing patterns in core backends and other contrib packages:
- Functional options for configuration (
WithOptionName()) - Wrapped errors with context
- Comprehensive error handling
Community backends are maintained by the community and may not receive the same level of support as core backends. Issues and PRs are welcome, but response times may vary.
If a community backend gains significant adoption and a maintainer willing to provide ongoing support, it may be considered for promotion to a core backend.