All Projects → ilyapuchka → graphique

ilyapuchka / graphique

Licence: MIT license
Experimental GraphQL query builders

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to graphique

Match3Kit
Library for simple Match3 games.
Stars: ✭ 38 (+58.33%)
Mutual labels:  swift5
DailyFeed
iOS client for newsapi.org
Stars: ✭ 128 (+433.33%)
Mutual labels:  swift5
audioStreamDemo
A music player created in swift using AVPlayer to stream audio from server.
Stars: ✭ 33 (+37.5%)
Mutual labels:  swift5
Windows11
💻 Windows 11 in SwiftUI.
Stars: ✭ 177 (+637.5%)
Mutual labels:  swift5
PagedLists
Paginated UITableView and UICollectionViews for iOS.
Stars: ✭ 69 (+187.5%)
Mutual labels:  swift5
AnyImageKit
A toolbox for pick/edit/capture photo or video. Written in Swift.
Stars: ✭ 580 (+2316.67%)
Mutual labels:  swift5
skillbox
Выполненные и принятые домашние задания, а также другие материалы, которые могут помочь в обучении
Stars: ✭ 32 (+33.33%)
Mutual labels:  swift5
BottomSheet
A sliding Sheet from the bottom of the Screen with 3 States build with SwiftUI.
Stars: ✭ 597 (+2387.5%)
Mutual labels:  swift5
GPhotos
A wrapper around the Google Photos API.
Stars: ✭ 21 (-12.5%)
Mutual labels:  swift5
STKitSwift
STKitSwift is a collection of useful classes and categories to develop Apps faster.
Stars: ✭ 56 (+133.33%)
Mutual labels:  swift5
iOSUtilitiesSource
IOS Utilities Library for Swift
Stars: ✭ 46 (+91.67%)
Mutual labels:  swift5
OKKLineMin
OKKLineMin kline for min for learning for iPhone (support Swift5 & the latest Swift & iPhone & iOS 16)(min K线图 用于学习了解)
Stars: ✭ 23 (-4.17%)
Mutual labels:  swift5
Pulse
❤️ A heart rate camera pulse detector written in Swift.
Stars: ✭ 53 (+120.83%)
Mutual labels:  swift5
SwiftUIDemo
A demo app showing you how to build a table view and navigation interface with SwiftUI
Stars: ✭ 26 (+8.33%)
Mutual labels:  swift5
GradientAnimator
GradientAnimator helps to fill your view with vibrant gradient theme colours and animates them to give a stunning view to your application design
Stars: ✭ 70 (+191.67%)
Mutual labels:  swift5
DTContainerController
A Swift container view controller to handle transitioning to a different child view controller.
Stars: ✭ 20 (-16.67%)
Mutual labels:  swift5
IGListKit-AsyncDisplayKit-Example
IGListKit be used with AsyncDisplayKit in Swift
Stars: ✭ 34 (+41.67%)
Mutual labels:  swift5
LeagueAPI
League of Legends API & Data Framework in Swift
Stars: ✭ 50 (+108.33%)
Mutual labels:  swift5
QuoteKit
A framework to use the free APIs provided by https://quotable.io
Stars: ✭ 17 (-29.17%)
Mutual labels:  swift5
JewelCase
This is the source code for JewelCase, a sample app demonstrating how to use SwiftUI and Firebase together. This slide deck discusses the architecture of the app: https://www.slideshare.net/peterfriese/building-swiftui-apps-with-firebase
Stars: ✭ 42 (+75%)
Mutual labels:  swift5

graphique

This library attempts to implement GraphQL query DSL using Swift 5.1 function builders.

Note: updated for Xcode 12 beta 6

To start you define your models as regular Swift types:

import Graphique

struct Hero {
  let id: String
  let name: String
  let episode: Episode
  let friends: [Hero]
}

enum Episode: String {
  case newHope = "NEWHOPE"
  case empire = "EMPIRE"
  case jedi = "JEDI"
}

To use these models with Graphique you need to:

  • Implement GQLEntity protocol on the models you want to query by defining a mapping for your entity key paths
extension Hero: GQLEntity {
  struct GQLEntityKeyPaths: GQLEntityKeyPath {
    let id              = \Hero.id
    let name            = \Hero.name
    let episode         = \Hero.episode
    let friends         = \Hero.friends
  }
}

