swift filestore

Lightweight key-value store with Structured Concurrency API

6
1
Swift

swift-filestore

Lightweight key-value store with Structured Concurrency API.

MIT License
Package Releases
Build Results
Swift Version
Supported Platforms

Why swift-filestore?

If your app is built with Swift Concurrency and is in need for a lightweight key-value storage solution, swift-filestore should be a good fit.

It is a key-value persistence solution which provides CRUD operation and change stream APIs under Swift’s Structured Concurrency(async/await, AsyncSequence).
Under the hood it simply serializes each object into a separate file, no databases or caches solutions are involved. This keeps your app lean and stable.

Quick Start

Obtain an instance by calling FileObjectStore.create(). The method simply create a root directory under app’s Application Support directory.
In rare cases where it fails to create the directory, you can choose to fallback to a in-memory implementation of ObjectStore, or can handle it in your own way.

func createWithFallback() -> ObjectStore {
  do {
    return try FileObjectStore.create()
  } catch {
    return MemoryObjectStore()
  }
}

swift-filestore does not require developers to create new struct/classes for your data model. For example, to use JSON serialization, just have your existing model conform to JSONDataRepresentable.


struct MyModel: Codable, JSONDataRepresentable {
    let id: String
    let value: String
}

let model = MyModel()
try await objectStore.write(key: model.id, namespace: "MyModels", object: model)

Object Change Stream

swift-filestore offers an object change subscription API via Swift Concurrency.

for try await model in await objectStore.observe(key: id, namespace: "MyModels", objectType: MyModel.self) {
    // process the newly emitted model object
}

Custom serialization/deserialization

If you are looking for non-json serializations, you can define your custom serialization/deserialization protocol as below:


protocol BinaryDataRepresentable: DataRepresentable {}

extension BinaryDataRepresentable {

  public func serialize() throws -> Data {
    // your custom serialization goes here...
  }
  
  public static func from(data: Data) throws -> Self {
    // your custom deseriazation goes here...
  }
}

struct MyModel: BinaryDataRepresentable {
    let id: String
    let value: String
}

PersistenceLog

swift-filestore offers an immutable logging component named PersistenceLog. It allows developer to store records on the disk and flush them at the right time. It can be used as an alternative to in-memory logging, which may risk data loss because app can be terminated at any time by user or the system.

Below code demonstrates how to use PersistenceLog to store and send in-app analytic events:

//data model for the analytics log
struct AnalyticsEvent: Codable, JSONDataRepresentable {
    let name: String
    let metaData: String
}

//initialization
let log = try PersistenceLogImpl<AnalyticsEvent>(name: "analytics-log")

//When new event is triggered
try await log.append(event1)

//When it's time to flush and sent to remote server
let events = try await log.flush()
try await networkClient.sendAnalytics(events)