Swiftpack.co -  BinaryBirds/liquid-kit as Swift Package
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
An abstract FileStorage solution, based on the SwiftNIO framework.
.package(url: "https://github.com/BinaryBirds/liquid-kit.git", from: "1.2.0")


An abstract FileStorage solution, based on the SwiftNIO framework.

Key-based file storage

  • The main concept of LiquidKit is somewhat similar how AWS S3 buckets work.
  • You can use keys (relative path components) to store files using various drivers.
  • Keys should be designed to work with all the supported drivers.
  • Drivers should provide a resolution mechanism to return the absolute URL for a given key.


the key "test.txt" could be resolved to "http://localhost:8080/assets/test.txt" when using the local fs driver.

Drivers and Vapor 4 support

Currently available drivers:

LiquidKit is also compatible with Vapor 4 through the Liquid repository, that contains Vapor specific extensions.

Usage with SwiftNIO

You can use the Liquid FileStorage driver directly with SwiftNIO, here's a possible usage example:

/// setup thread pool
let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let pool = NIOThreadPool(numberOfThreads: 1)

/// create fs  
let fileio = NonBlockingFileIO(threadPool: pool)
let storages = FileStorages(fileio: fileio)
storages.use(.custom(exampleConfigVariable: "assets"), as: .custom)
let fs = storages.fileStorage(.custom, logger: .init(label: "[test-logger]"), on: elg.next())!

/// test file upload
let key = "test.txt"
let data = Data("file storage test".utf8)
let res = try fs.upload(key: key, data: data).wait()

How to implement a custom driver?

Drivers should implement the following protocols:


Used to uniquely identify the file storage driver.

public extension FileStorageID {
    static var customDriver: FileStorageID { .init(string: "custom-driver-identifier") }


A custom set of configuration variables required to initialize or setup the driver.

struct LiquidCustomStorageConfiguration: FileStorageConfiguration {
    let exampleConfigVariable: String

    func makeDriver(for storages: FileStorages) -> FileStorageDriver {
        return LiquidCustomStorageDriver(fileio: storages.fileio, configuration: self)


The file storage driver used to create the underlying storage object (that implements the API methods) using the configuration and context.

struct LiquidCustomStorageDriver: FileStorageDriver {

    let fileio: NonBlockingFileIO
    let configuration: LiquidCustomStorageConfiguration

    func makeStorage(with context: FileStorageContext) -> FileStorage {
        LiquidCustomStorage(fileio: fileio, configuration: configuration, context: context)
    func shutdown() {



Actual storage implementation that handles the necessary API methods.

struct LiquidCustomStorage: FileStorage {

    let fileio: NonBlockingFileIO
    let configuration: LiquidCustomStorageConfiguration
    let context: FileStorageContext
    init(fileio: NonBlockingFileIO, configuration: LiquidCustomStorageConfiguration, context: FileStorageContext) {
        self.fileio = fileio
        self.configuration = configuration
        self.context = context

    // MARK: - api

    func resolve(key: String) -> String { /* ... */ }
    func upload(key: String, data: Data) -> EventLoopFuture<String> { /* ... */ }
    func createDirectory(key: String) -> EventLoopFuture<Void> { /* ... */ }
    func list(key: String?) -> EventLoopFuture<[String]> { /* ... */ }
    func copy(key source: String, to destination: String) -> EventLoopFuture<String> { /* ... */ }
    func move(key source: String, to destination: String) -> EventLoopFuture<String> { /* ... */ }
    func delete(key: String) -> EventLoopFuture<Void> { /* ... */ }
    func exists(key: String) -> EventLoopFuture<Bool> { /* ... */ }


An extension on the FileStorageConfigurationFactory object that helps you to create the custom driver with the necessary config values.

public extension FileStorageConfigurationFactory {

    static func custom(exampleConfigVariable: String) -> FileStorageConfigurationFactory {
        .init { LiquidCustomStorageConfiguration(exampleConfigVariable) }


Stars: 2
Last commit: 4 weeks ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Release Notes

New API methods & better docs
20 weeks ago
  • The following API methods are now available:
    • resolve
    • upload
    • copy
    • move
    • create directory
    • delete
    • exists
  • There is a new LiquidError enum with a keyNotExists case for missing key errors.
  • Documentation is updated with driver implementation details
  • Dependencies are updated (swift-nio, swift-log)

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API