Files

126 lines
3.4 KiB
Markdown
Raw Permalink Normal View History

# 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.*