Skip to content

Effects Composition

The StorageModule is an [EffectsModule(typeof(IFileStore))] that generates Eff<RT, T> effect methods for file storage operations.

Capability Interface

public interface IHasFileStore
{
    IFileStore FileStore { get; }
}

Effect Methods

public static partial class StorageModule
{
    public static partial class Storage
    {
        public static Eff<RT, FileMetadata> UploadAsync<RT>(
            string key, Stream content, string contentType)
            where RT : IHasFileStore => ...

        public static Eff<RT, Stream> DownloadAsync<RT>(string key)
            where RT : IHasFileStore => ...

        public static Eff<RT, Unit> DeleteAsync<RT>(string key)
            where RT : IHasFileStore => ...

        public static Eff<RT, bool> ExistsAsync<RT>(string key)
            where RT : IHasFileStore => ...

        public static Eff<RT, Option<FileMetadata>> GetMetadataAsync<RT>(string key)
            where RT : IHasFileStore => ...

        public static Eff<RT, string> GetPresignedUrlAsync<RT>(
            string key, TimeSpan expiry)
            where RT : IHasFileStore => ...
    }
}

Effect Pipeline Examples

Upload a file

var uploadAvatar =
    from metadata in StorageModule.Storage.UploadAsync<AppRuntime>(
        $"avatars/{userId}", fileStream, "image/png")
    from _ in AppStore.Users.Save<AppRuntime>(user with { AvatarUrl = metadata.Url })
    select metadata;

Generate a presigned download URL

var getDownloadLink =
    from exists in StorageModule.Storage.ExistsAsync<AppRuntime>(fileKey)
    from _ in Guard<AppRuntime>(exists, Error.New(404, "File not found"))
    from url in StorageModule.Storage.GetPresignedUrlAsync<AppRuntime>(
        fileKey, TimeSpan.FromMinutes(15))
    select url;

Delete with cleanup

var deleteAttachment =
    from _ in StorageModule.Storage.DeleteAsync<AppRuntime>(attachment.StorageKey)
    from __ in AppStore.Attachments.Delete<AppRuntime>(attachment.Id)
    select unit;