SkillAgentSearch skills...

CodyFire

๐ŸŒธ Powerful Codable API requests builder and manager for iOS.

Install / Use

/learn @CodyFlame/CodyFire
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Mihael Isaev

<p align="center"> <a href="LICENSE"> <img src="https://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT License"> </a> <a href="https://swift.org"> <img src="https://img.shields.io/badge/swift-4.2-brightgreen.svg" alt="Swift 4.2"> </a> <a href="https://discord.gg/q5wCPYv"> <img src="https://img.shields.io/discord/612561840765141005" alt="Swift.Stream"> </a> </p> <br>

This lib is about network requests with blackjack, roulette and craps!

Using it you will be able to convert your massive API layer code into an awesome convenient controllers with easy and maintainable network requests!

Use Codable models for everything related to API requests:

  • json payload
  • url-encoded payload
  • multipart payload
  • plain and json response
  • url query
  • headers

Wondered? That's only little part of what you will get from this lib! ๐Ÿป

Quick examples

How to send GET request

APIRequest<ResponseModel>("endpoint").onSuccess { model in
    //here's your decoded model!
    //no need to check http.statusCode, I already did it for you! By default it's 200 OK
    //of course you can choose which statusCode is equal to success (look at the `POST` and `DELETE` examples below)
}

How to send POST request

APIRequest<ResponseModel>("endpoint", payload: payloadModel)
    .method(.post)
    .desiredStatusCode(.created) //201 CREATED
    .onSuccess { model in
    //here's your decoded model!
    //success was determined by comparing desiredStatusCode with http.statusCode
}

How to send DELETE request

APIRequest<Nothing>("endpoint")
    .method(.delete)
    .desiredStatusCode(.noContent) //204 NO CONTENT
    .onSuccess { _ in
    //here's empty successful response!
    //success was determined by comparing desiredStatusCode with http.statusCode
}

How to send several requests?

You're able to run up to 10 requests one-by-one!

API.employee.all()
    .and(API.office.all())
    .and(API.car.all())
    .and(API.event.all())
    .and(API.post.all())
    .onError { error in
        print(error.description)
    }.onSuccess { employees, offices, cars, events, posts in
   // do what you want with received results!!! ๐Ÿป
}

Or you can run unlimited amount of requests one-by-one or at the same time, if you need just a completion handler.

[API.employee.all(), API.office.all(), API.car.all()].flatten().onError {
    print(error.description)
}.onSuccess {
    print("flatten finished!")
}

to run them concurrently just add .concurrent(by: 3) to run by 3 at the same time

Of course you'll be able to send PUT and PATCH requests, send multipart codable structs with upload progress callback, catch errors, even redefine error descriptions for every endpoint. Wondered? ๐Ÿ˜ƒ Let's read the whole readme below! ๐Ÿป

How to install

CodyFire is available through CocoaPods and SPM.

To install it, simply add the following line in your Podfile:

pod 'CodyFire', '~> 1.15.4'

Or you're looking for reactive code support? I have it! ๐Ÿบ

  • for RxSwift https://github.com/MihaelIsaev/RxCodyFire
pod 'RxCodyFire', '~> 1.1.0'
# no need to install `CodyFire` cause it's in dependencies

using this pod you should always import just RxCodyFire and every APIRequest will have .observable

  • for ReactiveCocoa https://github.com/MihaelIsaev/ReactiveCodyFire
pod 'ReactiveCodyFire', '~> 1.1.0'
# no need to install `CodyFire` cause it's in dependencies

using this pod you should always import just ReactiveCodyFire and every APIRequest will have .signalProducer

How to setup

CodyFire automatically detects which environment you're on, so I suggest you to definitely use this awesome feature ๐Ÿ‘

import CodyFire

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        let dev = CodyFireEnvironment(baseURL: "http://localhost:8080")
        let testFlight = CodyFireEnvironment(baseURL: "https://stage.myapi.com")
        let appStore = CodyFireEnvironment(baseURL: "https://api.myapi.com")
        CodyFire.shared.configureEnvironments(dev: dev, testFlight: testFlight, appStore: appStore)
        //Also if you want to be able to switch environments manually just uncomment the line below (read more about that)
        //CodyFire.shared.setupEnvByProjectScheme()
        return true
    }
}

Isn't it cool? ๐Ÿ˜

Or you can set different Server URL for every APIRequest

let server1 = ServerURL(base: "https://server1.com", path: "v1")
let server2 = ServerURL(base: "https://server2.com", path: "v1")
let server3 = ServerURL(base: "https://server3.com")

