Posted about 2 months by Jakob Gillich

When we launched Everbase, we provided everyone with the same API key because we prioritized improving our core product over everything else. As we're getting ready for beta, we're committing to maintaining a good quality of service, and this includes ending unauthorized access to our API.

You can now generate API keys in your account. Those keys are tied to your account quota, although we do not enforce any limit for now.

We ask you to transition to these keys until the 1st of August. After that date, we will start limiting requests on the shared API key to ensure a smooth transition.

If you have any questions, please contact us.

Posted 2 months by Jakob Gillich

Welcome to our third update! This time around, we have worked hard to greatly improve our in-schema documentation and we have removed some fields that were deprecated in the last release 3 months ago. We have also added a powerful new feature: web scraping.

Web scraping allows you to fetch and parse websites over a GraphQL interface, no backend required. Here's how you can get the latest posts on Hacker News:

{
  url(url: "https://news.ycombinator.com") {
    htmlDocument {
      title
      body {
        submissions: all(selector: "tr.athing") {
          rank: text(selector: "span.rank")
          text(selector: "a.storylink")
          url: attribute(selector: "a.storylink", name: "href")
          attrs: next {
            score: text(selector: "span.score")
            user: text(selector: "a.hnuser")
            comments: text(selector: "a:nth-of-type(3)")
          }
        }
      }
    }
  }
}

Executing this query returns a result like this:

{
  "data": {
    "url": {
      "htmlDocument": {
        "title": "Hacker News",
        "body": {
          "submissions": [
            {
              "rank": "1.",
              "text": "Anxiety Driven Development",
              "url": "https://andreschweighofer.com/agile/anxiety-in-product-development/",
              "attrs": {
                "score": "106 points",
                "user": "fidrelity",
                "comments": "31 comments"
              }
            },
            {
              "rank": "2.",
              "text": "I'm resigning from my job at Facebook",
              "url": "https://www.facebook.com/timothy.j.aveni/posts/3006224359465567",
              "attrs": {
                "score": "73 points",
                "user": "dredmorbius",
                "comments": "8 comments"
              }
            },
            {
              "rank": "3.",
              "text": "Blur Tools for Signal",
              "url": "https://signal.org/blog/blur-tools/",
              "attrs": {
                "score": "204 points",
                "user": "tosh",
                "comments": "106 comments"
              }
            },
            // ...
          ]
        }
      }
    }
  }
}

This is a very easy way to fetch data from websites that do not have their own APIs.

All Changes

Here is a list of all changes:

