Skip to content

Commit eae1e8a

Browse files
committed
edit/fix broken links
1 parent 741dab5 commit eae1e8a

7 files changed

+406
-98
lines changed

.env

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ POSTGRES_PASSWORD=SAMPLE_PASSWORD
33
POSTGRES_DB=todo_db
44
POSTGRES_PORT=5432
55
POSTGRES_HOST=127.0.0.1
6-
PORT=3333
6+
PORT=4000

.env_example

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
POSTGRES_USER=postgres
2+
POSTGRES_PASSWORD=SAMPLE_PASSWORD
3+
POSTGRES_DB=todo_db
4+
POSTGRES_PORT=5432
5+
POSTGRES_HOST=127.0.0.1
6+
PORT=4000

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
.env

pg-todo-tutorial_section-1.md

+35-37
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Postgres and Graphql: Structure for Everyone
2-
3-
**TL;DR** The structured nature of [Postgres][postgres] (A relational database mangement system) allows [Postgraphile][postgraphile] to generate a wonderful interface to [Graphql][graphql]. [Project Source at Github][source]
4-
5-
[source]:<https://github.com/dkkloimwieder/pg-todo-tutorial>
6-
[postgres]:<https://www.postgresql.org/>
7-
[postgraphile]:<https://www.graphile.org/postgraphile/>
8-
[graphql]:<https://graphql.org/>
2+
3+
**TL;DR** The structured nature of [Postgres][postgres] (A relational database mangement system) allows [Postgraphile][postgraphile] to generate a wonderful interface to [Graphql][graphql]. [Project Source at Github][source]
4+
5+
[source]: https://github.com/dkkloimwieder/pg-todo-tutorial
6+
[postgres]: https://www.postgresql.org/
7+
[postgraphile]: https://www.graphile.org/postgraphile/
8+
[graphql]: https://graphql.org/
99

1010
## Why Postgres and Graphql?
1111

@@ -17,16 +17,16 @@ This project will provide a brief overview of the underlying tools used to conne
1717

1818
This project requires a basic working knowledge of [Git][git], [Node][node], and a local install of [Docker][docker] with [Docker-Compose][docker-compose] for creating an isolated Postgres database. Please refer to the official documentation for installation as it varies by operating system and is outside the scope of this tutorial. If you would prefer to use a local installation of Postgres this tutorial will still apply; skip the the docker-compose configuration and adjust the provided .env as neccesary. The corresponding [repo][source] is divided into branches in case you would like to start with a relatively clean slate or jump ahead.
1919

20-
[git]:<https://git-scm.com/>
21-
[node]:<https://nodejs.org/en/>
22-
[docker]:<https://www.docker.com/>
23-
[docker-compose]:<https://docs.docker.com/compose/>
20+
[git]: https://git-scm.com/
21+
[node]: https://nodejs.org/en/
22+
[docker]: https://www.docker.com/
23+
[docker-compose]: https://docs.docker.com/compose/
2424

2525
## Create a Postgres instance
2626

27-
This section begins with the `section-1` branch and includes a little directory structure, a `.env`, `database.json`, and a `docker-config.yml`. Let's begin: `git checkout section-1`
27+
This section begins with the `section-1` branch and includes a little directory structure, a `.local_env`, `database.json`, and a `docker-config.yml`. Let's begin: `git checkout section-1`
2828

29-
>Note: In the root directory of the project first please have a look at the provided `.env` file. Please note that typically `.env` would ==**never**== be included in a public git repository. Its purpose is to provide a central place for environemtal variables which may or may not be super secret stuff like passwords or connection settings. Please make sure to add `.env` to your local .gitignore before proceeding: ` echo '.env' >> .gitignore `
29+
> Note: In the root directory of the project first please have a look at the provided `.env_example` file. You will want to copy it to your a local `.env`. Its purpose is to provide a central place for environemtal variables which may or may not be super secret stuff like passwords or connection settings. Please make sure to add `.env` to your local .gitignore before proceeding: `echo '.env' >> .gitignore`
3030
3131
Let's take a look at the `.env`. The first three lines will be used by docker-compose to configure the new postgres instance with a required user, password and database name:
3232

