Skip to content

Commit

Permalink
Readme and ci setup
Browse files Browse the repository at this point in the history
  • Loading branch information
maticzav committed Apr 4, 2018
1 parent 5febcbc commit efb2da6
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 116 deletions.
17 changes: 17 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
jobs:
build:
docker:
- image: 'circleci/node:latest'
steps:
- checkout
- run:
name: install
command: npm install
- run:
name: test
command: |
npm run test
- run:
name: release
command: npm run semantic-release || true
151 changes: 65 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,28 @@
# graphql-middleware

> NOTE: This repo is still WIP
<p align="center"><img src="media/logo.png" width="800" /></p>

## What's `graphql-middleware`?
# graphql-middleware

* Middlewares can be wrapped (based on provided order)
[![CircleCI](https://circleci.com/gh/maticzav/graphql-middleware.svg?style=shield)](https://circleci.com/gh/maticzav/graphql-middleware)
[![npm version](https://badge.fury.io/js/graphql-middleware.svg)](https://badge.fury.io/js/graphql-middleware)
![npm](https://img.shields.io/npm/dt/graphql-middleware.svg)

### What it does
All in one solution to manage middleware in your GraphQL projects.

* Value transformation
* Override arguments
* Error handling (throw & catch errors)
* Globbing syntax
## Overview

### What is doesn't
GraphQL Middleware is a schema wrapper which allows you to easily manage additional functionality accross multiple resolvers.

* Does **not** change the exposed GraphQL schema
* __Easiest way to handle GraphQL middleware:__ Intuitive, yet familiar API will get under your skin in a second.
* __Powerful:__ Allows complete control over your resolvers (Before, After).
* __Compatible:__ Works with any GraphQL Schema.

## Install

```sh
yarn add graphql-middleware
```

## API

### Field middleware

A field middleware is a resolver function that wraps another resolver function

```ts
type IFieldMiddlewareFunction = (
resolve: Function,
parent: any,
args: any,
context: any,
info: GraphQLResolveInfo,
) => Promise<any>

interface IFieldMiddlewareTypeMap {
[key: string]: IFieldMiddlewareFunction | IFieldMiddlewareFieldMap
}

interface IFieldMiddlewareFieldMap {
[key: string]: IFieldMiddlewareFunction
}

type IFieldMiddleware = IFieldMiddlewareFunction | IFieldMiddlewareTypeMap

function applyFieldMiddleware(schema: GraphQLSchema, ...middlewares: IFieldMiddleware[]): GraphQLSchema
```

### Document middleware

```ts
interface GraphQLResponse {
data: any
errors?: any[]
extensions?: any
}
type IDocumentMiddlewareFunction = (
execute: Function,
rootValue: any,
context: any,
info: GraphQLResolveInfo,
): Promise<GraphQLResponse>
function applyDocumentMiddleware(schema: GraphQLSchema, ...middlewares: IDocumentMiddlewareFunction[]): GraphQLSchema
```

## Examples
## Usage

```ts
import { applyFieldMiddleware } from 'graphql-middleware'
Expand All @@ -90,15 +42,6 @@ const beepMiddleware = {
},
}

const responseSizeMiddleware = async (execute, rootValue, context, info) => {
const response = await execute(rootValue, context, info)
if (count(response) > 1000) {
throw new Error('Response too big')
}
return response
}
const typeDefs = `
type Query {
hello(name: String): String
Expand All @@ -112,17 +55,21 @@ const resolvers = {

const schema = makeExecutableSchema({ typeDefs, resolvers })

const schemaWithFieldMiddlewares = applyFieldMiddleware(schema, metricsMiddleware, authMiddleware, beepMiddleware)
const schemaWithDocumentMiddlewares = applyDocumentMiddleware(schemaWithFieldMiddlewares, responseSizeMiddleware)
const schemaWithFieldMiddlewares = applyFieldMiddleware(
schema,
metricsMiddleware,
authMiddleware,
beepMiddleware,
)
```

### Usage with `graphql-yoga`

`graphql-yoga` has built-in support for `graphql-middleware`
> `graphql-yoga` has built-in support for `graphql-middleware`!
```ts
import { GraphQLServer } from 'graphql-yoga'
import { authMiddleware, metricsMiddleware, responseSizeMiddleware } from './middlewares'
import { authMiddleware, metricsMiddleware } from './middlewares'

const typeDefs = `
type Query {
Expand All @@ -139,36 +86,68 @@ const server = new GraphQLServer({
typeDefs,
resolvers,
fieldMiddlewares: [authMiddleware, metricsMiddleware],
documentMiddlewares: [responseSizeMiddleware],
documentMiddlewares: [],
})
server.start(() => console.log('Server is running on localhost:4000'))
```

## Terminology
### Examples

## API

A middleware is a resolver function that wraps another resolver function.

```ts
type IFieldMiddlewareFunction = (
resolve: Function,
parent: any,
args: any,
context: any,
info: GraphQLResolveInfo,
) => Promise<any>

interface IFieldMiddlewareTypeMap {
[key: string]: IFieldMiddlewareFunction | IFieldMiddlewareFieldMap
}

* Core resolver
interface IFieldMiddlewareFieldMap {
[key: string]: IFieldMiddlewareFunction
}

type IFieldMiddleware = IFieldMiddlewareFunction | IFieldMiddlewareTypeMap

## Middleware Use Cases
function applyFieldMiddleware(
schema: GraphQLSchema,
...middlewares: IFieldMiddleware[]
): GraphQLSchema
```

### Field level
## GraphQL Middleware Use Cases

* Logging
* Metrics
* Input sanitzation
* Performance measurement
* Authorization (`graphql-shield`)
* Authorization
* Caching
* Tracing

### Document level
## FAQ

### Can I use GraphQL-Middleware without GraphQL-Yoga?

Yes. Nevertheless we encourage you to use it in combination with Yoga, because of the many features Yoga offers combined with GraphQL-Middleware.

### How does GraphQL-Middleware compare to `directives`?

GraphQL-Middleware and `directives` tackle the same problem in completely different way. GraphQL-Middleware allows you to implement all your middleware logic in your code, whereas directives encourage you to mix schema with your functionality.

* Complexity analysis
### Should I modify the context using GraphQL-Middleware?

## Open questions
GraphQL-Middleware allows you to modify the context of your resolvers, but we encourage you to use GraphQL-Yoga's document-middleware for this functionality instead.

* [ ] Allow to transform schema?
* [ ] Anything to consider for subscriptions?
## Help & Community [![Slack Status](https://slack.graph.cool/badge.svg)](https://slack.graph.cool)

## Alternatives
Join our [Slack community](http://slack.graph.cool/) if you run into issues or have questions. We love talking to you!

- Directive resolvers
[![](http://i.imgur.com/5RHR6Ku.png)](https://www.graph.cool/)
Binary file added media/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
},
"author": "Matic Zavadlal <[email protected]>",
"dependencies": {
"graphql": "^0.13.0"
"graphql": "^0.13.0",
"graphql-tools": "^2.23.1"
},
"devDependencies": {
"@types/graphql": "^0.12.4",
"ava": "^0.25.0",
"graphql-tools": "^2.21.0",
"oao": "^1.5.1",
"prettier": "^1.11.1",
"prettier-check": "^2.0.0",
"semantic-release": "^12.4.1",
Expand Down
Loading

0 comments on commit efb2da6

Please sign in to comment.