✖  Field countryName (deprecated) was removed from object type City
✖  Field capitalName (deprecated) was removed from object type Country
✖  Field A (deprecated) was removed from object type DNSRecords
✖  Field AAAA (deprecated) was removed from object type DNSRecords
✖  Field CNAME (deprecated) was removed from object type DNSRecords
✖  Field MX (deprecated) was removed from object type DNSRecords
⚠  Default value 1 was added to argument amount on field Currency.convert
⚠  Default value 18437736874454810000 was added to argument high on field Random.float
⚠  Default value -1.7976931348623157e+308 was added to argument low on field Random.float
⚠  Default value 2147483647 was added to argument high on field Random.int
⚠  Default value -2147483648 was added to argument low on field Random.int
⚠  Default value 16 was added to argument length on field Random.string
✔  Object type City has description A city is a large human settlement.
✔  Field City.continent has description The continent.
✔  Field City.country has description The country.
✔  Field City.geonamesID has description The Geonames.org ID.
✔  Field City.id has description The Wikidata ID.
✔  Field City.location has description The location.
✔  Field City.name has description The name.
✔  Field City.population has description The population.
✔  Field timeZone was added to object type City
✔  Field timeZoneDST was added to object type City
✔  Object type Client has description Information about the client that sent the request.
✔  Field Client.ipAddress has description The IP address.
✔  Field Client.userAgent has description The user agent.
✔  Object type Continent has description A continent is one of several very large landmasses.
✔  Field Continent.geonamesID has description The Geonames.org ID.
✔  Field Continent.id has description The Wikidata ID.
✔  Field Continent.name has description The name.
✔  Field Continent.population has description The population.
✔  Object type Coordinates has description Geographic coordinates.
✔  Field Coordinates.lat has description Latitude.
✔  Field Coordinates.long has description Longitude
✔  Object type Country has description A sovereign state.
✔  Field Country.alpha2Code has description The ISO 3166-1 alpha-2 code.
✔  Field Country.alpha3Code has description The ISO 3166-1 alpha-3 code.
✔  Field Country.callingCodes has description Calling codes.
✔  Field Country.capital has description The capital city.
✔  Field Country.cities has description All cities of the country.
✔  Field Country.continent has description The continent the country is located in.
✔  Field Country.currencies has description All official currencies of the country.
✔  Field Country.geonamesID has description The Geonames.org ID.
✔  Field Country.id has description The Wikidata ID.
✔  Field Country.languages has description All official languages of the country.
✔  Field Country.location has description The location.
✔  Field Country.name has description The name.
✔  Field Country.population has description The population.
✔  Field vatRate was added to object type Country
✔  Field Currency.countries has description Countries that use the currency.
✔  Field Currency.id has description The Wikidata ID.
✔  Field Currency.isoCode has description The ISO 4217 code.
✔  Field Currency.name has description The name.
✔  Field Currency.unitSymbols has description Unit symbols.
✔  Object type DomainName has description Domain Name of the Domain Name System (DNS).
✔  Field a was added to object type DomainName
✔  Field aaaa was added to object type DomainName
✔  Field cname was added to object type DomainName
✔  Field mx was added to object type DomainName
✔  Field DomainName.name has description The domain name.
✔  Field DomainName.records is deprecated
✔  Field DomainName.records has deprecation reason Use fields on domainName itself
✔  Field EmailAddress.address has description The email address.
✔  Field EmailAddress.domainName has description The host as a domain name.
✔  Field ok was added to object type EmailAddress
✔  Field EmailServiceProvider.domainName has description The domain name.
✔  Field smtpOk was added to object type EmailServiceProvider
✔  Type HTMLDocument was added
✔  Type HTMLNode was added
✔  Description Can be either a IPv4 or a IPv6 address.

This product includes GeoLite2 data created by MaxMind, available from www.maxmind.com. on type IPAddress has changed to Internet Protocol address. Can be either a IPv4 or a IPv6 address.

This product includes GeoLite2 data created by MaxMind, available from www.maxmind.com.
✔  Field IPAddress.address has description The IP address.
✔  Field IPAddress.city has description The city this IP address belongs to.
✔  Field IPAddress.country has description The country this IP address belongs to.
✔  Field IPAddress.type has description The IP address type.
✔  Field Language.alpha2Code has description The ISO 639-1 code.
✔  Field Language.countries has description The countries that use the language.
✔  Field Language.id has description The Wikidata ID.
✔  Field Language.name has description The name.
✔  Field MXRecord.exchange has description The domain name.
✔  Field MXRecord.preference has description The preference value.
✔  Object type Query has description Query is the root object of all queries.
✔  Field Query.client has description Get client info.
✔  Field htmlDocument was added to object type Query
✔  Field timeZones was added to object type Query
✔  Field Random.float has description Generate a float.
✔  Field Random.int has description Generate a integer.
✔  Field Random.string has description Generate a string.
✔  Type TimeZone was added
✔  Type TimeZoneWhere was added
✔  Field URL.domainName has description The host as a domain name.
✔  Field URL.host has description The host.
✔  Field htmlDocument was added to object type URL
✔  Field URL.path has description The path.
✔  Field URL.port has description The port.
✔  Field URL.query has description The query.
✔  Field URL.scheme has description The scheme.
✔  Field URL.url has description The full URL.

As always, you can also fetch and compare the schema in our schema repository.

Posted 6 months by Jakob Gillich

Everbase was initially built on top of Rust and Juniper, but we eventually switched over to the Crystal programming language - the why is a topic for another blog post. But what Crystal lacked was a great GraphQL library like Juniper - so we built one.

If you’re not interested in the backstory, head straight to our docs to learn more.

How GraphQL servers work

The three pillars of a GraphQL server implementation are:

  1. Query language parsing
  2. Field resolution
  3. Introspection