@@ -46,18 +46,18 @@ The two additional lines will be used by `db-migrate`, `postgraphile`, and `expr
4646
Next lets take a look at out `todo_db/docker-compose.yml`
4747

4848
```yml
49-
version: "3.8"
50-
services:
51-
postgres:
52-
image: "postgres"
53-
ports:
54-
- "5432:5432"
55-
volumes:
56-
- todovolume:/var/lib/postgresql/data/
57-
env_file:
58-
- ../.env
59-
volumes:
60-
todovolume:
49+
version: '3.8'
50+
services:
51+
postgres:
52+
image: 'postgres'
53+
ports:
54+
- '5432:5432'
55+
volumes:
56+
- todovolume:/var/lib/postgresql/data/
57+
env_file:
58+
- ../.env
59+
volumes:
60+
todovolume:
6161
```
6262
6363
This file is responsible for the configuration of `docker-compose`. It specifies that we will use the official `postgres` docker image. `ports` specifies the exposed external port followed by the internal port postgres is using. Specifying `volumes` allows us to persist out database data. The volume will be created the first time that the container is brought up. `env_file` allows us to centralize(for the most part) our environment details. Refer to the [official][docker-compose] documentation if you would like to know more about the structure and specifics of `docker-compose.yml`.
@@ -86,7 +86,7 @@ yarn global add db-migrate
8686

8787
Why do we need `db-migrate`available globally? It is recommended as the method for install by the official documentation as it is primarily used on the command line. It will find the local install when running globally and in fact use it so there are no worries about project specific versioning.
8888

89-
[db-migrate]:<https://db-migrate.readthedocs.io/en/latest/>
89+
[db-migrate]: https://db-migrate.readthedocs.io/en/latest/
9090

9191
Next lets look at `.db-migraterc`:
9292

@@ -103,11 +103,11 @@ Now lets take a look at `database.json`:
103103
{
104104
"dev": {
105105
"driver": "pg",
106-
"user": {"ENV": "POSTGRES_USER"},
107-
"password": {"ENV": "POSTGRES_PASSWORD"},
108-
"host": {"ENV": "POSTGRES_HOST"},
109-
"database": {"ENV": "POSTGRES_DB"},
110-
"port": {"ENV": "POSTGRES_PORT"}
106+
"user": { "ENV": "POSTGRES_USER" },
107+
"password": { "ENV": "POSTGRES_PASSWORD" },
108+
"host": { "ENV": "POSTGRES_HOST" },
109+
"database": { "ENV": "POSTGRES_DB" },
110+
"port": { "ENV": "POSTGRES_PORT" }
111111
}
112112
}
113113
```
@@ -130,13 +130,13 @@ CREATE SCHEMA IF NOT EXISTS todo_public;
130130

131131
and now a corresponding down migrationg in `##############-create-schema-down.sql`
132132

133-
```SQL
134-
DROP SCHEMA todo_public;
135-
```
133+
```SQL
134+
DROP SCHEMA todo_public;
135+
```
136136

137137
So what's going on here? If you have not seen too much sql and it appears its yelling at you with a harsh tone of capitalization, do not worry, that is just a formality. SQL is case insensitive so often times it increases readability if SQL keywords are capitalized. Feel free to use all lowercase everything if you prefer. Why do we need to migrations? For everything we do to modify the database, we want to be able to easily revert our changes. This practice is somewhat [contested][stackoverflow-migration], although I tend to like it, especially during projects like this which are primarily for experimentation.
138138

139-
[stackoverflow-migration]:<https://nickcraver.com/blog/2016/05/03/stack-overflow-how-we-do-deployment-2016-edition/#database-migrations>
139+
[stackoverflow-migration]: https://nickcraver.com/blog/2016/05/03/stack-overflow-how-we-do-deployment-2016-edition/#database-migrations
140140

141141
Now lets run the first migration: `db-migrate up`
142142

@@ -166,5 +166,3 @@ DROP TABLE todo_public.todo;
166166
The down migrations simply drops the table.
167167

168168
`db-migrate up` and we are off to the next section.
169-
170-

pg-todo-tutorial_section-2.md

+31-26
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
In this section we will get to play with [postgraphile][postgraphile] via CLI and then setup [express.js][express] as a more permanent solution.
44

5-
[postgraphile]: <https://www.graphile.org/postgraphile/>
6-
[express]: <https://expressjs.com/>
5+
[postgraphile]: https://www.graphile.org/postgraphile/
6+
[express]: https://expressjs.com/
77

88
## Section 2, Postgraphile and Friends
99

10-
If you are following along jump to **Start Section 2** below but if you are just now starting the tutorial at branch `section-2` you will want to make sure you have a postgres instance up and running with an appropriately configured `.env`. I have provided defaults that are not at all secure, at the very least a password change might be in order. Make sure to add `.env` to your `.gitignore` and then:
10+
If you are following along jump to **Start Section 2** below but if you are just now starting the tutorial at branch `section-2` you will want to make sure you have a postgres instance up and running with an appropriately configured `.env`. I have provided defaults in `.env_example` that are not at all secure, at the very least a password change might be in order. Make sure to add `.env` to your `.gitignore` and then:
1111

