Skip to content

Commit

Permalink
Link chapters to free online book
Browse files Browse the repository at this point in the history
  • Loading branch information
okjulian committed Sep 16, 2022
1 parent 4597712 commit 68460c5
Show file tree
Hide file tree
Showing 7 changed files with 441 additions and 468 deletions.
15 changes: 8 additions & 7 deletions manuscript/chapter-0.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# PREFACE

[https://www.graphqladmin.com/books/fullstack-graphql/00-preface](https://www.graphqladmin.com/books/fullstack-graphql/00-preface)

GraphQL is revolutionizing client-server communication. It is a technology that enables better documented APIs, easier data management in HTTP clients, and optimized network usage.

One of the main benefits of GraphQL is that improves communication between APIs and API consumers. Facilitates team communication by providing an easy way for frontend developers to know all methods that the API exposes. It also enables better communication with 3rd party API consumers because GraphQL services have zero configuration API documentation.
Expand Down Expand Up @@ -46,16 +48,15 @@ Through the course of this book you will learn how to build a Pinterest clone ca

Pinapp should allow users to:

* Login with magic links
* Logout
* Add pins (a pin is an image that links to a URL)
* Search pins and users
* List pins
* See new pins without refreshing browser
- Login with magic links
- Logout
- Add pins (a pin is an image that links to a URL)
- Search pins and users
- List pins
- See new pins without refreshing browser

You will build this application in layers. First you will design the data layer, then write the business logic, after that create HTTP transport layer, then connect everything to the database layer and finally build the HTTP client.

## Development environment

There are no environment requirements to try the examples in this book, other than having a web browser and internet connection. Every step of the application has a live, editable online version hosted at glitch.com. Glitch is an awesome community to build apps created by the folks that developed Stack Overflow and Trello.

79 changes: 35 additions & 44 deletions manuscript/chapter-1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 1. Reading and writing data

[https://www.graphqladmin.com/books/fullstack-graphql/01-reading-and-writing-data](https://www.graphqladmin.com/books/fullstack-graphql/01-reading-and-writing-data)

In this chapter you will learn how to use GraphQL from a frontend developer's perspective. This chapter explains how to use queries and mutations to read and write data from GraphQL.

![Queries and mutations](images/graphql-schema.png)
Expand All @@ -16,19 +18,19 @@ The GraphQL query language defines how to interact with data using GraphQL's que

The rest of this chapter will teach you the following features of GraphQL syntax:

* Basic query
* Query nested fields
* Query multiple fields
* Operation name
* Arguments
* Aliases
* Fragments
* Variables
* Directives
* Default variables
* Mutations
* Inline fragments
* Meta fields
- Basic query
- Query nested fields
- Query multiple fields
- Operation name
- Arguments
- Aliases
- Fragments
- Variables
- Directives
- Default variables
- Mutations
- Inline fragments
- Meta fields

All concepts that you will learn have a runnable example, implemented using [`graphql-js`](https://github.com/graphql/graphql-js). GraphQL JS is the reference implementation of GraphQL, built with Javascript. This library exports a function called `graphql` which lets us send a query to a GraphQL schema.

Expand All @@ -45,7 +47,7 @@ const schema = require("../schema");

const query = ``;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -87,7 +89,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -132,7 +134,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -191,7 +193,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -244,7 +246,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -302,7 +304,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -344,7 +346,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -397,7 +399,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -468,10 +470,8 @@ const query = `
`;

graphql(schema, query, undefined, undefined, {
id: "1"
}).then(result =>
console.log(JSON.stringify(result, null, 1))
);
id: "1",
}).then((result) => console.log(JSON.stringify(result, null, 1)));
```

The result of running `node queries/8-variables.js` is pretty straightforward.
Expand Down Expand Up @@ -514,10 +514,8 @@ const query = `
`;

graphql(schema, query, undefined, undefined, {
withPins: true
}).then(result =>
console.log(JSON.stringify(result, null, 1))
);
withPins: true,
}).then((result) => console.log(JSON.stringify(result, null, 1)));
```

Go ahead and run the previous example with `node queries/9-directives.js`. Change `withPins` to false and see how the result's structure changes.
Expand Down Expand Up @@ -576,7 +574,7 @@ const query = `
}
`;

graphql(schema, query).then(result =>
graphql(schema, query).then((result) =>
console.log(JSON.stringify(result, null, 1))
);
```
Expand Down Expand Up @@ -642,10 +640,8 @@ const query = `
`;

graphql(schema, query, undefined, undefined, {
text: "Hello world"
}).then(result =>
console.log(JSON.stringify(result, null, 1))
);
text: "Hello world",
}).then((result) => console.log(JSON.stringify(result, null, 1)));
```

Run the previous example with `node queries/11-inline-fragments.js`.
Expand Down Expand Up @@ -696,10 +692,8 @@ const query = `
`;

graphql(schema, query, undefined, undefined, {
text: "Hello world"
}).then(result =>
console.log(JSON.stringify(result, null, 1))
);
text: "Hello world",
}).then((result) => console.log(JSON.stringify(result, null, 1)));
```

Run the previous script by entering `node queries/12-meta-fields.js` into the console. You will see that the response contains a `__typename` field in each object.
Expand Down Expand Up @@ -752,11 +746,9 @@ graphql(schema, query, undefined, undefined, {
pin: {
title: "Hello world",
link: "Hello world",
image: "Hello world"
}
}).then(result =>
console.log(JSON.stringify(result, null, 1))
);
image: "Hello world",
},
}).then((result) => console.log(JSON.stringify(result, null, 1)));
```

