# einherjar/storage-minio [![version](https://img.shields.io/badge/version-v1.0.0-5C4EE5?style=flat-square)](https://code.nochebuena.dev/einherjar/storage-minio) [![license](https://img.shields.io/badge/license-AGPL--3.0-22863A?style=flat-square)](LICENSE) [![go](https://img.shields.io/badge/Go-1.26+-00ADD8?style=flat-square&logo=go&logoColor=white)](https://go.dev) [![health](https://img.shields.io/badge/health-critical-D73A49?style=flat-square)]() > The shield does not care who forged it. It holds what it is given and gives it back unchanged. `code.nochebuena.dev/einherjar/storage-minio` is the MinIO/S3 object storage component of the Einherjar framework. It wraps `minio-go/v7` behind a lifecycle-aware `Component` with four common operations — upload, download, delete, and presigned URLs. For anything beyond that scope, `Native()` returns the raw `*miniogo.Client`. --- ## Usage ### Setup ```go import storageminio "code.nochebuena.dev/einherjar/storage-minio" s := storageminio.New(logger, storageminio.DefaultConfig()) launcher.Append(s) // OnInit connects; OnStop is a no-op (stateless client) health.Register(s) // BucketExists check; LevelCritical ``` ### Uploading ```go import miniogo "github.com/minio/minio-go/v7" info, err := s.PutObject(ctx, "my-bucket", "uploads/photo.jpg", reader, size, miniogo.PutObjectOptions{ ContentType: "image/jpeg", }) ``` ### Downloading ```go obj, err := s.GetObject(ctx, "my-bucket", "uploads/photo.jpg", miniogo.GetObjectOptions{}) if err != nil { return s.HandleError(err) } defer obj.Close() ``` ### Presigned URL (time-limited public access) ```go url, err := s.PresignedGetObject(ctx, "my-bucket", "uploads/photo.jpg", 15*time.Minute, nil) // url is a *url.URL — call url.String() to get the string form ``` ### Deleting ```go err := s.RemoveObject(ctx, "my-bucket", "uploads/photo.jpg", miniogo.RemoveObjectOptions{}) ``` ### Native escape hatch For multipart uploads, bucket management, or any operation not in `Provider`, use the raw client: ```go native := s.Native() // *miniogo.Client ``` Callers that use `Native()` must import `github.com/minio/minio-go/v7` directly. ### Error handling ```go if err := s.HandleError(someErr); err != nil { // minio-go error responses mapped to xerrors: // NoSuchKey / NoSuchBucket → ErrNotFound // AccessDenied → ErrPermissionDenied // context.Canceled → ErrCancelled // context.DeadlineExceeded → ErrDeadlineExceeded } ``` `HandleError` is also available as a package-level function: `storageminio.HandleError(err)`. --- ## Environment variables | Variable | Required | Default | Description | |---|---|---|---| | `EINHERJAR_MINIO_ENDPOINT` | Yes | — | MinIO/S3 endpoint (host:port or domain) | | `EINHERJAR_MINIO_ACCESS_KEY` | Yes | — | Access key ID | | `EINHERJAR_MINIO_SECRET_KEY` | Yes | — | Secret access key | | `EINHERJAR_MINIO_BUCKET` | Yes | — | Default bucket for health check | | `EINHERJAR_MINIO_USE_SSL` | No | `false` | Use TLS | | `EINHERJAR_MINIO_REGION` | No | `us-east-1` | Bucket region | --- ## Dependency graph ``` contracts (zero dependencies) ↑ core ↑ storage-minio (contracts, core, minio-go/v7) ↑ your app ``` --- ## Verification ```bash cd storage-minio/ go build ./... go vet ./... go test ./... gofmt -l . ``` --- > *The artifact survives the battle that created it.* > *Store it well. Someone will need it after you are gone.*