1212
```sh
1313
yarn install && yarn global add db-migrate
@@ -17,7 +17,7 @@ If you are following along jump to **Start Section 2** below but if you are just
1717

1818
---
1919

20-
**Start Section 2**
20+
## Start Section 2
2121

2222
Now lets test the database with `pgcli` or `psql` (You can use any postgres client really)
2323

@@ -28,7 +28,7 @@ pgcli "postgres://postgres:[email protected]/todo_db"
2828
Now at the prompt we will list the contents of our `todo` table on our `todo_public` schema:
2929

3030
```psql
31-
postgres@127:todo_db> \d todo_public.todo
31+
postgres@127:todo_db> \d todo_public.todo
3232
```
3333

3434
This should produce the output:
@@ -51,6 +51,8 @@ postgres@127:todo_db>
5151

5252
If your client cannot connect or you cannot list the table something has gone awry. Try `\dt todo_public.*` to see if any table has been created under the schema `todo_public`. If you cannot connect check that your environmental variables are correct. The connection string is of the form `"postgres://POSTGRES_USER:POSTGRES_PASSWORD@POSTGRES_HOST/POSTGRES_DB"`. I am certain you will have it figured out in no time. If not, open an issue on the [github][source].
5353

54+
[source]: https://github.com/dkkloimwieder/pg-todo-tutorial
55+
5456
Install `postgraphile` and a plugin to simplify naming **globally**. Do not worry we will get rid of our global install when we are don with them. For now it is convenient for command line usage.
5557

5658
`yarn global add postgraphile @graphile-contrib/pg-simplify-inflector`
@@ -83,6 +85,7 @@ Click the "GraphiQL GUI/IDE" link or open localhost:5000/graphiql in your browse
8385
<summary>Here is a screenshot if you would like to compare</summary>
8486
8587
![graphiql in the browser](assets/pg-todo-tutorial_graphiql.png)
88+
8689
</details>
8790
8891
Voila! We have easy access to our `todo` table. The `graphiql` explorer is primarily divided into four panes. The first is populated with queries or mutations depending on which you select that can built. The second is the actual interface to graphql queries. Clicking on items in the first pane will incrementally build queries in the second. The third pane is the output from the queries and the final pane is our documentation that postgraphile automagically generates for us.
@@ -107,9 +110,9 @@ Lets use the first pane to build a query. Select the `todos` dropdown and then c
107110
}
108111
```
109112
110-
>Note: The pg-simplify-inflector simplifies the "inflection" or the method that it uses to create names when analyzing the database. Postgraphile is by default very verbose/explicit with naming as it [leads to less accidental conflicts][inflection]. In out example there is very little difference but try starting postgraphile without it and you will get the general idea of what it does.
113+
> Note: The pg-simplify-inflector simplifies the "inflection" or the method that it uses to create names when analyzing the database. Postgraphile is by default very verbose/explicit with naming as it [leads to less accidental conflicts][inflection]. In out example there is very little difference but try starting postgraphile without it and you will get the general idea of what it does.
111114
112-
[inflections]: <https://www.graphile.org/postgraphile/inflection/>
115+
[inflections]: https://www.graphile.org/postgraphile/inflection/
113116
114117
Before we move on lets explore the documentation and see what postgraphile has generated for us so far.
115118
We are primarily interested in adding a todo at this point, as we have none. Browse `mutations` and then `input:CreateTodoInput`. And then `todo:TodoInput`. Now we know! Although not really. The fields for input are listed but what if our coworker also wanted to explore our newly created API? Maybe we should add some helpful coments in out database that describe the fields that we will be using. Back to the SQL!
@@ -127,14 +130,14 @@ COMMENT ON COLUMN todo_public.todo.completed IS 'status of todo';
127130
and corresponding `migrations/sqls/######-todo-comments-down.sql`
128131
129132
```sql
130-
COMMENT ON TABLE todo_public.todo IS NULL;
133+
COMMENT ON TABLE todo_public.todo IS NULL;
131134
COMMENT ON COLUMN todo_public.todo.id IS NULL;
132-
COMMENT ON COLUMN todo_public.todo.task IS NULL;
135+
COMMENT ON COLUMN todo_public.todo.task IS NULL;
133136
COMMENT ON COLUMN todo_public.todo.created_at IS NULL;
134137
COMMENT ON COLUMN todo_public.todo.completed IS NULL;
135138
```
136139
137-
>Note: COMMENT is postgreql specific
140+
> Note: COMMENT is postgreql specific
138141
139142
`db-migrate up`
140143
@@ -144,7 +147,7 @@ So lets create a todo. If we look in the leftmost panel we see only queries. Go
144147
145148
```gql
146149
mutation {
147-
createTodo(input: {todo: {task: "Finish Section 2"}}) {
150+
createTodo(input: { todo: { task: "Finish Section 2" } }) {
148151
todo {
149152
id
150153
completed
@@ -172,7 +175,7 @@ Ohhhh `NodeId`, where do you come from? Look in the documentation. It will tell
172175
173176
`The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.`
174177
175-
Graphql is gets much of its power and usefulness from the fact that it *normalizes* our data. Each piece of data in graphql gets a unique identifier. The key is a hash of the data and allows us to query our endpoint with laser precision, and then also to cache the query. We will not need the NodeId for quite some time, but it is nice to know we can get a hold of any of our nodes(todos) by NodeId if the need arises (like client side cache manipulation).
178+
Graphql is gets much of its power and usefulness from the fact that it _normalizes_ our data. Each piece of data in graphql gets a unique identifier. The key is a hash of the data and allows us to query our endpoint with laser precision, and then also to cache the query. We will not need the NodeId for quite some time, but it is nice to know we can get a hold of any of our nodes(todos) by NodeId if the need arises (like client side cache manipulation).
176179
177180
Have fun with graphiql for a little while. Make sure that you can fetch all the todos and fields, and perform an update and a deletion. Hint: The explorer (the first panel in graphiql) is your friend. Drop downs follow if you get stuck.
178181
@@ -254,49 +257,53 @@ We will `mkdir server` for our express server to live in and then two files, and
254257
```js
255258
/* server/index.js */
256259
257-
const path = require('path')
258-
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
260+
const path = require('path');
261+
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
259262
const express = require('express');
260263
const postgraphile = require('./postgraphile');
261264
262265
const app = express();
263266
app.use(postgraphile);
264267
265-
app.listen(process.env.PORT)
266-
268+
app.listen(process.env.PORT);
267269
```
268270
269-
Let's also define the `PORT` we will be using to serve content in our `.env`: `echo 'PORT=3333' >> .env`
271+
Let's also define the `PORT` we will be using to serve content in our `.env`: `echo 'PORT=4000' >> .env`
270272
271273
`server/index.js` is pretty straightforward at this point. We need `server/postgraphile.js` to define out postgraphile [middleware][middleware].
272274
273-
[middleware]:<https://www.graphile.org/postgraphile/usage-library/>
275+
[middleware]: https://www.graphile.org/postgraphile/usage-library/
274276
275277
```js
276278
/* server/postgraphile.js */
277279
278280
const { postgraphile } = require('postgraphile');
279281
const PgSimplifyInflectorPlugin = require('@graphile-contrib/pg-simplify-inflector');
280282
281-
const {POSTGRES_DB, POSTGRES_HOST, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_PORT} = process.env
283+
const {
284+
POSTGRES_DB,
285+
POSTGRES_HOST,
286+
POSTGRES_USER,
287+
POSTGRES_PASSWORD,
288+
POSTGRES_PORT,
289+
} = process.env;
282290
283291
module.exports = postgraphile(
284292
{
285293
database: POSTGRES_DB,
286294
host: POSTGRES_HOST,
287295
user: POSTGRES_USER,
288296
password: POSTGRES_PASSWORD,
289-
port: POSTGRES_PORT
297+
port: POSTGRES_PORT,
290298
},
291299
'todo_public',
292300
{
293301
appendPlugins: [PgSimplifyInflectorPlugin],
294302
watchPg: true,
295303
graphiql: true,
296-
enhanceGraphiql: true
304+
enhanceGraphiql: true,
297305
}
298-
)
299-
306+
);
300307
```
301308
302309
This file is also very basic and just assigns all the `.env` variables and CLI options we have already been using.
@@ -315,6 +322,4 @@ Then we just define a `watch` command in `package.json`
315322
}
316323
```
317324
318-
`yarn watch` and browse to `localhost:3333/graphiql` We are now serving our database via node. Oh happy day.
319-
320-
325+
`yarn watch` and browse to `localhost:4000/graphiql` We are now serving our database via node. Oh happy day.

0 commit comments

Comments
 (0)