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 }