All Projects → paren-com → Serene

paren-com / Serene

Generate clojure.spec with GraphQL and extend GraphQL with clojure.spec

Programming Languages

clojure
4091 projects
clojurescript
191 projects

Projects that are alternatives of or similar to Serene

Miraql
GraphQL performance monitoring & error-handling tool
Stars: ✭ 97 (-26.52%)
Mutual labels:  api, graphql
Src Cli
Sourcegraph CLI
Stars: ✭ 108 (-18.18%)
Mutual labels:  api, graphql
Graphql Dotnetcore
GraphQL for .NET core based on https://github.com/graphql/graphql-js
Stars: ✭ 97 (-26.52%)
Mutual labels:  api, graphql
Projectartemis
An analytic tool for GraphQL queries to external APIs with a Graphical User Interface to view performance metrics.
Stars: ✭ 84 (-36.36%)
Mutual labels:  api, graphql
Next
Directus is a real-time API and App dashboard for managing SQL database content. 🐰
Stars: ✭ 111 (-15.91%)
Mutual labels:  api, graphql
Ariadne
Ariadne is a Python library for implementing GraphQL servers using schema-first approach.
Stars: ✭ 1,274 (+865.15%)
Mutual labels:  api, graphql
Strapi
🚀 Open source Node.js Headless CMS to easily build customisable APIs
Stars: ✭ 41,786 (+31556.06%)
Mutual labels:  api, graphql
Graphql Server
This is the core package for using GraphQL in a custom server easily
Stars: ✭ 65 (-50.76%)
Mutual labels:  api, graphql
Laqul
A complete starter kit that allows you create amazing apps that look native thanks to the Quasar Framework. Powered by an API developed in Laravel Framework using the easy GraphQL queries language. And ready to use the Google Firebase features.
Stars: ✭ 110 (-16.67%)
Mutual labels:  api, graphql
Json Serverless
Transform a JSON file into a serverless REST API in AWS cloud
Stars: ✭ 108 (-18.18%)
Mutual labels:  api, graphql
Purescript Graphql
End to End typesafe GraphQL with PureScript
Stars: ✭ 79 (-40.15%)
Mutual labels:  api, graphql
Directus
Open-Source Data Platform 🐰 — Directus wraps any SQL database with a real-time GraphQL+REST API and an intuitive app for non-technical users.
Stars: ✭ 13,190 (+9892.42%)
Mutual labels:  api, graphql
Requent
A GraphQL like interface to map a request to eloquent query with data transformation for Laravel.
Stars: ✭ 78 (-40.91%)
Mutual labels:  api, graphql
Graphql Portal
Configurable and distributed GraphQL Gateway. Convert your legacy data sources or monitor your existing GraphQL Services with a visual dashboard.
Stars: ✭ 88 (-33.33%)
Mutual labels:  api, graphql
Graphql Microservices
Showcasing a graphql microservice setup
Stars: ✭ 68 (-48.48%)
Mutual labels:  api, graphql
Graphql devise
GraphQL interface on top devise_token_auth
Stars: ✭ 100 (-24.24%)
Mutual labels:  api, graphql
Best Of Web Python
🏆 A ranked list of awesome python libraries for web development. Updated weekly.
Stars: ✭ 1,118 (+746.97%)
Mutual labels:  api, graphql
Android Okgraphql
Reactive GraphQl client for Android
Stars: ✭ 64 (-51.52%)
Mutual labels:  api, graphql
Flask Graphene Sqlalchemy
⚗️Project template to build a GraphQL API in Python
Stars: ✭ 109 (-17.42%)
Mutual labels:  api, graphql
Postgraphile
GraphQL is a new way of communicating with your server. It eliminates the problems of over- and under-fetching, incorporates strong data types, has built-in introspection, documentation and deprecation capabilities, and is implemented in many programming languages. This all leads to gloriously low-latency user experiences, better developer experiences, and much increased productivity. Because of all this, GraphQL is typically used as a replacement for (or companion to) RESTful API services.
Stars: ✭ 10,967 (+8208.33%)
Mutual labels:  api, graphql

Clojars Project

Serene

Generate clojure.spec with GraphQL and extend GraphQL with clojure.spec.

  • 100% GraphQL schema spec coverage
  • Works with any GraphQL API
  • Extend GraphQL with your own specs
  • Works with Clojure & ClojureScript

Clojure/conj 2018 - Robust APIs with clojure.spec & GraphQL

Robust APIs with clojure.spec & GraphQL - Clojure/conj 2018

Table of Contents

QuickStart

Serene can generate specs for an entire GraphQL API in one line of code.

Let's say you have a project called "Serenity" and a GraphQL API available at "http://localhost:3000/graphql":

(ns serenity.now
  (:require
   [clojure.spec.alpha :as s]
   [paren.serene :as serene]
   [paren.serene.schema :as schema]))

;; Define specs
(serene/def-specs (schema/fetch "http://localhost:3000/graphql"))

;; Use specs
(s/valid? ::User {:firstName "Frank" :lastName "Costanza"}) ;=> true

