A GraphQL API for a Hacker News clone.
This project was created so I could become more familiar with GraphQL. It was originally based off the code for How to GraphQL's GraphQL.js tutorial, and evolved as follows:
- Integration tests added to facilitate refactoring.
- Conversion to TypeScript.
- Switched to constructing the GraphQL schema with Nexus Schema.
Clone this repository:
$ git clone git@github.com:tanem/hackernews-node.git --depth=1
Install dependencies:
$ cd hackernews-node
$ npm install
This also generates Prisma Client JS into
node_modules/@prisma/client
via apostinstall
hook of the@prisma/client
package.
Start the server:
$ npm run dev
Point a browser at http://localhost:4000 to explore the GraphQL API in a GraphQL Playground. The app uses a SQLite database, ./prisma/dev.db
, which was created and seeded with dummy data as follows:
$ npx cross-env-shell DATABASE_URL=file:./dev.db "npm run migrate && ts-node prisma/seed.ts"
The schema that specifies the API operations of the GraphQL server is defined in ./src/schema.graphql
. Below are a number of operations that you can send to the API using the GraphQL Playground.
Feel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.
Return all links
query {
feed {
count
links {
id
description
url
postedBy {
id
name
}
votes {
id
user {
id
name
}
}
}
}
}
Search for links whose description or url contains a filter string
query {
feed(filter: "graphql") {
count
links {
id
description
url
postedBy {
id
name
}
votes {
id
user {
id
name
}
}
}
}
}
Paginate the links query using offset pagination
📍 The Prisma documentation on offset pagination can be found here.
query {
feed(take: 3, skip: 1) {
count
links {
id
description
url
postedBy {
id
name
}
votes {
id
user {
id
name
}
}
}
}
}
Sort the links query
📍 Links can be sorted by
description
,url
orcreatedAt
.
query {
feed(orderBy: { description: asc }) {
count
links {
id
description
url
postedBy {
id
name
}
votes {
id
user {
id
name
}
}
}
}
}
Register a new user
mutation {
signup(name: "Sarah", email: "sarah@prisma.io", password: "graphql") {
token
}
}
Log in an existing user
mutation {
login(email: "sarah@prisma.io", password: "graphql") {
token
}
}
Post a link
📍 You need to be logged in for this query to work. One way to do this is to retrieve an authentication token via a
signup
orlogin
mutation, and then add it along with theBearer
-prefix to theAuthorization
header in the bottom-left corner of the GraphQL Playground:{ "Authorization": "Bearer __YOUR_TOKEN__" }
mutation {
post(
url: "https://graphql.org/"
description: "GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data."
) {
id
}
}
Vote for a link
📍 You need to be logged in for this query to work. One way to do this is to retrieve an authentication token via a
signup
orlogin
mutation, and then add it along with theBearer
-prefix to theAuthorization
header in the bottom-left corner of the GraphQL Playground:{ "Authorization": "Bearer __YOUR_TOKEN__" }
📍 You need to replace the
__LINK_ID__
-placeholder with an actualLink
id
. You can find one using afeed
-query.
mutation {
vote(linkId: "__LINK_ID__") {
id
}
}
Subscribe to new links
📍 Open two GraphQL Playground tabs, run the subscription in one tab, post a link in the other tab, and view the result in the subscription tab in real-time.
subscription {
newLink {
id
description
url
postedBy {
id
name
}
}
}
Subscribe to new votes
📍 Open two GraphQL Playground tabs, run the subscription in one tab, post a vote in the other tab, and view the result in the subscription tab in real-time.
subscription {
newVote {
id
link {
url
description
}
user {
name
email
}
}
}
Run all tests:
$ npm test
Run in watch mode:
$ npm run test:watch
Run with test coverage information:
$ npm run test:coverage
- prisma-examples for the documentation content and layout.
MIT