GQLEntityKeyPaths type will be used to convert key paths you use in a query to strings using Mirror. I.e. here \Hero.id will be converted to "id", \Hero.name will be converted to "name". This is needed because Swift does not provide any introspection on KeyPath type.

  • Conform types you want to use as query arguments to GQLObjectQueryArgumentsRepresentable
extension Episode: GQLObjectQueryArgumentsRepresentable {}

This conformance is used to convert argument values you use in a query to strings (default implementation is provided by the library so there is no need for you to add any implementation details).

  • Define your "root" query object
let hero = Query<Hero>("hero")

You will use this function in a query to specify the actual type of a query you want to perform, i.e. if you want to query all episodes you will add the following query object:

let episode = Query<Episode>("episode")

Or you can use string literals to give names to your queries (or mutations):

let hero: Query<Hero> = "hero"

With that you can start building your queries.

Basic query

// GraphQL

query {
  hero {
    name
    friends {
      name
    }
  }
}

// Swift

query("") {
  hero {
    \.name
    lens(\.friends) {
      \.name
    }
  }
}

Arguments

// GraphQL

query {
  hero(episode: JEDI) {
    name
  }
}

// Swift

query("") {
  hero(\.episode == .jedi) {
    \.name
  }
}

Aliases

// GraphQL

query {
  empireHero: hero(episode: EMPIRE) {
    id
    name
  }
  jediHero: hero(episode: JEDI) {
    id
    name
  }
}

// Swift

query("") {
  "empireHero" == hero(\.episode == .empire) {
    \.id
    \.name
  }
  "jediHero" == hero(\.episode == .jedi) {
    \.id
    \.name
  }
}

Fragments

// GraphQL

query {
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Hero {
  id
  name
  friends {
    id
    name
  }
}

// Swift

let comparisonFields = fragment("comparisonFields", on: Hero.self) {
  \.id
  \.name

  lens(\.friends) {
    \.id
    \.name
  }
}

// or

var comparisonFields: GQLObjectQueryFragment<Hero> {
  fragment {
    \.id
    \.name

    lens(\.friends) {
      \.id
      \.name
    }
  }
}

query("") {
  "leftComparison" == hero(\.episode == .empire) {
    ...comparisonFields
  }
  "rightComparison" == hero(\.episode == .jedi) {
    ...comparisonFields
  }
}

Using variables inside fragments

TBD

Operation name

// GraphQL

query HeroQuery {
  hero(episode: JEDI) {
    id
    name
  }
}

// Swift

query("HeroQuery") {
  hero(\.episode, .jedi) {
    \.id
    \.name
  }
}

// or

func HeroQuery() -> GQLQuery<Hero> {
  query {
    hero(\.episode, .jedi) {
      \.id
      \.name
    }
  }
}

In the last example the query will get the name of the function where it is defined.

Variables

// GraphQL

query HeroQuery($episode: Episode = JEDI) {
  hero(episode: $episode) {
    name
  }
}

// Swift

func HeroQuery(episode: Episode = .jedi) -> GQLQuery<Hero> {
  query {
    hero(\.episode == episode) {
      \.name
    }
  }
}

Note that the resulting query will have its parameters replaced with actuall values you pass to the query function, so if you call let query = HeroQuery() it will create a query

query HeroQuery {
  hero(episode: jedi) {
    name
  }
}

Directives

TBD

Mutations

// GraphQL

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

{
  "ep": "JEDI",
  "review": {
    "stars": 5,
    "commentary": "This is a great movie!"
  }
}

// Swift
let createReview = Mutation<CreateReview>("createReview")

func CreateReviewForEpisode(episode: Episode, review: Review) -> GQLMutation<CreateReview> {
  mutation {
    createReview(\.episode == episode, \.review == review) {
      \.stars
      \.commentary
    }
  }
}

Inline Fragments

// GraphQL

query {
  hero {
    name
    ... on Droid {
      primaryFunction
    }
    ... on Human {
      height
    }
  }
}

// Swift

query("") {
  hero {
    \.name
    ...on(Droid.self) {
      \.primaryFunction
    }
    ...on(Human.self) {
      \.height
    }
  }
}

Meta fields

// GrahpQL

query {
  hero {
    __typename
    name
  }
}

// Swift

query {
  hero {
    \.__typename
    \.name
  }
}

Limitations

  • inline fragments do not enforce types to be related, e.g. Droid and Human to be subtypes of Hero.
  • to use inline fragments you'll need to use classes for models, not structs
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].