Skip to content

Instantly share code, notes, and snippets.

@andriitishchenko
Last active April 30, 2024 03:50
Show Gist options
  • Save andriitishchenko/292f946c8f9fe08b1631d15e7c792cef to your computer and use it in GitHub Desktop.
Save andriitishchenko/292f946c8f9fe08b1631d15e7c792cef to your computer and use it in GitHub Desktop.
Swift + graphQL
var express = require("express")
var { createHandler } = require("graphql-http/lib/use/express")
var { ruruHTML } = require("ruru/server")
var casual = require('casual');
var { makeExecutableSchema } = require('@graphql-tools/schema');
var { addMocksToSchema } = require('@graphql-tools/mock');
// Fill this in with the schema string
const schemaString = `
type Post {
id: Int
title: String
text: String
views: Int
author: Author
}
type Author {
id: Int
firstName: String
lastName: String
posts: [Post]
}
type Query {
echo: String
author(firstName: String, lastName: String): Author
authorById(id: Int!): Author
allAuthors: [Author]
}
`
const mocks = {
Int: () => Math.floor(Math.random() * 100),
Float: () => 22.1,
String: () => 'Hello echo string',
DateTime: () => casual.date(/* format = 'YYYY-MM-DDTHH:mm:ss.SSSZZ' */),
Query: () => ({
author: ({firstName, lastName}) => {
return { firstName: firstName, lastName: lastName };
},
authorById: ({ id }) => {
return { id:id, firstName: casual.first_name, lastName: casual.last_name };
},
}),
Author: () => ({
firstName: () => casual.first_name,
lastName: () => casual.last_name }),
Post: () => ({
title:() => casual.title,
text: casual.sentences(3)
}),
};
// Make a GraphQL schema with no resolvers
const schema = makeExecutableSchema({ typeDefs: schemaString })
const preserveResolvers = false
const schemaWithMocks = addMocksToSchema({
schema,
mocks,
preserveResolvers
})
var app = express()
// Create and use the GraphQL handler.
app.all(
"/graphql",
createHandler({
schema: schemaWithMocks,
})
)
// Serve the GraphiQL IDE.
app.get("/", (_req, res) => {
res.type("html")
res.end(ruruHTML({ endpoint: "/graphql" }))
})
// Start the server at port
app.listen(4000)
console.log("Running a GraphQL API server at http://localhost:4000/graphql")

Query:

{
  authorById(id: 1) {
    id
    firstName
    lastName
    posts {
      id
      title
      text
      views
    }
  }
  testString
}

Responce:

{
  "data": {
    "authorById": {
      "id": 1,
      "firstName": "Leslie",
      "lastName": "Jacobson",
      "posts": [
        {
          "id": 53,
          "title": "Ex eum autem",
          "text": "Rem aperiam exercitationem nostrum dolorem neque. Eaque totam saepe sed animi sint dolore corporis. Tempora nihil rem ipsum voluptas.",
          "views": 26
        },
        {
          "id": 16,
          "title": "Ut adipisci iusto",
          "text": "Est est accusantium repellat sequi necessitatibus quia nesciunt delectus voluptates. Quo nisi eius aut quas. Et illo eaque voluptatem repudiandae quis quis ipsam suscipit et.",
          "views": 64
        }
      ]
    },
    "testString": "Hello"
  }
}

Project target name: GraphQLDemo

xcode -> add Apollo package dependency

Select project in xcode and install CLI for Apollo (via context menu)

apollo-ios-cli must added

switch to terminal, navigate to project root dir

./apollo-ios-cli init --schema-namespace MyAPI --target-name GraphQLDemo --module-type embeddedInTarget

apollo-codegen-config.json must generated

edit apollo-codegen-config.json and add section:

"schemaDownloadConfiguration": {
    "downloadMethod": {
          "introspection": {
              "endpointURL": "http://localhost:4000/graphql",
              "httpMethod": {
                  "POST": {}
              },
              "includeDeprecatedInputValues": false,
              "outputFormat": "SDL"
          }
      },
      "downloadTimeout": 60,
      "headers": [],
      "outputPath": "./graphql/schema.graphqls"
  }

execute

./apollo-ios-cli fetch-schema

./graphql/schema.graphqls generated

create new file ./graphql/query.graphql

query DemoRequest {
  authorById(id: 1) {
    id
    firstName
    lastName
    posts {
      id
      title
      text
      views
    }
  }
  testString
}

execute

./apollo-ios-cli generate

GraphQLDemo/MyAPI generated

Drag MyAPI to xcode project

import Apollo
...

        let store = ApolloStore(cache: InMemoryNormalizedCache())
        let interceptorProvider = DefaultInterceptorProvider(store: store)        
        let networkTransport = RequestChainNetworkTransport(
            interceptorProvider: interceptorProvider,
            endpointURL: URL(string: "http://localhost:4000/graphql")!,
            autoPersistQueries: true
        )

        let client = ApolloClient(networkTransport: networkTransport, store: store)
        let r = MyAPI.DemoRequestQuery()
        client.fetch(query: r) { result in
            guard let data = try? result.get().data else {
                print(result)
                return
            }
            print(data.testString)
        }
        

in my case fetch failed with error

failure(Apollo.ResponseCodeInterceptor.ResponseCodeError.invalidResponseCode(response: Optional(<NSHTTPURLResponse: 0x600000226960> { URL: http://localhost:4000/graphql } { Status Code: 400,

as a workaround :


struct NetworkInterceptorProvider: InterceptorProvider {
    private let store: ApolloStore
    private let client: URLSessionClient
    
    init(store: ApolloStore, client: URLSessionClient) {
        self.store = store
        self.client = client
    }
    
    func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
        return [
            MaxRetryInterceptor(),
            CacheReadInterceptor(store: self.store),
            NetworkFetchInterceptor(client: self.client),
            ResponseCodeInterceptor(),
            JSONResponseParsingInterceptor(),
            AutomaticPersistedQueryInterceptor(),
            CacheWriteInterceptor(store: self.store)
        ]
    }
}
...

        let store = ApolloStore(cache: InMemoryNormalizedCache())
//        let interceptorProvider = DefaultInterceptorProvider(store: store)
        let cl = URLSessionClient()
        let interceptorProvider = NetworkInterceptorProvider(store: store, client: cl)
        
        let networkTransport = RequestChainNetworkTransport(
            interceptorProvider: interceptorProvider,
            endpointURL: URL(string: "http://localhost:4000/graphql")!,
            autoPersistQueries: false
        )


Install Node

brew install node

install deps

npm install express graphql-http graphql ruru casual @graphql-tools/mock @graphql-tools/schema --save

download app.js

start local servre

node app.js

test

curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ echo }"}' \
http://localhost:4000/graphql

Responce:
{"data":{"testString":"Hello"}}%   

MacOS GUI client

Altair GraphQL Client

Altair GraphQL Client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment