SkillAgentSearch skills...

AnotherFuckingNetworkingSDK

A modern, lightweight Swift networking SDK built for iOS 15+ with async/await support. Type-safe API requests, built-in pagination, error handling, request logging with cURL commands, and mocking capabilities for testing. No dependencies, no bullshit, just clean API calls that actually work.

Install / Use

/learn @MikesHorcrux/AnotherFuckingNetworkingSDK
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

🔥 AnotherFuckingNetworkingSDK 🔥

Yet another Swift networking library, but this one actually doesn't suck. It's lightweight, powerful, and built for modern Swift with async/await. No bullshit, just clean API calls. ✨

Is it missing functionality? Maybe. But it fucking works, and you can just email < Your email here > with your complaints or contribute. Or don't. Whatever. 🤷‍♂️

✨ Features

  • ✅ 100% Swift, built for modern concurrency with async/await 🚀
  • ✅ Type-safe API requests and responses (so you can stop guessing what the hell your API returns) 🧩
  • ✅ Built-in pagination support that doesn't make you want to throw your laptop 💻🪟
  • ✅ Clear error handling that actually tells you what went wrong 🚨
  • ✅ Request logging with cURL command generation (inspect your requests like a grown-up) 🔍
  • ✅ Mocking support that makes testing not completely suck 🧪
  • ✅ Zero dependencies because who needs that fucking headache 🏝️
  • ✅ Works on iOS 15+, macOS 12+, and other Apple platforms nobody cares about 🍎

📦 Installation

Swift Package Manager

Add the following to your Package.swift file, or don't, I'm not your mom: 👩‍👧

dependencies: [
    .package(url: "https://github.com/MikesHorcrux/AnotherFuckingNetworkingSDK.git", from: "1.0.0")
]

Or in Xcode:

  1. Go to File → Add Packages... 📁
  2. Enter the repository URL: https://github.com/MikesHorcrux/AnotherFuckingNetworkingSDK.git
  3. Click "Add Package" and wait for Xcode to inevitably freeze for no reason ⏳❄️

🚀 Quick Start

1. Configure the client 🔧

import AnotherFuckingNetworkingSDK

// Set up the global shared client (the lazy way)
APIClient.shared.baseURL = URL(string: "https://api.example.com")
APIClient.shared.globalHeaders = ["Authorization": "Bearer YOUR_TOKEN"]

// Or be a fucking professional and create your own instance
let client = APIClient(baseURL: URL(string: "https://api.example.com"))

2. Define your models 📊

Make sure they conform to Decodable or you're gonna have a bad time: 💀

struct User: Decodable {
    let id: Int
    let name: String
    let email: String
    let isAdmin: Bool
    
    // Handle snake_case if your backend devs hate camelCase
    enum CodingKeys: String, CodingKey {
        case id, name, email
        case isAdmin = "is_admin"
    }
}

3. Create request types 📝

This is where the magic happens. Each API endpoint gets its own request type: 🪄

// Simple GET request
struct GetUserRequest: Request {
    typealias ReturnType = User // Tell it what you expect back
    
    let userID: Int
    var path: String { "users/\(userID)" } // Define the endpoint path
}

// POST request with a body
struct CreateUserRequest: Request {
    typealias ReturnType = User
    
    let name: String
    let email: String
    let password: String
    
    var path: String { "users" }
    var method: HTTPMethod { .post } // Override the default GET
    
    // Define the request body
    var body: Data? {
        try? JSONEncoder().encode([
            "name": name,
            "email": email,
            "password": password
        ])
    }
}

// Request with query parameters
struct SearchUsersRequest: Request {
    typealias ReturnType = [User]
    
    let query: String
    let limit: Int
    
    var path: String { "users/search" }
    
    var queryItems: [URLQueryItem]? {
        [
            URLQueryItem(name: "q", value: query),
            URLQueryItem(name: "limit", value: "\(limit)")
        ]
    }
}

// Request with custom headers
struct AuthenticateRequest: Request {
    typealias ReturnType = AuthResponse
    
    let username: String
    let password: String
    
    var path: String { "auth/login" }
    var method: HTTPMethod { .post }
    
    var headers: [String: String]? {
        ["Content-Type": "application/json"] 
    }
    
    var body: Data? {
        try? JSONEncoder().encode([
            "username": username,
            "password": password
        ])
    }
}

4. Make API calls with async/await ⚡

func fetchUser(id: Int) async {
    do {
        let userRequest = GetUserRequest(userID: id)
        let user = try await APIClient.shared.send(userRequest)
        print("Got user: \(user.name), \(user.email)")
    } catch let error as NetworkError {
        handleNetworkError(error)
    } catch {
        print("Some other shit went wrong: \(error)")
    }
}

5. Paginated requests that don't suck 📄📄📄

struct ListUsersRequest: PaginatedRequest {
    typealias ReturnType = User
    
    var path: String { "users" }
    let page: Int
    let pageSize: Int
}

