Skip to content
This repository was archived by the owner on Nov 5, 2024. It is now read-only.

Commit 925572c

Browse files
xavxyzpauldowman
authored andcommitted
⊂(◕‿◕)つ ADVANCED GRAPHQL
1 parent 6a40b58 commit 925572c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+14929
-0
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# editorconfig.org
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
charset = utf-8
9+
insert_final_newline = true

README.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# OK GROW! Training
2+
3+
Welcome to Advanced GraphQL! In order to make the best use of people's time, we ask you to **please take the time to set a few things up before the class. NOTE: If your employer-provided laptop uses a proxy, it may block these services. The best solution is to use a personal laptop which has unrestricted access to the internet. If you are blocked on this, please contact us as soon as possible**.
4+
5+
## For students coming from GraphQL Fundamentals
6+
7+
You will need one more api ([Apollo Engine](https://engine.apollographql.com/)), but you can start with your .env files from the fundamentals class.
8+
9+
You can see that we have also made a few changes to the project:
10+
11+
- The Create React App structure has been "ejected" (we have a webpack config)
12+
- We are therefore able to use .gql files for queries instead of .js
13+
- We have used fragments to standardize query fields between different client GraphQL operations.
14+
- We have split our schema up into multiple files
15+
16+
These changes form a better foundation for advanced GraphQL patterns.
17+
18+
## Setup Success looks like this
19+
20+
You will need to get two servers working, one for the GraphQL API, and one for the React UI.
21+
22+
If the `api` server is running correctly, you will see the following at [localhost:4000](http://localhost:4000):
23+
24+
![A correctly configured API server](screenshots/graphql_playground_screenshot.png)
25+
26+
Detailed instructions can be found [here](#API-server-setup)
27+
28+
If the `ui` server is running correctly, you will see the following at [localhost:3000](http://localhost:3000/). Logging in won't work yet
29+
30+
![A correctly configured client app](screenshots/ui_screenshot.png)
31+
32+
Detailed instructions can be found [here](#UI-server-setup)
33+
34+
## About the Class
35+
36+
### Versioning
37+
38+
We’ll use [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) to complete exercises.
39+
40+
### Code editor
41+
42+
We recommend [VS Code](https://code.visualstudio.com/) with the following packages installed:
43+
44+
- ESLint
45+
- One of:
46+
- GraphQL for VSCode (or)
47+
- GraphQL (newer)
48+
- Prettier - Code formatter
49+
50+
If you prefer to use another editor, please check for corresponding packages.
51+
52+
### Node.js
53+
54+
You’ll need Node.js installed. We recommend the use of [NVM](https://nvm.sh). You can also install it from the [official website](https://nodejs.org). **We’ll use Node 11.** The packages are not guaranteed to work with other releases.
55+
56+
Though Node comes with a package manager called npm, we’ll use [Yarn](https://yarnpkg.com), a modern deterministic packager.
57+
58+
## Prerequisite knowledge
59+
60+
We will explore all of this thoroughly during the course, but if you are not comfortable with the following concepts, these links are worth a look.
61+
62+
### JavaScript basics
63+
64+
We won’t cover basic JS syntax. You should know at least how to write a function. If you don’t, please take this free course on [Codecademy](https://www.codecademy.com).
65+
66+
### ES2015+
67+
68+
Recent tools are making good use of the newest features in ES2015 and even ES2016 and ES2017. The newest JavaScript is a joy to use. If you haven't tried these, we hope you'll enjoy getting to know the new JS: http://es6-features.org/
69+
70+
Used in this class
71+
72+
- modules with import/export
73+
- const and let
74+
- arrow functions
75+
- destructuring, rest and spread operators
76+
- template literals (everywhere, but a special use in GraphQL)
77+
- async/await - APIs and Apollo
78+
- Array.concat()
79+
80+
### React
81+
82+
We will be using [React](https://facebook.github.io/react/) to render client components.
83+
84+
One nice thing about React is that it is close to base JS, so you should be able to follow even if you are new to it. Nevertheless, some understanding of it will be highly useful. We will implement the GraphQL integration with [render props](https://reactjs.org/docs/render-props.html). We'll help you if this is new to you.
85+
86+
### Nice to have - GraphQL culture
87+
88+
Some background on GraphQL: “[So what’s this GraphQL thing I keep hearing about?](https://medium.freecodecamp.com/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf)
89+
90+
We will be using [Apollo](https://www.apollographql.com/docs/) for client and server GraphQL operations. You can get a head start by reviewing the documentation, but we will cover everything you need to know during the class.
91+
92+
## Questions before the course starts
93+
94+
Depending on your current level, you can expect to spend up to several hours on this material. It's worth it, and you will get much more from the class. If anything here is confusing or you want to clarify a fine point, please get in touch. We are happy to answer your questions, before, during, and after the class.
95+
96+
You can email us at [training@okgrow.com](mailto:training@okgrow.com)
97+
98+
## Code Quality
99+
100+
We strive to use best practices in this repo, but we prioritize the learning experience where necessary.
101+
102+
This usually just means a simplified file structure, but this app lacks some safety and security features, so please use your judgment when reusing this code.
103+
104+
If you have any questions or concerns about specific code, please ask us; we love to talk about code quality.
105+
106+
## Detailed setup instructions
107+
108+
You will need to get two servers working, `/api` is the GraphQL API, and `/ui` is the React UI.
109+
110+
### API keys
111+
112+
For your convenience, we will provide Google and Darksky API keys for your use during the training because these both require a credit card to set up. **NOTE: These will be revoked sometime soon after the training, which means the app will stop working correctly until you replace them with your own.** If you prefer you can get your own now instead.
113+
114+
- Google: `AIzaSyA_CSe2Nu2Nry6NinhfMT9OMoBpzz1901Y`
115+
- Dark Sky: `ffa903008f2fec70757cd590c50c3756`
116+
117+
### API server setup
118+
119+
*NOTE for Windows users*: This app starts MongoDB automatically when you run the api server, using the [mongodb-prebuilt](https://www.npmjs.com/package/mongodb-prebuilt) npm package. Currently it seems to be broken on Windows, so you can independently install Mongo and run MongoDB before starting the api server. Then add `MONGO_PORT=` (with the correct port number) to `api/.env`.
120+
121+
```sh
122+
# make a .env file from the example
123+
cp .env.example .env
124+
```
125+
126+
Update the .env file with the correct API keys. **For your convenience, we will provide Google and Darksky API keys for your use during the training – these will be revoked after the training.** If you prefer, you can get your own keys:
127+
128+
- `GOOGLE_API_KEY` – use our temporary one (see above), or [get your own](https://cloud.google.com/maps-platform): click "Get Started" and choose Places to enable an API key with `geocoding`. Google will collect billing information, but we will not incur any costs during this training.
129+
- `DARKSKY_API_KEY` - use our temporary one (see above), or [get your own](https://darksky.net/dev).
130+
- `ENGINE_API_KEY` - you will need to [get your own Apollo Engine key](https://engine.apollographql.com/) (it's free): sign in and then create a new service.
131+
132+
```sh
133+
# install the dependencies
134+
yarn
135+
136+
# run the API server
137+
yarn start
138+
```
139+
140+
#### Reset the database
141+
142+
This is not required for setup, but if you end up with a lot of `place`s while developing or your data gets corrupted, you can reset the db to the default setup with:
143+
144+
```sh
145+
yarn reset-db
146+
```
147+
148+
### UI server setup
149+
150+
> This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
151+
152+
```sh
153+
# make a .env file from the example
154+
cp .env.example .env
155+
```
156+
157+
Update the .env file with your api keys:
158+
159+
- REACT_APP_GOOGLE_API_KEY: use the key you entered in the api folder as GOOGLE_API_KEY
160+
161+
```sh
162+
# install the dependencies
163+
yarn
164+
165+
# run the web server
166+
yarn start
167+
```
168+
169+
## Troubleshooting
170+
171+
If you have issues you can't resolve, please contact us before the class if at all possible. If you resolve your problem, please let us know what you did so we can improve this readme. Here are a some pointers:
172+
173+
- Make sure you are on **Node 11**. Both earlier and later versions may not work as expected.
174+
- MongoDB errors: This app starts MongoDB automatically when you run the api server. If you get MongoDB errors, start by checking your Node version. If it still doesn't work, you can independently install Mongo and run the database with `mongod` before starting the api server. Then add `MONGO_PORT=` (with the correct port number) to `api/.env`.
175+
- external API problems:
176+
- Make sure you set up .env files in both `api/` and `ui/`. You'll need to restart the servers for changes to take effect.
177+
- If Google gives you an authorization error, make sure your Google API key includes `geocoding`, and make a new one if not. They key that we provide should have the correct permissions.
178+
- Make sure your laptop is not blocking outside api calls via a proxy. You may be able to stop the proxy (e.g., in a Vagrant dev setup), but if you can't, you may want to use a personal laptop instead. Contact us if you think this is a blocker for you.

api/.babelrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
presets: ['env'],
3+
plugins: [
4+
'transform-runtime',
5+
'transform-async-generator-functions',
6+
'transform-object-rest-spread',
7+
],
8+
}

api/.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
GOOGLE_API_KEY=
2+
DARKSKY_API_KEY=
3+
ENGINE_API_KEY=

api/.eslintrc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"extends": ["prettier"],
3+
"plugins": ["prettier"],
4+
"rules": {
5+
"prettier/prettier": [
6+
"error",
7+
{
8+
"singleQuote": true,
9+
"trailingComma": "es5",
10+
"printWidth": 80
11+
}
12+
]
13+
}
14+
}

api/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/db
2+
/node_modules
3+
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
8+
.env

api/index.js

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import dotenv from 'dotenv-safe';
2+
import nodemon from 'nodemon';
3+
import fs from 'fs';
4+
import path from 'path';
5+
import mongoPrebuilt from 'mongodb-prebuilt';
6+
import denodeify from 'denodeify';
7+
8+
const dbpath = `${__dirname}/db`;
9+
10+
dotenv.config();
11+
12+
const PORT = 4000;
13+
14+
const {
15+
MONGO_PORT = parseInt(PORT, 10) + 2,
16+
MONGO_URL = `mongodb://localhost:${MONGO_PORT}/database`,
17+
} = process.env;
18+
19+
// Taken from https://github.com/meteor/meteor/blob/debug-circle-timeout-promise-await/tools/utils/mongo-exit-codes.js
20+
const MONGO_CODES = {
21+
0: {
22+
code: 0,
23+
symbol: 'EXIT_CLEAN',
24+
longText: 'MongoDB exited cleanly'
25+
},
26+
1: {
27+
code: 1,
28+
// No symbol in the source. This is in src/mongo/base/initializer.cpp.
29+
symbol: 'global-initialization',
30+
longText: 'MongoDB failed global initialization'
31+
},
32+
2: {
33+
code: 2,
34+
symbol: 'EXIT_BADOPTIONS',
35+
longText:
36+
'MongoDB was started with erroneous or incompatible command line options'
37+
},
38+
3: {
39+
code: 3,
40+
symbol: 'EXIT_REPLICATION_ERROR',
41+
longText:
42+
'There was an inconsistency between hostnames specified\n' +
43+
'on the command line compared with hostnames stored in local.sources'
44+
},
45+
4: {
46+
code: 4,
47+
symbol: 'EXIT_NEED_UPGRADE',
48+
longText: 'MongoDB needs to upgrade to use this database'
49+
},
50+
5: {
51+
code: 5,
52+
symbol: 'EXIT_SHARDING_ERROR',
53+
longText: 'A moveChunk operation failed'
54+
},
55+
12: {
56+
code: 12,
57+
symbol: 'EXIT_KILL',
58+
longText: 'The MongoDB process was killed, on Windows'
59+
},
60+
14: {
61+
code: 14,
62+
symbol: 'EXIT_ABRUPT',
63+
longText: 'Unspecified unrecoverable error. Exit was not clean'
64+
},
65+
20: {
66+
code: 20,
67+
symbol: 'EXIT_NTSERVICE_ERROR',
68+
longText: 'Error managing NT Service on Windows'
69+
},
70+
45: {
71+
code: 45,
72+
symbol: 'EXIT_FS',
73+
longText: 'MongoDB cannot open or obtain a lock on a file'
74+
},
75+
47: {
76+
code: 47,
77+
symbol: 'EXIT_CLOCK_SKEW',
78+
longText: 'MongoDB exited due to excess clock skew'
79+
},
80+
48: {
81+
code: 48,
82+
symbol: 'EXIT_NET_ERROR',
83+
longText:
84+
'MongoDB exited because its port was closed, or was already\n' +
85+
'taken by a previous instance of MongoDB'
86+
},
87+
100: {
88+
code: 100,
89+
symbol: 'EXIT_UNCAUGHT',
90+
longText:
91+
'MongoDB had an unspecified uncaught exception.\n' +
92+
'This can be caused by MongoDB being unable to write to a local database.\n' +
93+
`Check that you have permissions to write to ${dbpath}. MongoDB does\n` +
94+
'not support filesystems like NFS that do not allow file locking.'
95+
}
96+
};
97+
98+
if (!process.env.MONGO_URL && !process.env.MONGO_PORT) {
99+
console.log(
100+
`Creating development MongoDB on mongodb://localhost:${MONGO_PORT}`
101+
);
102+
103+
if (!fs.existsSync(dbpath)) {
104+
fs.mkdirSync(dbpath);
105+
}
106+
107+
// Weirdly, this promise never resolves if Mongo starts.
108+
// However, we'll just go ahead and start the node server anyway,
109+
// and if we see an error, we'll quit
110+
denodeify(mongoPrebuilt.start_server.bind(mongoPrebuilt))({
111+
auto_shutdown: true,
112+
args: {
113+
port: MONGO_PORT,
114+
dbpath
115+
}
116+
}).catch(errorCode => {
117+
const error = MONGO_CODES[errorCode];
118+
console.error(`Failed to start MongoDB server on port ${MONGO_PORT}`);
119+
console.error(
120+
`Error Code ${errorCode}: ${error ? error.longText : 'Unknown'}`
121+
);
122+
process.exit(1);
123+
});
124+
}
125+
126+
nodemon({
127+
script: path.join('src/server', 'index.js'),
128+
ext: 'js graphql',
129+
exec: 'babel-node'
130+
}).on('restart', () => console.log('Restarting server due to file change\n'));
131+
132+
// Ensure stopping our parent process will properly kill nodemon's process
133+
// Ala https://www.exratione.com/2013/05/die-child-process-die/
134+
135+
// SIGTERM AND SIGINT will trigger the exit event.
136+
process.once('SIGTERM', function () {
137+
process.exit(0);
138+
});
139+
process.once('SIGINT', function () {
140+
process.exit(0);
141+
});
142+
// And the exit event shuts down the child.
143+
process.once('exit', function () {
144+
nodemon.emit('SIGINT');
145+
});

0 commit comments

Comments
 (0)