Skip to content

Commit f30d39b

Browse files
authored
feat: Allow to provide FieldConfig via function (#3)
* feat: Allow to provide FieldConfig via function * docs: add links to live demo and it's repo * docs: Adjust examples * docs: fix demo repo link * docs: reorganize `README.md` Add schema building and custom fetching example. Generalize examples. * docs: small readme fixes
1 parent 1d344ec commit f30d39b

File tree

14 files changed

+250
-591
lines changed

14 files changed

+250
-591
lines changed

README.md

Lines changed: 104 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,34 @@
77
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
88
[![Greenkeeper badge](https://badges.greenkeeper.io/graphql-compose/graphql-compose-rest.svg)](https://greenkeeper.io/)
99

10-
This is a plugin for [graphql-compose](https://github.com/nodkz/graphql-compose), which derives GraphQLType from REST response. Also derives bunch of internal GraphQL Types.
10+
This is a plugin for [graphql-compose](https://github.com/nodkz/graphql-compose), which generates GraphQLTypes from REST response or any JSON. It takes fields from object, determines their types and construct GraphQLObjectType with same shape.
1111

12-
## Getting started
12+
## Demo
1313

14-
### Demo
14+
We have a [Live demo](https://graphql-compose-swapi.herokuapp.com/?query=%7B%0A%20%20person%28id%3A%201%29%20%7B%0A%20%20%20%20name%0A%20%20%20%20films%20%7B%0A%20%20%20%20%20%20title%0A%20%20%20%20%20%20release_date%0A%20%20%20%20%20%20director%0A%20%20%20%20%7D%0A%20%20%20%20homeworld%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20climate%0A%20%20%20%20%20%20diameter%0A%20%20%20%20%7D%0A%20%20%20%20starships%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20cost_in_credits%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A) (source code [repo](https://github.com/lyskos97/graphql-compose-swapi)) which shows how to build an API upon [SWAPI](https://swapi.co) using `graphql-compose-rest`.
1515

16-
We have a [demo app](demo/) which shows how to build an API upon [SWAPI](https://swapi.co) using `graphql-compose-rest`.
16+
## Installation
1717

18-
You can run it using:
19-
20-
```js
21-
npm run demo
22-
```
23-
24-
### Installation
25-
26-
```
18+
```bash
2719
npm install graphql graphql-compose graphql-compose-rest --save
2820
```
2921

3022
Modules `graphql`, `graphql-compose`, are located in `peerDependencies`, so they should be installed explicitly in your app. They have global objects and should not have ability to be installed as submodule.
3123

32-
### Examples
24+
## Example
3325

34-
We have a sample response object:
26+
You have a sample response object `restApiResponse` which you can pass to `graphql-compose-rest` along with desired type name as your first argument and it will automatically generate a composed GraphQL type `PersonTC`.
3527

3628
```js
37-
const responseFromRestApi = {
29+
// person.js
30+
31+
import composeWithRest from 'graphql-compose-rest';
32+
33+
const restApiResponse = {
3834
name: 'Anakin Skywalker',
3935
birth_year: '41.9BBY',
4036
gender: 'male',
37+
mass: 77,
4138
homeworld: 'https://swapi.co/api/planets/1/',
4239
films: [
4340
'https://swapi.co/api/films/5/',
@@ -51,43 +48,122 @@ const responseFromRestApi = {
5148
'https://swapi.co/api/starships/39/',
5249
],
5350
};
51+
52+
export const PersonTC = composeWithRest('Person', responseFromRestApi);
53+
export const PersonGraphQLType = PersonTC.getType();
5454
```
5555

56-
which we pass to a `composeWithRest` function of `graphql-compose-rest` along with desired type name as first argument in order to generate a `GraphQL` type:
56+
## Customization
57+
58+
You can write custom field configs directly to a field of your API response object via function (see `mass` and `starships_count` field):
5759

5860
```js
59-
const PersonTC = composeWithRest('Person', responseFromRestApi);
61+
const restApiResponse = {
62+
name: 'Anakin Skywalker',
63+
birth_year: '41.9BBY',
64+
starships: [
65+
'https://swapi.co/api/starships/59/',
66+
'https://swapi.co/api/starships/65/',
67+
'https://swapi.co/api/starships/39/',
68+
],
69+
mass: () => 'Int', // by default numbers coerced to Float, here we set up Int
70+
starships_count: () => ({ // more granular field config with resolve function
71+
type: 'Int',
72+
resolve: source => source.starships.length,
73+
}),
74+
};
6075
```
6176

62-
and successfully export for furher usage:
77+
## Schema building
78+
79+
Now when you have your type built, you may specify the schema and data fetching method:
6380

6481
```js
65-
export PersonTC;
82+
// schema.js
83+
import { GraphQLSchema, GraphQLObjectType, GraphQLNonNull, GraphQLInt } from 'graphql';
84+
import fetch from 'node-fetch';
85+
import { PersonTC } from './person';
86+
87+
const schema = new GraphQLSchema({
88+
query: new GraphQLObjectType({
89+
name: 'Query',
90+
fields: {
91+
person: {
92+
type: PersonTC.getType(), // get GraphQL type from PersonTC
93+
args: {
94+
id: new GraphQLNonNull(GraphQLInt),
95+
},
96+
resolve: (_, args) =>
97+
fetch(`https://swapi.co/api/people/${args.id}/`).then(r => r.json()),
98+
},
99+
},
100+
}),
101+
});
66102
```
103+
Or do the same via `graphql-compose`:
104+
```js
105+
import { GQC } from 'graphql-compose';
106+
107+
GQC.rootQuery().addFields({
108+
person: {
109+
type: PersonTC,
110+
args: {
111+
id: `Int!`, // equals to `new GraphQLNonNull(GraphQLInt)`
112+
},
113+
resolve: (_, args) =>
114+
fetch(`https://swapi.co/api/people/${args.id}/`).then(r => r.json()),
115+
},
116+
}
117+
118+
const schema = GQC.buildSchema(); // returns GraphQLSchema
119+
```
120+
121+
## Further customization with `graphql-compose`
122+
123+
Moreover, `graphql-compose` allows you to pass pre-defined resolvers of other types to the response object and customize them:
124+
125+
```js
126+
const restApiResponse = {
127+
name: 'Anakin Skywalker',
128+
starships: () =>
129+
PeopleTC.getResolver('findByUrlList') // get some standard resolver
130+
.wrapResolve(next => rp => { // wrap with additional logic
131+
const starshipsUrls = rp.source.starships;
132+
rp.args.urls = starshipsUrls; // populate `urls` arg from source
133+
return next(rp); // call standard resolver
134+
})
135+
.removeArg('urls'), // remove `urls` args from resolver and schema
136+
};
137+
}
138+
139+
const PersonTC = composeWithRest('Person', responseFromRestApi);
140+
```
141+
142+
In case you need to separate custom field definition from your response object there are `graphql-compose` methods made for this purpose.
67143
68-
If you want to specify new fields for your type, just use the `addField` function of `TypeComposer` type of `graphql-compose`:
144+
If you want to specify new fields of your type, simply use the `addFields` method of `graphql-compose`:
69145
70146
```js
71147
PersonTC.addFields({
72-
weapon: { // standard GraphQL like field definition
73-
type: GraphQLString,
74-
resolve: (source) => source.name.toUpperCase(),
148+
vehicles_count: {
149+
type: 'Int!', // equals to `new GraphQLNonNull(GraphQLInt)`
150+
resolve: (source) => source.vehicles.length,
75151
},
76152
});
77153
```
78154
79-
In case you want to create a relation with another type simply use `addRelation` function of `TypeComposer`:
155+
When you want to create a relation with another type simply use `addRelation` method of `graphql-compose`:
80156
81157
```js
82-
PersonTC.addRelation('filmObjects', { // uses shortened syntax
158+
PersonTC.addRelation('filmObjects', {
83159
resolver: () => FilmTC.getResolver('findByUrlList'),
84-
prepareArgs: { // you're free to define `resolve` the way you want
160+
prepareArgs: {
85161
urls: source => source.films,
86162
},
87163
});
88164
```
89165
90-
`graphql-compose` provides a vast variety of methods for types' `fields` and `resolvers` (aka `field configs` in vanilla `GraphQL`) management. To learn more visit [graphql-compose repo](https://github.com/nodkz/graphql-compose).
166+
`graphql-compose` provides a vast variety of methods for `fields` and `resolvers` (aka field configs in vanilla `GraphQL`) management of `GraphQL` types. To learn more visit [graphql-compose repo](https://github.com/nodkz/graphql-compose).
91167
92168
## License
93169

demo/index.js

Lines changed: 0 additions & 22 deletions
This file was deleted.

demo/schema/Film.js

Lines changed: 0 additions & 117 deletions
This file was deleted.

0 commit comments

Comments
 (0)