Swiftpack.co -  Package - reddavis/Papyrus
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
reddavis/Papyrus
Papyrus aims to hit the sweet spot between saving raw API responses to the file system and a fully fledged database like Realm.
.package(url: "https://github.com/reddavis/Papyrus.git", from: "v0.9.0")

Papyrus

Papyrus aims to hit the sweet spot between saving raw API responses to the file system and a fully fledged database like Realm.

struct Car: Papyrus
{
    let id: String
    let model: String
    let manufacturer: String
}

let car = Car(id: "abc...", model: "Model S", manufacturer: "Tesla")
let store = try PapyrusStore()
store.save(car)

Requirements

  • iOS 14.0+
  • macOS 11.0+

Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/reddavis/Papryrus", from: "0.9.0")
]

Documentation

API Reference

Usage

All write functions are synchronous and have asynchonous counterparts. Variety is the spice of life after all.

Saving

Anything that conforms to the Papyrus protocol can be stored.

Example A - Basic Saving

struct Car: Papyrus
{
    let id: String
    let model: String
    let manufacturer: String
}

let car = Car(id: "abc...", model: "Model S", manufacturer: "Tesla")
let store = try PapyrusStore()
store.save(car)

Example B - Eventual Saving

struct Car: Papyrus
{
    let id: String
    let model: String
    let manufacturer: String
}

let car = Car(id: "abc...", model: "Model S", manufacturer: "Tesla")
let store = try PapyrusStore()
store.saveEventually(car)

Example C - Relationships

Papyrus also understands relationships. If we continue with our Car modelling...Let's imagine we have an app that fetches a list of car manufacturers and their cars.

Our models could look like:

struct Manufacturer: Papyrus
{
    let id: String
    let name: String
    let cars: [Car]
}

struct Car: Papyrus
{
    let id: String
    let model: String
}

let modelS = Car(id: "abc...", model: "Model S")
let tesla = Manufacturer(id: "abc...", name: "Tesla", cars: [modelS])
let store = try PapyrusStore()
store.save(tesla)

Because Car also conforms to Papyrus, PapyrusStore will also persist the cars when it saves the manufacturer.

Example D - Merge

A common use case when dealing with API's is to fetch a collection of objects and the merge the results into your local collection.

Merge also has a async counterpart mergeEventually(objects:).

Papyrus provides a function for this:

let carA = Car(id: "abc...", model: "Model S", manufacturer: "Tesla")
let carB = Car(id: "def...", model: "Model 3", manufacturer: "Tesla")
let carC = Car(id: "ghi...", model: "Model X", manufacturer: "Tesla")

let store = try PapyrusStore()
store.save(objects: [carA, carB])

store.merge(with: [carA, carC])
store
    .objects(type: Car.self)
    .execute()
// #=> [carA, carC]

Fetching by ID

Fetching objects has two forms:

  • Fetch by id.
  • Fetch collection.

Example A

let store = try PapyrusStore()
let tesla = store.object(id: "abc...", of: Manufacturer.self)

Fetching collections

Papryrus gives you the ability to fetch, filter and observe colletions of objects.

Example A - Simple fetch

let manufacturers = self.store
                        .objects(type: Manufacturer.self)
                        .execute()

Example B - Filtering

let manufacturers = self.store
                        .objects(type: Manufacturer.self)
                        .filter { $0.name == "Tesla" }
                        .execute()

Example C - Sorting

let manufacturers = self.store
                        .objects(type: Manufacturer.self)
                        .sort { $0.name < $1.name }
                        .execute()

Calling observe() on a PapryrusStore.Query object will return a Combine publicher which will emit the collection of objects. Unless specified the publisher will continue to emit a collection objects whenever a change is detected.

A change constitutes of:

  • Addition of an object.
  • Deletion of an object.
  • Update of an object.

Example D - Observing changes

self.store
    .objects(type: Manufacturer.self)
    .observe()
    .subscribe(on: DispatchQueue.global())
    .receive(on: DispatchQueue.main)
    .sink { self.updateUI(with: $0) }
    .store(in: &self.cancellables)

Example E - All together

self.store
    .objects(type: Manufacturer.self)
    .filter { $0.name == "Tesla" }
    .sort { $0.name < $1.name }
    .observe()
    .subscribe(on: DispatchQueue.global())
    .receive(on: DispatchQueue.main)
    .sink { self.updateUI(with: $0) }
    .store(in: &self.cancellables)

Deleting

There are several methods for deleting objects.

Example A

let store = try PapyrusStore()
let tesla = store.object(id: "abc...", of: Manufacturer.self)
store.delete(tesla)

Example B

let store = try PapyrusStore()
let tesla = store.object(id: "abc...", of: Manufacturer.self)
store.deleteEventually(tesla)

Example C

let store = try PapyrusStore()
store.delete(id: "abc...", of: Manufacturer.self)

Example D

let store = try PapyrusStore()
let tesla = store.object(id: "abc...", of: Manufacturer.self)
let ford = store.object(id: "xyz...", of: Manufacturer.self)
store.delete(objects: [tesla, ford])

License

Whatevs.

GitHub

link
Stars: 7
Last commit: 1 week ago

Release Notes

v0.9.0
15 weeks ago

You probably shouldn't use yet

🤞

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