Rationale

It is our experience that GraphQL is superior to REST for most APIs used for web and mobile applications. We also think that clojure.spec provides a good balance of expressiveness and strictness.

GraphQL's type system provides a point of leverage for API providers and consumers. Because GraphQL schemas are introspectable, GraphQL tooling tends to be very powerful. Some languages, like OCaml/Reason, can even validate queries and response code at compile time.

If other languages can leverage GraphQL to this extent, Clojure should be able to as well. Serene aims to address this.

Usage

Generated Spec Names

Spec names are keywords that are prefixed and namespaced by their position in the schema. For the example below, let's assume a prefix of :gql, though the prefix is customizable.

# Built-in scalars are defined: :gql/Boolean, :gql/Float , :gql/ID , :gql/Int, :gql/String

scalar Email # :gql/Email

enum Mood { # :gql/Mood
  SERENE # :gql.Mood/SERENE
  ANNOYED # :gql.Mood/ANNOYED
  ANGRY # :gql.Mood/ANGRY
}

type User { # :gql/User
  id: ID! # :gql.User/id
  username: String! # :gql.User/username
  email: Email! # :gql.User/email
  mood: Mood # :gql.User/mood
}

type Mutation { # :gql/Mutation
  createUser(
    username: String!, # :gql.Mutation.createUser/username
    email: Email! # :gql.Mutation.createUser/email
    mood: Mood # :gql.Mutation.createUser/mood
    # :gql.Mutation.createUser/&args is an anonymous `s/keys` spec for args map
  ): User! # :gql.Mutation/createUser
}

Generating Specs

paren.serene/def-specs

Note: All arguments to def-specs are evaled.

def-specs is a macro that will define specs for a GraphQL schema. It takes compilation options as an optional second argument. Compilation options are documented below.

(serene/def-specs gql-schema options)

paren.serene/spit-specs

spit-specs is like def-specs, but outputs s/def forms to a file. The file path and namespace are the first two arguments to spit-specs.

(serene/spit-specs "src/api/specs.cljc" 'api.specs gql-schema options)

Getting your GraphQL Schema

paren.serene.schema/fetch

fetch takes a GraphQL server endpoint and optional configuration.

(schema/fetch "https://api.github.com/graphql" {:headers {"Authorization" (str "bearer " gh-access-token)}})

paren.serene.schema/query

query is this GraphQL introspection query string.

fetch works by asking the HTTP GraphQL server to execute query.

You can use query directly if your GraphQL API is not accessible via HTTP.

Compilation Options

:extend

:extend is a function or map of spec names to spec forms. If a spec form is returned, it will be combined with default specs using s/and.

For example, if you have a custom Keyword scalar you could use the following to add custom scalar validation:

(serene/def-specs gql-schema {:extend {:Keyword `keyword?}})

:alias

:alias is a function or map which receives unprefixed spec names and returns aliases for those names.

(serene/def-specs gql-schema {:alias {:Query #{:api/query :api.query/root}
                                      :Query/node :api.query/get-node}})

This would cause both :api/query and :api.query/root to be defined as aliases of the :Query type spec and would cause :api.query/get-node to be defined as an alias of the :Query/node field spec.

:prefix

:prefix is a wrapper around :alias for the common case of altering default *ns* prefixes.

For example, instead of having a long namespace prefix, you might want to prefix your specs with :gql:

(serene/def-specs gql-schema {:prefix :gql})

This will produce specs like :gql/Query, :gql.Query/node, etc.

:gen-object-fields

:gen-object-fields will cause test.check generators for object types to generate all fields, even though all object fields are optional.

This is necessary if you are using test.check to generate data for object, interface, or union types because all object fields are optional (clients can query for any combination of fields).

However, generating data for map specs where all keys are optional can be frustrating because you often end up with empty or nearly empty maps. It is also not possible to always generate all fields, because objects can be cyclic, so you have to stop after some predetermined level.

:gen-object-fields solves this by always generating all fields up to n where n is a configurable depth that defaults to s/*recursion-limit*.

;; modify all objects to generate `s/*recursion-limit*` levels deep
(serene/def-specs gql-schema {:gen-object-fields true})

;; modify only `Query` to generate 5 levels deep
(serene/def-specs gql-schema {:gen-object-fields {:Query 5}})

Custom Compilation Options

All compilation options are implemented and documented in paren.serene.compiler.transducers.

Custom compilation options can be added in the same way that default options are provided.

How It Works

Serene works in much the same way as GraphiQL and other GraphQL tools; it uses GraphQL's introspection capabilities. GraphQL schemas are introspectable, meaning that you can query a running API to determine all of the capabilities of that API.

Serene uses this introspection query, which is conveniently defined as paren.serene/introspection-query, to generate specs that match your API.

Status

If clojure.spec is alpha, then Serene is extra alpha.

Consider everything to be an implementation detail unless it is explicitly documented here.

Serene uses Break Versioning.

License

Copyright © Paren, LLC

Distributed under the Eclipse Public License version 2.0.

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].