func fetchAllUsers() async {
    var currentPage = 1
    var hasMorePages = true
    var allUsers: [User] = []
    
    while hasMorePages {
        do {
            let request = ListUsersRequest(page: currentPage, pageSize: 20)
            let response = try await APIClient.shared.sendPage(request)
            
            allUsers.append(contentsOf: response.items)
            
            // Check if there's a next page
            if let nextPage = response.nextPage {
                currentPage = nextPage
            } else {
                hasMorePages = false
            }
        } catch {
            print("Error fetching users: \(error)")
            hasMorePages = false
        }
    }
    
    print("Fetched a total of \(allUsers.count) users")
}

🧠 Advanced Usage

Setting up a proper service layer 🏢

Don't be a barbarian. Structure your API calls in service classes: 🏗️

class UserService {
    private let client: APIClient
    
    // Dependency injection for testability
    init(client: APIClient = APIClient.shared) {
        self.client = client
    }
    
    func getUser(id: Int) async throws -> User {
        let request = GetUserRequest(userID: id)
        return try await client.send(request)
    }
    
    func createUser(name: String, email: String, password: String) async throws -> User {
        let request = CreateUserRequest(name: name, email: email, password: password)
        return try await client.send(request)
    }
    
    func searchUsers(query: String, limit: Int = 20) async throws -> [User] {
        let request = SearchUsersRequest(query: query, limit: limit)
        return try await client.send(request)
    }
    
    func listUsers(page: Int = 1, pageSize: Int = 20) async throws -> PaginatedResponse<User> {
        let request = ListUsersRequest(page: page, pageSize: pageSize)
        return try await client.sendPage(request)
    }
}

Error handling that actually makes sense 🚫

func handleNetworkError(_ error: NetworkError) {
    switch error {
    case .invalidURL:
        // You fucked up the URL 🤦‍♂️
        showAlert(title: "Invalid URL", message: "Contact the developer, they can't type URLs correctly")
        
    case .requestFailed(let statusCode, let data):
        // The server fucked up 💩
        switch statusCode {
        case 401:
            // Token expired or invalid
            refreshTokenAndRetry()
        case 403:
            showAlert(title: "Access Denied", message: "You're not allowed to do that, buddy")
        case 404:
            showAlert(title: "Not Found", message: "The thing you're looking for doesn't exist")
        case 500..<600:
            showAlert(title: "Server Error", message: "The server is having a bad day")
        default:
            if let data = data, let errorJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
                print("Server said: \(errorJson)")
            }
            showAlert(title: "Error \(statusCode)", message: "Something went wrong")
        }
        
    case .decodingFailed(let decodingError):
        // The JSON decoder fucked up 💥
        print("Decoding error: \(decodingError)")
        showAlert(title: "Data Error", message: "Could not understand the server response")
        
    case .unknown(let underlyingError):
        // Something else fucked up 🤷‍♂️
        print("Unknown error: \(underlyingError)")
        showAlert(title: "Unknown Error", message: underlyingError.localizedDescription)
    }
}

🧪 Testing with Mock Responses

Because tests that hit real APIs are stupid and unreliable. 👎

1. Set up your test class 🏗️

import XCTest
@testable import YourAppModule
import AnotherFuckingNetworkingSDK

class UserServiceTests: XCTestCase {
    
    var mockClient: MockAPIClient!
    var userService: UserService!
    
    override func setUp() {
        super.setUp()
        // Create a mock client instead of hitting real APIs
        mockClient = MockAPIClient()
        
        // Inject the mock into your service
        userService = UserService(client: mockClient)
    }
    
    override func tearDown() {
        mockClient.resetMocks()
        mockClient = nil
        userService = nil
        super.tearDown()
    }

2. Test a successful request ✅

func testGetUser() async throws {
    // 1. Create fake data 🤥
    let mockUser = User(id: 42, name: "Arthur Dent", email: "arthur@earth.com", isAdmin: false)
    
    // 2. Tell the mock what to return
    mockClient.mock(GetUserRequest.self, with: mockUser)
    
    // 3. Call the API through your service
    let user = try await userService.getUser(id: 42)
    
    // 4. Verify you got what you expected
    XCTAssertEqual(user.id, 42)
    XCTAssertEqual(user.name, "Arthur Dent")
    XCTAssertEqual(user.email, "arthur@earth.com")
    
    // 5. Verify the correct request was made
    XCTAssertTrue(mockClient.calledRequests.contains("users/42"))
}

3. Test with fake errors ❌

func testGetUserError() async {
    // 1. Set up a mock error 💣
    let mockError = NetworkError.requestFailed(statusCode: 404, data: nil)
    mockClient.mockError(GetUserRequest.self, with: mockError)
    
    // 2. Try to call the API and expect an error
    do {
        _ = try a

Related Skills

View on GitHub
GitHub Stars31
CategoryDevelopment
Updated6mo ago
Forks1

Languages

Swift

Security Score

67/100

Audited on Oct 9, 2025

No findings