Swiftpack.co - Package - markuswntr/apicalypse


A simple Swift module for creating Apicalypse queries.

Release Version Build Status Codacy Swift Version Twitter: @markuswntr

Basic example

Say you have your usual-suspect User model:

struct User {
    let id: Int
    let name: String
    let age: Int?

To use this model as query entity, all you have to do is make User conform to Composable and link KeyPaths to CodingKeys

extension User: Composable {

    static func codingPath(for keyPath: PartialKeyPath<User>) throws -> CodingKey {
        switch keyPath {
        case \User.id: return CodingKeys.id
        case \User.name: return CodingKeys.name
        case \User.age: return CodingKeys.age
        default: throw Error.invalidKeyPath(keyPath)

Now you can write type-safe Queries on User using KeyPaths:

let query = try Query(entity: User.self)
    .include(contentsOf: .allFields) // Include all fields of the user, i.e. `id`, `name` and `age`
    .where(\User.age > 20) // Ignore users that are of age 20 or younger
    .exclude(\.age) // Also, exclude age on all users in the response
    .sort(by: \.name, order: .ascending) // Sorted by their name

Advanced example

Given the following struct Game and enum Game.Category

struct Game: Composable {

    enum Category: Int, CustomStringConvertible {
        case mainGame = 1
        case expansion
        var description: String {
            return String(rawValue)

    enum CodingKeys: String, CodingKey {
        case identifier = "id"
        case name, category
        case platforms
        case screenshots

    var identifier: UInt64
    var name: String
    var category: Category
    var platforms: [UInt64]
    var screenshots: [UInt64]?

    static func codingPath(for keyPath: PartialKeyPath<Game>) throws -> CodingKey {
        switch keyPath {
        case \Game.identifier: return CodingKeys.identifier
        case \Game.name: return CodingKeys.name
        case \Game.category: return CodingKeys.category
        case \Game.platforms: return CodingKeys.platforms
        case \Game.screenshots: return CodingKeys.screenshots
        default: throw Error.invalidKeyPath(keyPath)

A more advanced Query (that makes no sense whatsoever, but shows a lot of the built-in features) may look like:

let query = try Query(entity: Game.self)
    .include(\.name)        // Include name ...
    .include(\.releaseDate) // ... and releaseDate
    .include(\.screenshots) // ... and screenshots
    .include(contentsOf: [\Game.category, \Game.platforms]) // ... and category and platforms

    .exclude(\.releaseDate) // Then exclude releaseDate...
    .exclude(contentsOf: [\Game.platforms]) // .. and platforms

    // Only main games that are on either platform with identifier 9, 6 or 12
    .where(\Game.category == .mainGame && \Game.platforms ~= [9, 6, 12])
    // Only games, that do have screenshots
    .where(\Game.screenshots != nil)
    // Only games where name start with "zelda" (~= means case-insensitive)
    // or have "Mario" somewhere in there name (== means case-sensitive)
    .where(\Game.name ~= "zelda"* || \Game.name == *"Mario"*)

    .sort(by: \.releaseDate, order: .ascending)
    .sort(by: \.category) // `order` will default to .descending

Warning: Multiple where-Filter are not (yet) supported. Last where will always win.


Swift Package Manager

If you want to use Apicalypse in a project that uses SPM, it's as simple as adding a dependencies clause to your Package.swift:

dependencies: [
    .package(url: "https://github.com/markuswntr/apicalypse.git", from: Version(1, 0, 0))

Then import Apicalypse wherever necessary.

Hope you enjoy Apicalypse

For more updates on Apicalypse, and my other open source projects, follow me on Twitter: @markuswntr

Also make sure to check out IGDB, that lets you interact with the igdb.com API, to see Apicalypse in action


Stars: 0
Help us keep the lights on


Used By

Total: 1


1.0.1 - Jan 24, 2019

  • Add single to many Filter
  • Fixes invalid access modifier on Filter.
  • Fixes some input strings in Filter conversion

1.0.0 - Jan 24, 2019

🎉 Apicalypse 1.0 is here!

Stay tuned for future updates - and better documentation.