Skip to content

Commit 577a9ad

Browse files
authored
Provide people with tabs so they can use classes as well (#4284)
This provides people with the option to choose between the template approach or the classes approach. This is a proposal to tackle #1368 [Preview](https://graphql-7w0ort26u-the-graph-ql-foundation.vercel.app/) This has been applied throughout the codebase now, however one of the things I am uncertain about is how we offer `buildSchema` with the GraphQLDefer/... directives? Should we add an option to `buildSchema`? The exports defined in that chapter seem to only exist in v17 so we should explicitly flag that.
1 parent e9b6b62 commit 577a9ad

9 files changed

+818
-85
lines changed

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
/denoDist
88
/websiteDist
99
/website/out
10+
/website/**/*.mdx
1011
.next

website/pages/authentication-and-express-middleware.mdx

+54-6
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,67 @@ title: Authentication and Express Middleware
33
sidebarTitle: Authentication & Middleware
44
---
55

6+
import { Tabs } from 'nextra/components';
7+
68
It's simple to use any Express middleware in conjunction with `graphql-http`. In particular, this is a great pattern for handling authentication.
79

810
To use middleware with a GraphQL resolver, just use the middleware like you would with a normal Express app. The `request` object is then available as the second argument in any resolver.
911

1012
For example, let's say we wanted our server to log the IP address of every request, and we also want to write an API that returns the IP address of the caller. We can do the former with middleware, and the latter by accessing the `request` object in a resolver. Here's server code that implements this:
1113

14+
<Tabs items={['SDL', 'Code']}>
15+
<Tabs.Tab>
1216
```js
1317
const express = require('express');
1418
const { createHandler } = require('graphql-http/lib/use/express');
1519
const { buildSchema } = require('graphql');
1620

17-
const schema = buildSchema(`
18-
type Query {
19-
ip: String
20-
}
21-
`);
21+
const schema = buildSchema(`type Query { ip: String }`);
22+
23+
function loggingMiddleware(req, res, next) {
24+
console.log('ip:', req.ip);
25+
next();
26+
}
27+
28+
const root = {
29+
ip(args, context) {
30+
return context.ip;
31+
},
32+
};
33+
34+
const app = express();
35+
app.use(loggingMiddleware);
36+
app.all(
37+
'/graphql',
38+
createHandler({
39+
schema: schema,
40+
rootValue: root,
41+
context: (req) => ({
42+
ip: req.raw.ip,
43+
}),
44+
}),
45+
);
46+
app.listen(4000);
47+
console.log('Running a GraphQL API server at localhost:4000/graphql');
48+
49+
````
50+
</Tabs.Tab>
51+
<Tabs.Tab>
52+
```js
53+
const express = require('express');
54+
const { createHandler } = require('graphql-http/lib/use/express');
55+
const {
56+
GraphQLObjectType,
57+
GraphQLSchema,
58+
GraphQLString,
59+
} = require('graphql');
60+
61+
const schema = new GraphQLSchema({
62+
query: new GraphQLObjectType({
63+
name: 'Query',
64+
fields: { ip: { type: GraphQLString } },
65+
}),
66+
});
2267
2368
function loggingMiddleware(req, res, next) {
2469
console.log('ip:', req.ip);
@@ -45,7 +90,10 @@ app.all(
4590
);
4691
app.listen(4000);
4792
console.log('Running a GraphQL API server at localhost:4000/graphql');
48-
```
93+
````
94+
95+
</Tabs.Tab>
96+
</Tabs>
4997
5098
In a REST API, authentication is often handled with a header, that contains an auth token which proves what user is making this request. Express middleware processes these headers and puts authentication data on the Express `request` object. Some middleware modules that handle authentication like this are [Passport](http://passportjs.org/), [express-jwt](https://github.com/auth0/express-jwt), and [express-session](https://github.com/expressjs/session). Each of these modules works with `graphql-http`.
5199

website/pages/basic-types.mdx

+60-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
title: Basic Types
33
---
44

5+
import { Tabs } from 'nextra/components';
6+
57
In most situations, all you need to do is to specify the types for your API using the GraphQL schema language, taken as an argument to the `buildSchema` function.
68

79
The GraphQL schema language supports the scalar types of `String`, `Int`, `Float`, `Boolean`, and `ID`, so you can use these directly in the schema you pass to `buildSchema`.
@@ -12,6 +14,8 @@ To use a list type, surround the type in square brackets, so `[Int]` is a list o
1214

1315
Each of these types maps straightforwardly to JavaScript, so you can just return plain old JavaScript objects in APIs that return these types. Here's an example that shows how to use some of these basic types:
1416

17+
<Tabs items={['SDL', 'Code']}>
18+
<Tabs.Tab>
1519
```js
1620
const express = require('express');
1721
const { createHandler } = require('graphql-http/lib/use/express');
@@ -26,6 +30,56 @@ const schema = buildSchema(`
2630
}
2731
`);
2832

33+
// The root provides a resolver function for each API endpoint
34+
const root = {
35+
quoteOfTheDay() {
36+
return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within';
37+
},
38+
random() {
39+
return Math.random();
40+
},
41+
rollThreeDice() {
42+
return [1, 2, 3].map((\_) => 1 + Math.floor(Math.random() \* 6));
43+
},
44+
};
45+
46+
const app = express();
47+
app.all(
48+
'/graphql',
49+
createHandler({
50+
schema: schema,
51+
rootValue: root,
52+
}),
53+
);
54+
app.listen(4000);
55+
console.log('Running a GraphQL API server at localhost:4000/graphql');
56+
57+
````
58+
</Tabs.Tab>
59+
<Tabs.Tab>
60+
```js
61+
const express = require('express');
62+
const { createHandler } = require('graphql-http/lib/use/express');
63+
const {
64+
GraphQLObjectType,
65+
GraphQLSchema,
66+
GraphQLString,
67+
GraphQLFloat,
68+
GraphQLList,
69+
} = require('graphql');
70+
71+
// Construct a schema
72+
const schema = new GraphQLSchema({
73+
query: new GraphQLObjectType({
74+
name: 'Query',
75+
fields: {
76+
quoteOfTheDay: { type: GraphQLString },
77+
random: { type: GraphQLFloat },
78+
rollThreeDice: { type: new GraphQLList(GraphQLFloat) },
79+
},
80+
}),
81+
});
82+
2983
// The root provides a resolver function for each API endpoint
3084
const root = {
3185
quoteOfTheDay() {
@@ -40,16 +94,21 @@ const root = {
4094
};
4195
4296
const app = express();
97+
4398
app.all(
4499
'/graphql',
45100
createHandler({
46101
schema: schema,
47102
rootValue: root,
48103
}),
49104
);
105+
50106
app.listen(4000);
51107
console.log('Running a GraphQL API server at localhost:4000/graphql');
52-
```
108+
````
109+
110+
</Tabs.Tab>
111+
</Tabs>
53112
54113
If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs.
55114

website/pages/constructing-types.mdx

+21-14
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,30 @@
22
title: Constructing Types
33
---
44

5+
import { Tabs } from 'nextra/components';
6+
57
For many apps, you can define a fixed schema when the application starts, and define it using GraphQL schema language. In some cases, it's useful to construct a schema programmatically. You can do this using the `GraphQLSchema` constructor.
68

79
When you are using the `GraphQLSchema` constructor to create a schema, instead of defining `Query` and `Mutation` types solely using schema language, you create them as separate object types.
810

911
For example, let's say we are building a simple API that lets you fetch user data for a few hardcoded users based on an id. Using `buildSchema` we could write a server with:
1012

13+
<Tabs items={['SDL', 'Code']}>
14+
<Tabs.Tab>
1115
```js
1216
const express = require('express');
1317
const { createHandler } = require('graphql-http/lib/use/express');
1418
const { buildSchema } = require('graphql');
1519

1620
const schema = buildSchema(`
17-
type User {
18-
id: String
19-
name: String
20-
}
21-
22-
type Query {
23-
user(id: String): User
24-
}
21+
type User {
22+
id: String
23+
name: String
24+
}
25+
26+
type Query {
27+
user(id: String): User
28+
}
2529
`);
2630

2731
// Maps id to User object
@@ -52,10 +56,10 @@ app.all(
5256
);
5357
app.listen(4000);
5458
console.log('Running a GraphQL API server at localhost:4000/graphql');
55-
```
56-
57-
We can implement this same API without using GraphQL schema language:
5859

60+
````
61+
</Tabs.Tab>
62+
<Tabs.Tab>
5963
```js
6064
const express = require('express');
6165
const { createHandler } = require('graphql-http/lib/use/express');
@@ -110,8 +114,11 @@ app.all(
110114
);
111115
app.listen(4000);
112116
console.log('Running a GraphQL API server at localhost:4000/graphql');
113-
```
117+
````
118+
119+
</Tabs.Tab>
120+
</Tabs>
114121
115-
When we use this method of creating the API, the root level resolvers are implemented on the `Query` and `Mutation` types rather than on a `root` object.
122+
When we use the `GraphQLSchema` constructor method of creating the API, the root level resolvers are implemented on the `Query` and `Mutation` types rather than on a `root` object.
116123
117-
This is particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema. You might have a common format for something like creating and updating database records. This is also useful for implementing features like union types which don't map cleanly to ES6 classes and schema language.
124+
This can be particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema. You might have a common format for something like creating and updating database records. This is also useful for implementing features like union types which don't map cleanly to ES6 classes and schema language.

website/pages/getting-started.mdx

+45-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ title: Getting Started With GraphQL.js
33
sidebarTitle: Getting Started
44
---
55

6+
import { Tabs } from 'nextra/components';
7+
68
{/* title can be removed in Nextra 4, since sidebar title will take from first h1 */}
79

810
# Getting Started With GraphQL.js
@@ -19,7 +21,7 @@ and arrow functions, so if you aren't familiar with them you might want to read
1921
2022
To create a new project and install GraphQL.js in your current directory:
2123

22-
```bash
24+
```sh npm2yarn
2325
npm init
2426
npm install graphql --save
2527
```
@@ -28,18 +30,49 @@ npm install graphql --save
2830

2931
To handle GraphQL queries, we need a schema that defines the `Query` type, and we need an API root with a function called a “resolver” for each API endpoint. For an API that just returns “Hello world!”, we can put this code in a file named `server.js`:
3032

33+
<Tabs items={['SDL', 'Code']}>
34+
<Tabs.Tab>
3135
```javascript
32-
let { graphql, buildSchema } = require('graphql');
36+
const { graphql, buildSchema } = require('graphql');
3337

3438
// Construct a schema, using GraphQL schema language
35-
let schema = buildSchema(`
36-
type Query {
37-
hello: String
38-
}
39-
`);
39+
const schema = buildSchema(`type Query { hello: String } `);
40+
41+
// The rootValue provides a resolver function for each API endpoint
42+
const rootValue = {
43+
hello() {
44+
return 'Hello world!';
45+
},
46+
};
47+
48+
// Run the GraphQL query '{ hello }' and print out the response
49+
graphql({
50+
schema,
51+
source: '{ hello }',
52+
rootValue,
53+
}).then((response) => {
54+
console.log(response);
55+
});
56+
});
57+
58+
````
59+
</Tabs.Tab>
60+
<Tabs.Tab>
61+
```javascript
62+
const { graphql, GraphQLSchema, GraphQLObjectType } = require('graphql');
63+
64+
// Construct a schema
65+
const schema = new GraphQLSchema({
66+
query: new GraphQLObjectType({
67+
name: 'Query',
68+
fields: {
69+
hello: { type: GraphQLString },
70+
},
71+
}),
72+
});
4073
4174
// The rootValue provides a resolver function for each API endpoint
42-
let rootValue = {
75+
const rootValue = {
4376
hello() {
4477
return 'Hello world!';
4578
},
@@ -53,7 +86,10 @@ graphql({
5386
}).then((response) => {
5487
console.log(response);
5588
});
56-
```
89+
````
90+
91+
</Tabs.Tab>
92+
</Tabs>
5793
5894
If you run this with:
5995

0 commit comments

Comments
 (0)