Coder Social home page Coder Social logo

trevorblades / countries Goto Github PK

View Code? Open in Web Editor NEW
446.0 10.0 68.0 1.93 MB

🌎 Public GraphQL API for information about countries

Home Page: https://countries.trevorblades.com

License: MIT License

JavaScript 2.71% TypeScript 97.29%
countries continents languages apollo graphql graphql-api public-api api free schema

countries's Introduction

globe

Countries GraphQL API

Build Status Contributor Covenant Twitter Follow

A public GraphQL API for information about countries, continents, and languages. This project uses Countries List and provinces as data sources, so the schema follows the shape of that data, with a few exceptions:

  1. The codes used to key the objects in the original data are available as a code property on each item returned from the API.
  2. The Country.continent and Country.languages are now objects and arrays of objects, respectively.
  3. The Country.currency and Country.phone fields sometimes return a comma-separated list of values. For this reason, this API also exposes currencies and phones fields that are arrays of all currencies and phone codes for a country.
  4. Each Country has an array of states populated by their states/provinces, if any.
  5. Each Country also has an awsRegion field that shows its nearest AWS region, powered by country-to-aws-region.

Writing queries

query GetCountry {
  country(code: "BR") {
    name
    native
    capital
    emoji
    currency
    languages {
      code
      name
    }
  }
}

The above GraphQL query will produce the following JSON response:

{
  "data": {
    "country": {
      "name": "Brazil",
      "native": "Brasil",
      "capital": "Brasília",
      "emoji": "🇧🇷",
      "currency": "BRL",
      "languages": [
        {
          "code": "pt",
          "name": "Portuguese"
        }
      ]
    }
  }
}

Check out the playground to explore the schema and test out some queries.

Filtering

The countries, continents, and languages top-level Query fields accept an optional filter argument that causes results to be filtered on one or more subfields. The continents and languages fields can be filtered by their code, while countries can be filtered by code, currency, or continent.

Note: The continent filter on the Query.countries field must be the continent code, i.e. "SA" for South America.

The filtering logic is powered by sift and this API supports the following operators: eq, ne, in, nin, and regex. To learn more about these operators and how they work, check out the sift docs.

Here are some examples of filtering that you can copy and paste into the playground to try for yourself:

query ListCountriesThatUseUSD {
  countries(filter: { currency: { eq: "USD" } }) {
    code
    name
  }
}

query ListCountriesInNAFTA {
  countries(filter: { code: { in: ["US", "CA", "MX"] } }) {
    code
    name
    languages {
      name
    }
  }
}

query ListCountriesThatBeginWithTheLetterA {
  countries(filter: { name: { regex: "^A" } }) {
    code
    name
    currency
  }
}

Examples

License

MIT

Powered by Stellate, the GraphQL API Management platform

countries's People

Contributors

dependabot[bot] avatar franp-code avatar gabrielsroka avatar harounchebbi avatar martinkavik avatar muhsin-k avatar pelletier197 avatar skoofer avatar trevorblades avatar zaneturner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

countries's Issues

Issue with the 'name' Field in GraphQL Playground and the Need for README Update"

I am encountering an issue in GraphQL Playground despite the query being shown as an example in the README file. It seems like the name field has been removed from the filter parameters, so it may require an update to the README file. Below, I'm providing the error message along with the query:

GraphQL Query:

query ListCountriesThatBeginWithTheLetterA {
  countries(filter: { name: { regex: "^A" } }) {
    code
    name
    currency
  }
}

Error Message:

{
  "errors": [
    {
      "message": "Field \"name\" is not defined by type \"CountryFilterInput\".",
      "locations": [
        {
          "line": 2,
          "column": 22
        }
      ]
    }
  ]
}

the README.md link
the playground link

Surprising response data

Just some ideas for future improvements. See code with comments below.


Input A:

query CountryA {
  country(code: "NO") {
    languages {
      code
      name
      native
      rtl
    }
  }
}

Output A:

{
  "data": {
    "country": {
      "languages": [
         ...
        {
          "code": "nb",
          "name": null,    // missing data in data-source?
          "native": null,   // missing data in data-source?
          "rtl": false
        },
        ...
      ]
    }
  }
}

Input B:

query CountryB {
  country(code: "AQ") {
    capital
    currency
  }
}

Output B:

{
  "data": {
    "country": {
      "capital": "",   // should be nullable?
      "currency": ""  // should be nullable?
    }
  }
}

413 Payload Too Large

Hi,

I've been working on a GraphQL project and testing it with the Countries API, https://countries.trevorblades.com/
Recently I started getting an error like this for queries of more than 3 or 4 levels deep:

  "message": "Query depth limit exceeded.",
  "extensions": {
    "code": "GCDN_QUERY_DEPTH_LIMIT",
    "httpStatusCode": 413
  }

I'm just wondering if this was an intentional change to the API, or a mistake - I can run a local instance of the API if needed.

Query Returning null?

I'm trying to filter the countries by continent. i.e List the countries as per the continent. I am getting a null and it does'nt make much sense why its not working:

This is my query:

query { countries(filter: {continent: {eq: "Africa"}}){ name, capital } }

400 Bad Request for websockets endpoint

Hi,

I am the maintainer of the graphql-python/gql client and we make a great use of your countries website for our examples in our documentation. A big thanks for your website which provides a stable backend when we need to do some simple tests sometimes.

It has been brought to my attention recently that all the examples involving the websockets protocol are not working anymore (the http protocol continues to work fine).

Now we always receive a 400 Bad Request response when trying to connect to the websockets endpoint.

If I try to run the following code with gql version 3.1.0:

import asyncio                                                                                                          
import logging                                                                                                          
                                                                                                                        
from gql import Client, gql                                                                                             
from gql.transport.websockets import WebsocketsTransport                                                                
                                                                                                                        
logging.basicConfig(level=logging.DEBUG)                                                                                
                                                                                                                        
                                                                                                                        
async def main():                                                                                                       
                                                                                                                        
    transport = WebsocketsTransport(                                                                                    
        url="wss://countries.trevorblades.com/graphql",                                                                 
        subprotocols=[WebsocketsTransport.APOLLO_SUBPROTOCOL],                                                          
    )                                                                                                                   
                                                                                                                        
    async with Client(                                                                                                  
        transport=transport, fetch_schema_from_transport=True,                                                          
    ) as session:                                                                                                       
                                                                                                                        
        # Execute single query                                                                                          
        query = gql(                                                                                                    
            """                                                                                                         
            query getContinents {                                                                                       
              continents {                                                                                              
                code                                                                                                    
                name                                                                                                    
              }                                                                                                         
            }                                                                                                           
        """                                                                                                             
        )                                                                                                               
        result = await session.execute(query)                                                                           
        print(result)                                                                                                   
                                                                                                                        
                                                                                                                        
asyncio.run(main())

Then I receive the following result:

DEBUG:asyncio:Using selector: EpollSelector
DEBUG:gql.transport.websockets:connect: starting
DEBUG:websockets.client:= connection is CONNECTING
DEBUG:websockets.client:> GET /graphql HTTP/1.1
DEBUG:websockets.client:> Host: countries.trevorblades.com
DEBUG:websockets.client:> Upgrade: websocket
DEBUG:websockets.client:> Connection: Upgrade
DEBUG:websockets.client:> Sec-WebSocket-Key: ZK9W8vXCkiwnBMzyG0UnSA==
DEBUG:websockets.client:> Sec-WebSocket-Version: 13
DEBUG:websockets.client:> Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
DEBUG:websockets.client:> Sec-WebSocket-Protocol: graphql-ws
DEBUG:websockets.client:> User-Agent: Python/3.8 websockets/10.2
DEBUG:websockets.client:< HTTP/1.1 400 Bad Request
DEBUG:websockets.client:< access-control-allow-origin: *
DEBUG:websockets.client:< content-type: text/html; charset=utf-8
DEBUG:websockets.client:< content-length: 18
DEBUG:websockets.client:< etag: W/"12-7JEJwpG8g89ii7CR/6hhfN27Q+k"
DEBUG:websockets.client:< date: Mon, 11 Apr 2022 19:33:55 GMT
DEBUG:websockets.client:< connection: keep-alive
DEBUG:websockets.client:< keep-alive: timeout=5
DEBUG:websockets.client:< server: Fly/523fc696 (2022-04-06)
DEBUG:websockets.client:< via: 1.1 fly.io
DEBUG:websockets.client:< fly-request-id: 01G0D1X9FAAFXFHY58RRYJ6WGX-fra
DEBUG:websockets.client:! failing connection with code 1006
DEBUG:websockets.client:x closing TCP connection
DEBUG:websockets.client:= connection is CLOSED
Traceback (most recent call last):
  File "docs/code_examples/websockets_async.py", line 36, in <module>
    asyncio.run(main())
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "docs/code_examples/websockets_async.py", line 17, in main
    async with Client(
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/site-packages/gql/client.py", line 580, in __aenter__
    await self.transport.connect()
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/site-packages/gql/transport/websockets_base.py", line 491, in connect
    self.websocket = await asyncio.wait_for(
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/asyncio/tasks.py", line 483, in wait_for
    return fut.result()
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/asyncio/tasks.py", line 684, in _wrap_awaitable
    return (yield from awaitable.__await__())
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/site-packages/websockets/legacy/client.py", line 650, in __await_impl_timeout__
    return await asyncio.wait_for(self.__await_impl__(), self.open_timeout)
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/asyncio/tasks.py", line 483, in wait_for
    return fut.result()
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/site-packages/websockets/legacy/client.py", line 658, in __await_impl__
    await protocol.handshake(
  File "/home/leszek/miniconda3/envs/gql-dev/lib/python3.8/site-packages/websockets/legacy/client.py", line 328, in handshake
    raise InvalidStatusCode(status_code, response_headers)
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 400

It has been a while that I tested this so this could have been the case for a long time already.

Additonal functionalities

Hello, great api. I would like to ask if it is possible to add new functionalities such filtering countries by continent. It would be a great addition

Cannot read properties of undefined (reading 'toString')

Query:
{ countries(filter: {code: {eq: "US"}}) { states { name value: code } } }

Response:
{ "errors": [ { "message": "Cannot read properties of undefined (reading 'toString')", "locations": [ { "line": 2, "column": 3 } ], "path": [ "countries" ], "extensions": { "code": "INTERNAL_SERVER_ERROR", "stacktrace": [ "TypeError: Cannot read properties of undefined (reading 'toString')", " at isVanillaObject (/var/task/netlify/functions/graphql/graphql.js:50619:107)", " at createQueryOperations (/var/task/netlify/functions/graphql/graphql.js:50864:14)", " at createQueryOperation (/var/task/netlify/functions/graphql/graphql.js:50850:18)", " at createDefaultQueryOperation (/var/task/netlify/functions/graphql/graphql.js:51293:16)", " at createDefaultQueryTester (/var/task/netlify/functions/graphql/graphql.js:51302:18)", " at resolve (/var/task/netlify/functions/graphql/graphql.js:58100:42)", " at field.resolve (/var/task/netlify/functions/graphql/graphql.js:54949:22)", " at executeField (/var/task/netlify/functions/graphql/graphql.js:8987:24)", " at executeFields (/var/task/netlify/functions/graphql/graphql.js:8962:24)", " at executeOperation (/var/task/netlify/functions/graphql/graphql.js:8933:18)" ] } } ], "data": null }

Optional fields & arguments

Hi!
Is there a reason why all fields and arguments are optional?

I'm writing GraphQL example for Seed and it makes code unnecessary complex because we have to take into account all valid possibilities.

Thank you.

Add a license

Hey man. I'm building a course on GraphQL and I'd love to use this as an example, but I need this repo to have a license in order to do that. Is this something you'd be willing to do?

Proposition: add static documentation

Hello! I am the maintainer of a documentation tool called Magidoc, a tool that generates static GraphQL API documentation references.

I would like to propose to integrate Magidoc into your great project to build a static API reference. This would allow users to easily get an overview of the whole API, but also other documentation that may be useful to use your API. You could even move all your examples or any other content you want there, since Magidoc supports Custom pages.

If you want to see an example, here is a link to a demo website.

I am also willing to help you integrate it if you want, and this could be hosted on any static content host: so can be GitHub pages, Netlify, Vercel, or anything else you want.

Let me know what you think about the idea, and feel free to close the issue if you're not interested.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.