In any GraphQL implementation, the first two will look similar. Where they differ is in how they implement introspection.

But what is introspection, you ask? It’s what allows tools like GraphiQL to work. It’s an API that allows you to retrieve information about the types and structure of the API. Here is a query that works on any GraphQL-compliant API:

{
  __schema {
    types {
      name
      kind
    }
  }
}

The result is a list of types and their kind. Something like this:

{
  "data": {
    "__schema": {
      "types": [
        {
          "name": "Boolean",
          "kind": "SCALAR"
        },
        {
          "name": "City",
          "kind": "OBJECT"
        }
        // ...
      ]
    }
  }
}

A GraphQL API must be able to produce this type information at runtime. To achieve this, there are two common approaches.

Schema-First

Schema-first means you specify your schema separately from your implementation. In Graphql.js, you do this:

var schema = buildSchema(`
  type Query {
    hello: String
  }
`);

var root = {
  hello: () => {
    return 'Hello world!';
  },
};

First, we build a schema using a GraphQL definition, and then we provide an implementation. The schema is used to provide type information through the introspection API, and the implementation is used to resolve queries.

However, there is a big problem with this approach. What if my schema does not match the implementation? In the example above, what would happen if hello returns a number? Or what if we change the schema but forget to update the implementation?

It would fail at runtime. This is of course how dynamically typed languages work, and it becomes manageable through automated testing. But it’s not rare for errors to slip through unnoticed.

Statically typed languages offer a solution to this problem.

Code-First

With a code-first implementation, there is no schema. Your schema is your code. With our GraphQL library for Crystal, the example from above becomes:

class Query
  def hello : String
    "Hello world!"
  end
end

What if we return a number instead of a string? Compile error. What if we change the method return type but return something else? Compile error. What if we forget to set a return type? Sorry you can’t, also compile error.

The introspection information is generated through macros, so it’s guaranteed to match the implementation. Getting the schema is a single line of code, so we can have a test to ensure our schema doesn’t change in unexpected ways.

All of this is also standard Crystal code, so we can take full advantage of Crystal’s compiler and tooling to ensure our code is correct. This helps not only with development, where errors are caught quickly, it also increases the trust in your code. You will still have to write tests, but when you combine testing with Crystal’s static type checking, most errors are eliminated before they ever reach production.

Learn more

Here’s our documentation and here’s our Gitlab repo, please open an issue if you have questions.

Posted 6 months by Jakob Gillich

This is our first update, bringing you continents and city coordinates. Here is a complete list of what's new and changed:

  • Continent: new type
  • Coordinates: new type
  • City: added continent
  • City: added location
  • City: deprecated countryName
  • CityWhere: deprecated countryName
  • Country: deprecated capitalName
  • CountryWhere: deprecated capitalName
  • DNSRecords: deprecated A, added a
  • DNSRecords: deprecated AAAA, added aaaa
  • DNSRecords: deprecated MX, added mx
  • DNSRecords: deprecated CNAME, added cname
  • Query: added continents

For a schema diff, take a look at our schema repository.

This update brings us up to schema version 2.

If you run into any issues, please post on our Spectrum community.

Posted 6 months by Jakob Gillich

Everbase is currently in alpha. Let us explain what that means for you.

Breaking Changes

GraphQL makes it very easy to improve our API by adding new types and fields without breaking existing queries. This means we do not version our API like most REST APIs do. Instead, a breaking change will happen in phases:

  1. We announce deprecation of a field
  2. You remove usages of the deprecated field
  3. After a minimum period, we remove the field

In case a field is being renamed or refactored, we will introduce the new field together with the deprecation of the old field. Other changes such as renaming of a type will not go through these phases as they have no impact on your queries.

During our alpha, this process happens over a period of at least 2 weeks. We know that this is not a lot of time, but we want to keep the ability to make improvements as we see fit and move fast. In most cases, you will have significantly more time to transition. To get notified about breaking changes, please sign up for our newsletter.

Quality Of Service

We do not keep track of your quota so we ask you to be a good citizen of the internet and use our service responsibly. We are actively monitoring the quality of service, but we’re running a fairly small operation. Just something to keep in mind.

Questions?

If you have questions, join our community on Spectrum.

of 2