From 62fa4adaea442c8af56a38f6bfee93fb99efebfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veljko=20Tekelerovi=C4=87?= Date: Wed, 20 Dec 2023 16:36:13 +0100 Subject: [PATCH] Updated README and initial Documentation. Provided basic app samples. Closes #30 Closes #40 Closes #26 --- Docs/Examples/Grab_example.swift | 32 +++ Docs/Examples/Push_example.swift | 44 +++++ {Guides => Docs}/Fridge.diagram.md | 0 {Guides => Docs}/Usage.md | 7 +- .../Fridge basics.playground/Contents.swift | 54 ------ .../contents.xcplayground | 4 - README.md | 182 +++++++----------- 7 files changed, 156 insertions(+), 167 deletions(-) create mode 100644 Docs/Examples/Grab_example.swift create mode 100644 Docs/Examples/Push_example.swift rename {Guides => Docs}/Fridge.diagram.md (100%) rename {Guides => Docs}/Usage.md (93%) delete mode 100644 Guides/Examples/Fridge basics.playground/Contents.swift delete mode 100644 Guides/Examples/Fridge basics.playground/contents.xcplayground diff --git a/Docs/Examples/Grab_example.swift b/Docs/Examples/Grab_example.swift new file mode 100644 index 0000000..67124fa --- /dev/null +++ b/Docs/Examples/Grab_example.swift @@ -0,0 +1,32 @@ +import UIKit +import Fridge + +//MARK: - Basic network Grab example + +// define your URL endpoint +let todoEndpoint = URL(string: "https://jsonplaceholder.typicode.com/todos/")! + +// conform your struct to Decodable +struct ToDo: Decodable { + var id: Int + var title: String + var completed: Bool +} + +//TODO: Use other async methods that serve your needs +async { + print("---> Grabbing all TODO objects from URL endpoint using Fridge") + do { + // ** Grab with Fridge !! ** + let results: [ToDo] = try await Fridge.grab🔮(from: todoEndpoint) + + // do something with results.... + for item in results { + print("ID:\t\(item.id)") + print("Title:\t\(item.title)") + } + } catch let fridgeError { + // handle any errors that we received + print("Grab failed. Error: \(fridgeError)") + } +} diff --git a/Docs/Examples/Push_example.swift b/Docs/Examples/Push_example.swift new file mode 100644 index 0000000..4468353 --- /dev/null +++ b/Docs/Examples/Push_example.swift @@ -0,0 +1,44 @@ +import UIKit +import Fridge + +//MARK: - Simple network Push example + +// define your URL endpoint +let networkEndpoint = URL(string: "https://jsonplaceholder.typicode.com/comments/")! + +// Conform your struct to Codable +struct Comment: Codable, CustomDebugStringConvertible { + let postId: Int + let id: Int + let name: String + let email: String + let body: String + + var debugDescription: String { + return "[Comment] (ID:\(id)) \(name) - \(email). Body: \(body)" + } +} + +//TODO: Use other async methods that serve your needs +async { + print("---> Pushing custom struct to URL endpoint using Fridge...") + do { + let newComment = Comment( + postId: 12, + id: 100, + name: "New comment", + email: "some@email.com", + body: "Body of the new comment" + ) + + // ** Push data using Fridge !! ** + let response: Comment = try await Fridge.push📡(newComment, to: networkEndpoint) + + // handle response... + print("New comment successfuly pushed") + print("Returned response: ", response) + } catch let fridgeError { + // handle any errors that we received + print("Grab failed. Error: \(fridgeError)") + } +} \ No newline at end of file diff --git a/Guides/Fridge.diagram.md b/Docs/Fridge.diagram.md similarity index 100% rename from Guides/Fridge.diagram.md rename to Docs/Fridge.diagram.md diff --git a/Guides/Usage.md b/Docs/Usage.md similarity index 93% rename from Guides/Usage.md rename to Docs/Usage.md index 9aedf75..9561cd5 100644 --- a/Guides/Usage.md +++ b/Docs/Usage.md @@ -11,7 +11,12 @@ For deeper information, you can check `in-code` documentation. --- -## Network fetching +## Network fetching +|Method|Description| +|-|-| +`Fridge.grab🔮(from: URL)`|Grabs your model from the network endpoint (_iOS 15+ only_)| +|`Fridge.push📡(object, to)`|Pushes (sends) your model to designated network endpoint (_iOS 15+ only_)| + With Fridge, network fetching is performed in just 3 steps: 1. Conform your desired `struct` to `Decodable` 2. Define `URL` endpoint where your model resides diff --git a/Guides/Examples/Fridge basics.playground/Contents.swift b/Guides/Examples/Fridge basics.playground/Contents.swift deleted file mode 100644 index 5ff730c..0000000 --- a/Guides/Examples/Fridge basics.playground/Contents.swift +++ /dev/null @@ -1,54 +0,0 @@ -import UIKit -import Fridge - -//MARK: Grab example - -let todoEndpoint = URL(string: "https://jsonplaceholder.typicode.com/todos/")! -struct ToDo: Decodable { - var id: Int - var title: String - var completed: Bool -} - -async { - print("--> Grabbing all TODO objects...") - do { - let results: [ToDo] = try await Fridge.grab🔮(from: todoEndpoint) - // print all the results - for item in results { - print("ID:\(item.id) - \(item.title)") - } - print("|\nSuccessfully grabbed \(results.count) ToDO objects\n-----") - } catch { - print("Grab failed.") - } -} - -//MARK: - Push example - -struct Comment: Codable, CustomDebugStringConvertible { - let postId: Int - let id: Int - let name: String - let email: String - let body: String - - var debugDescription: String { - return "[Comment] (ID:\(id)) \(name) - \(email). Body: \(body)" - } -} - -async { - print("--> Posting new comment...") - do { - - let newComment = Comment(postId: 12, id: 100, name: "New comment", email: "some@email.com", body: "Body of the new comment") - - let response: Comment = try await Fridge.push📡(newComment, to: "https://jsonplaceholder.typicode.com/comments/") - - print("New comment successfuly pushed.\nReturned (response) object:") - print(response) - } catch { - print("Push failed") - } -} diff --git a/Guides/Examples/Fridge basics.playground/contents.xcplayground b/Guides/Examples/Fridge basics.playground/contents.xcplayground deleted file mode 100644 index ebe9554..0000000 --- a/Guides/Examples/Fridge basics.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/README.md b/README.md index a2850dc..b1b8620 100644 --- a/README.md +++ b/README.md @@ -3,145 +3,110 @@

