/hackernews-node

📰 A GraphQL API for a Hacker News clone.

Primary LanguageTypeScriptMIT LicenseMIT

hackernews-node

build status coverage status

A GraphQL API for a Hacker News clone.

Table of Contents

Background

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.

Getting Started

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 a postinstall 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"

Using the GraphQL API

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 or createdAt.

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 or login mutation, and then add it along with the Bearer-prefix to the Authorization 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 or login mutation, and then add it along with the Bearer-prefix to the Authorization header in the bottom-left corner of the GraphQL Playground:

{
  "Authorization": "Bearer __YOUR_TOKEN__"
}

📍 You need to replace the __LINK_ID__-placeholder with an actual Link id. You can find one using a feed-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
    }
  }
}

Running Tests

Run all tests:

$ npm test

Run in watch mode:

$ npm run test:watch

Run with test coverage information:

$ npm run test:coverage

Credits

License

MIT