And then initialize your APIRequests like this ๐Ÿ”ฅ

APIRequest(server1, "endpoint", payload: payloadObject)
APIRequest(server2, "endpoint", payload: payloadObject)
APIRequest(server3, "endpoint", payload: payloadObject)

Or in some cases you even can do it like this ๐Ÿ˜

APIRequest("endpoint", payload: payloadObject).serverURL(server1)

Create your API controllers

I promise that this is API code architecture from your dreams which are come true!

Create an API folder and API.swift file inside it

class API {
    typealias auth = AuthController
    typealias task = TaskController
}

Create a folder named Controllers inside API folder, and create a folder for each controller

API/Controllers/Auth/Auth.swift

class AuthController {}

API/Controllers/Task/Task.swift

class TaskController {}

Create an extension file for each controller's endpoint

Auth login as simple POST request

API/Controllers/Auth/Auth+Login.swift

import CodyFire
extension AuthController {
  struct LoginRequest: JSONPayload {
        let email, password: String
        init (email: String, password: String) {
            self.email = email
            self.password = password
        }
    }

    struct LoginResponse: Codable {
        var token: String
    }

    static func login(_ request: LoginRequest) -> APIRequest<LoginResponse> {
        return APIRequest("login", payload: request).method(.post).addCustomError(.notFound, "User not found")
    }
}
Auth login for Basic auth

API/Controllers/Auth/Auth+Login.swift

import CodyFire
extension AuthController {
    struct LoginResponse: Codable {
        var token: String
    }

    static func login(email: String, password: String) -> APIRequest<LoginResponse> {
        return APIRequest("login").method(.post).basicAuth(email: email, password: password)
            .addCustomError(.notFound, "User not found")
    }
}
Task REST endpoints
Get task by id or a list of tasks by offset and limit

API/Controllers/Task/Task+Get.swift

import CodyFire
extension TaskController {
    struct Task: Codable {
        var id: UUID
        var name: String
    }

    struct ListQuery: Codable {
        var offset, limit: Int
        init (offset: Int, limit: Int) {
            self.offset = offset
            self.limit = limit
        }
    }

    static func get(_ query: ListQuery? = nil) -> APIRequest<[Task]> {
        return APIRequest("task").query(query)
    }

    static func get(id: UUID) -> APIRequest<Task> {
        return APIRequest("task/" + id.uuidString)
    }
}
Create a task

API/Controllers/Task/Task+Create.swift

import CodyFire
extension TaskController {
    struct CreateRequest: JSONPayload {
        var name: String
        init (name: String) {
            self.name = name
        }
    }

    static func create(_ request: CreateRequest) -> APIRequest<Task> {
        return APIRequest("post", payload: request).method(.post).desiredStatusCode(.created)
    }
}
Edit a task

API/Controllers/Task/Task+Edit.swift

import CodyFire
extension TaskController {
    struct EditRequest: JSONPayload {
        var name: String
        init (name: String) {
            self.name = name
        }
    }

    static func create(id: UUID, request: EditRequest) -> APIRequest<Task> {
        return APIRequest("post/" + id.uuidString, payload: request).method(.patch)
    }
}
Delete a task

API/Controllers/Task/Task+Delete.swift

import CodyFire
extension TaskController {
    static func delete(id: UUID) -> APIRequest<Nothing> {
        return APIRequest("post/" + id.uuidString).method(.delete).desiredStatusCode(.noContent)
    }
}

Easily use your API endpoints!

Send login request
API.auth.login(email: "test@mail.com", password: "qwerty").onError { error in
    switch error.code {
    case .notFound: print("User not found")
    default: print(error.description)
    }
}.onSuccess { token in
    print("Received auth token: "+ token)
}
Get a list of tasks
API.task.get().onError { error in
    print(error.description)
}.onSuccess { tasks in
    print("received \(tasks.count) tasks")
}
Create a task
API.task.create(TaskController.CreateRequest(name: "Install CodyFire")).onError { error in
    print(error.description)
}.onSuccess { task in
    print("just created new task: \(task)")
}
Delete a task
let taskId = UUID()
API.task.delete(id: taskId).onError { error in
    print(error.description)
}.onSuccess { _ in
    print("just removed task with id: \(taskId)")
}

Multipart example

//declare a PostController
class PostController()
extension PostController {
    struct CreateRequest: MultipartPayload {
        var text: String
        var tags: [String]
        var images: [Att

Related Skills

View on GitHub
GitHub Stars253
CategoryDevelopment
Updated2mo ago
Forks18

Languages

Swift

Security Score

95/100

Audited on Jan 6, 2026

No findings