91 lines
2.2 KiB
Go
91 lines
2.2 KiB
Go
package artifact
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"errors"
|
|
"fmt"
|
|
"gitea.maximumdirect.net/eric/scriptorium/internal/domain"
|
|
"mime"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
var (
|
|
ErrUnsupportedRefType = errors.New("unsupported artifact reference type")
|
|
ErrMissingInlineBody = errors.New("missing body for inline artifact")
|
|
ErrMissingFilePath = errors.New("missing file path for file artifact")
|
|
)
|
|
|
|
// Reader resolves artifact references into actual artifacts.
|
|
type Reader interface {
|
|
Read(ctx context.Context, ref domain.ArtifactRef) (*domain.Artifact, error)
|
|
}
|
|
|
|
// CompositeReader routes artifact resolution based on the reference type.
|
|
type CompositeReader struct {
|
|
inlineReader *inlineReader
|
|
fileReader *fileReader
|
|
}
|
|
|
|
func NewCompositeReader() Reader {
|
|
return &CompositeReader{
|
|
inlineReader: &inlineReader{},
|
|
fileReader: &fileReader{},
|
|
}
|
|
}
|
|
|
|
func (c *CompositeReader) Read(ctx context.Context, ref domain.ArtifactRef) (*domain.Artifact, error) {
|
|
switch ref.Type {
|
|
case domain.ArtifactRefInline:
|
|
return c.inlineReader.Read(ctx, ref)
|
|
case domain.ArtifactRefFile:
|
|
return c.fileReader.Read(ctx, ref)
|
|
default:
|
|
return nil, fmt.Errorf("%w: %s", ErrUnsupportedRefType, ref.Type)
|
|
}
|
|
}
|
|
|
|
type inlineReader struct{}
|
|
|
|
func (r *inlineReader) Read(ctx context.Context, ref domain.ArtifactRef) (*domain.Artifact, error) {
|
|
if ref.Body == "" {
|
|
return nil, ErrMissingInlineBody
|
|
}
|
|
|
|
body := []byte(ref.Body)
|
|
return &domain.Artifact{
|
|
Body: body,
|
|
Size: int64(len(body)),
|
|
Hash: fmt.Sprintf("%x", sha256.Sum256(body)),
|
|
URI: ref.URI,
|
|
}, nil
|
|
}
|
|
|
|
type fileReader struct{}
|
|
|
|
func (r *fileReader) Read(ctx context.Context, ref domain.ArtifactRef) (*domain.Artifact, error) {
|
|
if ref.URI == "" {
|
|
return nil, ErrMissingFilePath
|
|
}
|
|
|
|
data, err := os.ReadFile(ref.URI)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read file %s: %w", ref.URI, err)
|
|
}
|
|
|
|
contentType := mime.TypeByExtension(filepath.Ext(ref.URI))
|
|
if contentType == "" {
|
|
contentType = "text/plain" // Default
|
|
}
|
|
|
|
return &domain.Artifact{
|
|
Name: filepath.Base(ref.URI),
|
|
ContentType: contentType,
|
|
Body: data,
|
|
URI: ref.URI,
|
|
Size: int64(len(data)),
|
|
Hash: fmt.Sprintf("%x", sha256.Sum256(data)),
|
|
}, nil
|
|
}
|