Run this mutation example by entering `node queries/13-mutations.js` in the console. Remember that our schema works with mocked data, it does not have a real implementation underneath, so don't expect any data changes caused by this mutation.
Expand All @@ -782,4 +774,3 @@ If you query the list of pins after your last mutation, you will notice that thi
GraphQL makes frontend development easier by providing powerful querying capabilities. It makes it easy to fetch for multiple, nested resources in a single query. Fetching the minimal set of fields needed from a resource is also a built-in feature.

In the next chapter, called Data Modeling, you will design from scratch the schema you used in this chapter. As opposed to this chapter's schema, the next one will be backed by an in-memory database, it will not have mocked values.

60 changes: 28 additions & 32 deletions manuscript/chapter-2.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 2. Data modeling

[https://www.graphqladmin.com/books/fullstack-graphql/02-data-modeling](https://www.graphqladmin.com/books/fullstack-graphql/02-data-modeling)

In the previous chapter you learned how to read and write data by sending queries against a schema using the GraphQL query language. In this chapter you will learn how to model the data behind the queries using schemas and types. To create this schema you will use the GraphQL Schema Definition Language (also called SDL, not to be confused with LSD).

Whereas the previous chapter focused on how clients interact with servers using GraphQL, this chapter will tackle how to expose a data model that clients can consume.
Expand All @@ -16,10 +18,10 @@ Because GraphQL is a specification implemented in many languages, it provides it

The schema you will create is more than just an example that illustrates how to write SDL. It is the initial step of building PinApp, the sample application of this book. It allows most of the features in the final app:

* Login with magic links
* Allow authenticated users to add pins
* Search pins and users
* List pins
- Login with magic links
- Allow authenticated users to add pins
- Search pins and users
- List pins

Make your own copy of this example with the following button:

Expand All @@ -46,7 +48,7 @@ const resolvers = require("./resolvers");

const schema = makeExecutableSchema({
typeDefs,
resolvers
resolvers,
});

module.exports = schema;
Expand Down Expand Up @@ -104,11 +106,11 @@ Notice that `addPin` has a `pin` argument of type `PinInput`, and the other two

Scalar types can't have nested fields, they represent the leaves of a schema. These are the built-in scalar types in GraphQL:

* `Int`
* `Float`
* `String`
* `Boolean`
* `ID`
- `Int`
- `Float`
- `String`
- `Boolean`
- `ID`

Some GraphQL implementations allow you to define custom scalar types. This means that you could create custom scalars such as `Date` or `JSON`.

Expand Down Expand Up @@ -241,12 +243,12 @@ const {
createShortLivedToken,
sendShortLivedToken,
createLongLivedToken,
createUser
createUser,
} = require("./business-logic");

const database = {
users: {},
pins: {}
pins: {},
};

const resolvers = {
Expand All @@ -255,29 +257,26 @@ const resolvers = {
users: () => Object.values(database.users),
search: (_, { text }) => {
return [
...Object.values(database.pins).filter(pin =>
...Object.values(database.pins).filter((pin) =>
pin.title.includes(text)
),
...Object.values(database.users).filter(user =>
...Object.values(database.users).filter((user) =>
user.email.includes(text)
)
),
];
}
},
},
Mutation: {
addPin: async (_, { pin }, { user }) => {
const {
user: updatedUser,
pin: createdPin
} = await addPin(user, pin);
const { user: updatedUser, pin: createdPin } = await addPin(user, pin);
database.pins[createdPin.id] = createdPin;
database.users[user.id] = updatedUser;
return createdPin;
},
sendShortLivedToken: (_, { email }) => {
let user;
const userExists = Object.values(database.users).find(
u => u.email === user.email
(u) => u.email === user.email
);
if (userExists) {
user = userExists;
Expand All @@ -290,34 +289,32 @@ const resolvers = {
},
createLongLivedToken: (_, { token }) => {
return createLongLivedToken(token);
}
},
},
Person: {
__resolveType: person => {
__resolveType: (person) => {
if (person.admin) {
return "Admin";
}
return "User";
}
},
},
User: {
pins({ id }) {
return Object.values(database.pins).filter(
pin => pin.user_id === id
);
}
return Object.values(database.pins).filter((pin) => pin.user_id === id);
},
},
SearchResult: {
__resolveType: searchResult => {
__resolveType: (searchResult) => {
if (searchResult.admin) {
return "Admin";
}
if (searchResult.email) {
return "User";
}
return "Pin";
}
}
},
},
};

module.exports = resolvers;
Expand Down Expand Up @@ -355,4 +352,3 @@ Feel free to learn by modifying the different resolver functions and seeing how
You learned how to create GraphQL schemas. You wrote type definitions using SDL, and resolvers using Javascript. The schema you created in this chapter is accessible by scripts using `graphql-js`.

The next chapter will teach you how to create GraphQL HTTP APIs. You will add the different layers that make up a GraphQL server on top of the GraphQL schema from this chapter. This API will have several additional layers, like HTTP, database and authentication.

Loading

0 comments on commit 68460c5

Please sign in to comment.