{"id":18278043,"url":"https://github.com/tanem/hackernews-node","last_synced_at":"2026-04-29T01:33:35.614Z","repository":{"id":38884617,"uuid":"283911394","full_name":"tanem/hackernews-node","owner":"tanem","description":"📰 A GraphQL API for a Hacker News clone.","archived":false,"fork":false,"pushed_at":"2023-07-07T17:38:12.000Z","size":597,"stargazers_count":2,"open_issues_count":28,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T04:37:55.540Z","etag":null,"topics":["api","api-server","gql","gql-api","graphql","graphql-yoga","hacker-news","howtographql","nexus","prisma"],"latest_commit_sha":null,"homepage":"https://tanem-hackernews-node.herokuapp.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tanem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-31T01:15:47.000Z","updated_at":"2023-07-26T10:09:58.000Z","dependencies_parsed_at":"2023-02-13T19:30:45.061Z","dependency_job_id":null,"html_url":"https://github.com/tanem/hackernews-node","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tanem/hackernews-node","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanem%2Fhackernews-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanem%2Fhackernews-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanem%2Fhackernews-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanem%2Fhackernews-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tanem","download_url":"https://codeload.github.com/tanem/hackernews-node/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanem%2Fhackernews-node/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32407164,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T19:38:08.556Z","status":"ssl_error","status_checked_at":"2026-04-28T19:37:55.688Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-server","gql","gql-api","graphql","graphql-yoga","hacker-news","howtographql","nexus","prisma"],"created_at":"2024-11-05T12:22:44.588Z","updated_at":"2026-04-29T01:33:35.591Z","avatar_url":"https://github.com/tanem.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hackernews-node\n\n[![build status](https://img.shields.io/github/workflow/status/tanem/hackernews-node/CI?style=flat-square)](https://github.com/tanem/hackernews-node/actions?query=workflow%3ACI)\n[![coverage status](https://img.shields.io/codecov/c/github/tanem/hackernews-node.svg?style=flat-square)](https://codecov.io/gh/tanem/hackernews-node)\n\n\u003e A GraphQL API for a Hacker News clone.\n\n## Table of Contents\n\n- [Background](#background)\n- [Getting Started](#getting-started)\n- [Using the GraphQL API](#using-the-graphql-api)\n- [Running Tests](#running-tests)\n- [Credits](#credits)\n- [License](#license)\n\n## Background\n\nThis project was created so I could become more familiar with [GraphQL](https://graphql.org/). It was originally based off [the code](https://github.com/howtographql/graphql-js) for [How to GraphQL](https://www.howtographql.com/)'s [GraphQL.js tutorial](https://www.howtographql.com/graphql-js/0-introduction/), and evolved as follows:\n\n- Integration tests added to facilitate refactoring.\n- Conversion to TypeScript.\n- Switched to constructing the GraphQL schema with [Nexus Schema](https://github.com/graphql-nexus/schema).\n\n## Getting Started\n\nClone this repository:\n\n```\n$ git clone git@github.com:tanem/hackernews-node.git --depth=1\n```\n\nInstall dependencies:\n\n```\n$ cd hackernews-node\n$ npm install\n```\n\n\u003e This also generates Prisma Client JS into `node_modules/@prisma/client` via a `postinstall` hook of the `@prisma/client` package.\n\nStart the server:\n\n```\n$ npm run dev\n```\n\nPoint a browser at [http://localhost:4000](http://localhost:4000) to explore the GraphQL API in a [GraphQL Playground](https://github.com/prisma/graphql-playground). The app uses a SQLite database, [`./prisma/dev.db`](./prisma/dev.db), which was created and seeded with dummy data as follows:\n\n```\n$ npx cross-env-shell DATABASE_URL=file:./dev.db \"npm run migrate \u0026\u0026 ts-node prisma/seed.ts\"\n```\n\n## Using the GraphQL API\n\nThe schema that specifies the API operations of the GraphQL server is defined in [`./src/schema.graphql`](./src/schema.graphql). Below are a number of operations that you can send to the API using the GraphQL Playground.\n\nFeel free to adjust any operation by adding or removing fields. The GraphQL Playground helps you with its auto-completion and query validation features.\n\n\u003cdetails\u003e\n\u003csummary\u003eReturn all links\u003c/summary\u003e\n\u003cp\u003e\n\n```graphql\nquery {\n  feed {\n    count\n    links {\n      id\n      description\n      url\n      postedBy {\n        id\n        name\n      }\n      votes {\n        id\n        user {\n          id\n          name\n        }\n      }\n    }\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSearch for links whose description or url contains a filter string\u003c/summary\u003e\n\u003cp\u003e\n\n```graphql\nquery {\n  feed(filter: \"graphql\") {\n    count\n    links {\n      id\n      description\n      url\n      postedBy {\n        id\n        name\n      }\n      votes {\n        id\n        user {\n          id\n          name\n        }\n      }\n    }\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ePaginate the links query using offset pagination\u003c/summary\u003e\n\u003cp\u003e\n\n\u003e 📍 The Prisma documentation on offset pagination can be found [here](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/pagination#offset-pagination).\n\n```graphql\nquery {\n  feed(take: 3, skip: 1) {\n    count\n    links {\n      id\n      description\n      url\n      postedBy {\n        id\n        name\n      }\n      votes {\n        id\n        user {\n          id\n          name\n        }\n      }\n    }\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSort the links query\u003c/summary\u003e\n\u003cp\u003e\n\n\u003e 📍 Links can be sorted by `description`, `url` or `createdAt`.\n\n```graphql\nquery {\n  feed(orderBy: { description: asc }) {\n    count\n    links {\n      id\n      description\n      url\n      postedBy {\n        id\n        name\n      }\n      votes {\n        id\n        user {\n          id\n          name\n        }\n      }\n    }\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eRegister a new user\u003c/summary\u003e\n\u003cp\u003e\n\n```graphql\nmutation {\n  signup(name: \"Sarah\", email: \"sarah@prisma.io\", password: \"graphql\") {\n    token\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eLog in an existing user\u003c/summary\u003e\n\u003cp\u003e\n\n```graphql\nmutation {\n  login(email: \"sarah@prisma.io\", password: \"graphql\") {\n    token\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ePost a link\u003c/summary\u003e\n\u003cp\u003e\n\n\u003e 📍 You need to be logged in for this query to work. One way to do this is\n\u003e to retrieve an authentication token via a `signup` or `login` mutation, and\n\u003e then add it along with the `Bearer`-prefix to the `Authorization` header in\n\u003e the bottom-left corner of the GraphQL Playground:\n\u003e\n\u003e ```json\n\u003e {\n\u003e   \"Authorization\": \"Bearer __YOUR_TOKEN__\"\n\u003e }\n\u003e ```\n\n```graphql\nmutation {\n  post(\n    url: \"https://graphql.org/\"\n    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.\"\n  ) {\n    id\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eVote for a link\u003c/summary\u003e\n\u003cp\u003e\n\n\u003e 📍 You need to be logged in for this query to work. One way to do this is\n\u003e to retrieve an authentication token via a `signup` or `login` mutation, and\n\u003e then add it along with the `Bearer`-prefix to the `Authorization` header in\n\u003e the bottom-left corner of the GraphQL Playground:\n\u003e\n\u003e ```json\n\u003e {\n\u003e   \"Authorization\": \"Bearer __YOUR_TOKEN__\"\n\u003e }\n\u003e ```\n\n\u003e 📍 You need to replace the `__LINK_ID__`-placeholder with an actual `Link` `id`. You can find one using a `feed`-query.\n\n```graphql\nmutation {\n  vote(linkId: \"__LINK_ID__\") {\n    id\n  }\n}\n```\n\n\u003cp\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSubscribe to new links\u003c/summary\u003e\n\u003cp\u003e\n\n\u003e 📍 Open two GraphQL Playground tabs, run the subscription in one tab, post a\n\u003e link in the other tab, and view the result in the subscription tab in\n\u003e real-time.\n\n```graphql\nsubscription {\n  newLink {\n    id\n    description\n    url\n    postedBy {\n      id\n      name\n    }\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSubscribe to new votes\u003c/summary\u003e\n\u003cp\u003e\n\n\u003e 📍 Open two GraphQL Playground tabs, run the subscription in one tab, post a\n\u003e vote in the other tab, and view the result in the subscription tab in\n\u003e real-time.\n\n```graphql\nsubscription {\n  newVote {\n    id\n    link {\n      url\n      description\n    }\n    user {\n      name\n      email\n    }\n  }\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n## Running Tests\n\nRun all tests:\n\n```\n$ npm test\n```\n\nRun in watch mode:\n\n```\n$ npm run test:watch\n```\n\nRun with test coverage information:\n\n```\n$ npm run test:coverage\n```\n\n## Credits\n\n- [prisma-examples](https://github.com/prisma/prisma-examples) for the documentation content and layout.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanem%2Fhackernews-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftanem%2Fhackernews-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanem%2Fhackernews-node/lists"}