- Fridge - extremely simple async/await fetch-and-store implementation you'll ever see !
- Let your fancy struct(s) raise and shine again, allowing you to focus on 💬 🥊🤖⭐️🗝 stuff.

-

-

- - - - - - - - - -
- - Release build - - - - GitHub release (latest by date) - - - Platforms - License -
+ Fridge is Swift based freezing device.
+ It helps you fetch-n-store data without major hassle.

+ Lightweight, Async/Await friendly, Zero dependency, Foundation based. + +
+ + GitHub release (latest by date) + + + + License + +

---- - - - -

+

Supported platforms

+ Platforms + + Issues + +

Tests

+ + Release build + Tets build - - Issues - -

-# 💠 Library interface -`Fridge` is a freezing device ❄️. It **has** to keep things cool enough, exposing just icy interface. +## 💠 Library description +`Fridge` is a freezing device ❄️ so it **has** to keep things cool enough, exposing just icy interface. -### Networking -|Method|Description| -|-|-| -`Fridge.grab🔮(from: URL)`|Grabs your model from the network endpoint (_iOS 15+ only_)| -|`Fridge.push📡(object, to)`|Pushes (sends) your model to designated network endpoint (_iOS 15+ only_)| - -Fridge networking model supports `async/await` philosophy and is here to reduce the pain of: +Fridge is designed to _reduce the pain with most common software operations_ such as **[fetching](#networking-🕸)** and **[storing](#persistant-local-storage-💾)** data. Or something like this: - fetching _your stuff_ from the network, - parsing or decoding (JSON) data, - doing boring _error checking_ - - and yeah... good old **closures**. - -With Fridge, you can even _say goodbye to closures and CoreData_ if you want! 🤷🏻‍♂️ + - storing _the stuff_ somewhere on disk + - doing boring _error checking_ again + - invoking more than 1 dependency for this (not using `Fridge`) + - and yeah... even cursing old **closures**. + - (not)doing tests -Checkout [documentation](Guides/Usage.md) for more information. +Fridge is so `async/await` friendly and designed with simplicity and flexibility in hand. With Fridge, you can even _say goodbye to closures and CoreData_ if you want! 🤷🏻‍♂️ -### Persistant (local) storage -|Method|Description| -|-|-| -`Fridge.freeze🧊(object, identifier)`|Safely "freezes" your `struct` to persistant store| -|`Fridge.unfreeze🪅🎉(identifier)`|"Unfreezes" (previously frozen), `struct` giving you control of it| +Checkout [documentation](Docs/Usage.md) for more information. -Fridge storage mechanics are built on Foundation principles and use `BSON` as internal storage mechanism. All you have to do is to conform your struct to `Encodable` and you're ready to go, Fridge will take care of the rest. - -Checkout [documentation](Guides/Usage.md) for more information. +> _Talking is cheap. Show me the code._ - Linus Torvalds -# Quick code example +## Networking 🕸 ```Swift -// 1. Conform your fancy struct to Decodable -struct GHRepo: Decodable { - var name: String - var repositoryURL: URL - // ... other fields +// define your endpoint +let endpoint = URL("https://github.com/vexy/")! + +// conform your fancy struct to Decodable +struct GitHubRepoObject: Decodable { + var name: String + var repositoryURL: URL + + // ... some other fields } +// use Fridge to grab🔮 data from the network endpoint do { - // 2. Await for grab🔮 method... - let myRepo: GHRepo = try await Fridge.grab🔮(from: URL("https://github.com/vexy/")!) + let myRepo: GitHubRepoObject = try await Fridge.grab🔮(from: endpoint) + + // do something with your object + print(myRepo) + print(myRepo.name) } catch let err { print("Naaah.. Something bad happened: \(err)") } +``` +Checkout more [_documentation on networking_](Docs/Usage.md#network-fetching) or start with basic [code **examples**](Docs/Examples/). + + +## Persistant (local) storage 💾 -// 3. Then, at your will, use myRepo as any other Foundation object -print(myRepo) -print(myRepo.name) +Fridge storage mechanics are built on Foundation principles and use `BSON` as internal storage mechanism. All you have to do is to conform your struct to `Encodable` and you're ready to go, Fridge will take care of the rest. + -// ... something ... +```Swift +// conform your fancy struct to Decodable +struct GitHubRepoObject: Decodable { + var name: String + var repositoryURL: URL +} -// 4. Later on... +// freeze it to local storage in just on line do { try Fridge.freeze🧊(myRepo, id: "myIdentifier") } catch let e { - print("Whoops... Here: \(e)") + print("Whoops... Can't freeze because: \(e)") } ``` -> _Talking is cheap. Show me the code._ - Linus Torvalds +Checkout [documentation](Docs/Usage.md) for more information. +# Real world use cases Here is some **real world** usage of `Fridge`: - - [**Clmn** - _Beautiful macOS app that operates with tasks in columns_](https://github.com/igr/Clmn) - - [Playground examples of Fridge practical usage](/Guides/Examples/Fridge%20basics.playground/Contents.swift) + - [Clmn](https://github.com/igr/Clmn) - Beautiful macOS app that operates with tasks in columns + - [Sample code](/Docs/Examples) - with Fridge in practical usage -# Installation instructions +## Installation instructions Using `Swift Package Manager` is by far the sexiest way to install `Fridge`. ```Swift @@ -166,7 +131,7 @@ url: "https://github.com/vexy/Fridge.git" branch: "main" ``` -## Minimum versions required +### Minimum versions required For `Fridge` to work in full capacity, following Swift & iOS configuration is _recommended_: - Xcode `13.1+` - Swift `5.5` @@ -190,13 +155,14 @@ That may be helpfull for `Xcode 12.x`, assuming `Swift 5.x` is installed. Checkout official [Swift.org](https://www.swift.org/) website, for supporting earlier than minimums and other info. ## External dependencies -Fridge uses [BSONCoder v0.9](https://github.com/vexy/bsoncoder) - Copyright by [Vexy](https://github.com/vexy). -Check original library licencing information under licencing section in README file. + +Since `v1.0` Fridge **does not** use anything other than Foundation provided `JSONEncoder`. +Up to `v0.9.2` Fridge used [BSONCoder v0.9](https://github.com/vexy/bsoncoder) as main encoding device. # Documentation > _RTFM isn't a joke..._ 🥴 -In the **[Docs](Guides/Usage.md)** you'll quickly figure out how to: +In the **[Docs](Docs/Usage.md)** you'll quickly figure out how to: - *easily fetch object* from the network, - *persistently store* your objects, - *load them back* into your app,