{"id":16483990,"url":"https://github.com/angad777/graphql-node-typescript-prisma","last_synced_at":"2025-10-27T17:32:07.722Z","repository":{"id":40311825,"uuid":"374100904","full_name":"angad777/graphql-node-typescript-prisma","owner":"angad777","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-14T05:35:28.000Z","size":156,"stargazers_count":2,"open_issues_count":6,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-03-03T05:02:57.648Z","etag":null,"topics":["api","apollo-server","apollographql","graphql","nodejs","orm","orm-framework","prisma","prisma2","sqlite","typescript"],"latest_commit_sha":null,"homepage":"https://dev.to/angad777/create-a-fully-typesafe-graphql-api-with-nodejs-typescript-and-prisma-3c59","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/angad777.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-05T11:50:04.000Z","updated_at":"2021-12-14T14:15:55.000Z","dependencies_parsed_at":"2023-01-28T17:15:31.924Z","dependency_job_id":null,"html_url":"https://github.com/angad777/graphql-node-typescript-prisma","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angad777%2Fgraphql-node-typescript-prisma","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angad777%2Fgraphql-node-typescript-prisma/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angad777%2Fgraphql-node-typescript-prisma/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angad777%2Fgraphql-node-typescript-prisma/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/angad777","download_url":"https://codeload.github.com/angad777/graphql-node-typescript-prisma/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219860766,"owners_count":16556011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","apollo-server","apollographql","graphql","nodejs","orm","orm-framework","prisma","prisma2","sqlite","typescript"],"created_at":"2024-10-11T13:15:36.525Z","updated_at":"2025-10-27T17:32:07.381Z","avatar_url":"https://github.com/angad777.png","language":"TypeScript","readme":"# Create a fully type safe GraphQL API with Nodejs, Typescript and Prisma\n\nPrisma is a modern object relational mapper (ORM) that lets you build new greenfield projects at high speed with few errors, it also has an introspect feature which can be used on existing databases to generate a schema.\nPrisma currently supports PostgreSQL, MySQL and SQLite and our working on NoSQL databases. Prisma is easy to integrate into your framework of choice. Prisma simplifies database access and saves repetitive Create, Read, Update, Delete (CRUD) boilerplate and increases type safety. It's the ideal database toolkit for building robust and scalable web APIs.\n\n## Tech stack\n\n- Node.js ≥ 14.17.0 (LTS)\n- Typescript\n- Apollo Server\n- Prisma\n- GraphQL\n- Node Package Manager\n\n## What are we building ?\n\nFor the purposes of this demo, we'll model a very basic database for a sneaker store and expose some of the data via a graphql api.\n\n## Scaffolding the app\n\n```bash\nmkdir graphql-node-typescript-prisma\nnpm init -y\nnpx tsc --init\n```\n\n### Install dependencies\n\n```bash\nnpm i apollo-server graphql\n```\n\n### Install developer dependencies\n\n```bash\nnpm i ts-node ts-node-dev typescript @types/node prisma -D\n```\n\n### Add scripts\n\nWe'll use ts-node-dev for hot reloading capabilities whilst we develop, you can also choose to use nodemon if thats what you prefer.\n\n```json\n  \"scripts\": {\n    \"compile\": \"tsc\",\n    \"dev\": \"ts-node-dev src/app/main\",\n    \"start\": \"node ./build/app/main.js\"\n  },\n```\n\nYour package.json should now look like this\n\n```json\n{\n  \"name\": \"graphql-node-typescript-prisma\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Create a fully typesafe GraphQL API with Nodejs, Typescript and Prisma\",\n  \"author\": \"Angad Gupta\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"compile\": \"tsc\",\n    \"dev\": \"ts-node-dev src/app/main\",\n    \"start\": \"node ./build/app/main.js\"\n  },\n  \"dependencies\": {\n    \"@prisma/client\": \"^2.23.0\",\n    \"apollo-server\": \"^2.25.0\",\n    \"graphql\": \"^15.5.0\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^15.6.1\",\n    \"prisma\": \"^2.23.0\",\n    \"ts-node\": \"^10.0.0\",\n    \"ts-node-dev\": \"^1.1.6\",\n    \"typescript\": \"^4.3.2\"\n  }\n}\n```\n\n## Basic commands\n\n```json\nnpm run compile  // to compile typescript to javascript\nnpm run dev     // to start the dev server\nnpm run start  // to start the production server that serves the compiled javascript\n```\n\n## Bootstrap an apollo graphql server with\n\nWe'll initialise a new server using ApolloServer and pass our schema and context.\n\n```typescript\nimport { ApolloServer } from 'apollo-server'\nimport { schema } from './graphql/schema'\nimport { context } from './graphql/context'\n\nconst server = new ApolloServer({\n  schema,\n  context,\n})\n\nserver.listen().then(({ url }) =\u003e {\n  console.log(`graphql api running at ${url}graphql`)\n})\n```\n\n## Lets add Prisma\n\nFrom the root directory init prisma\n\n```bash\nnpx prisma init\n```\n\nThis will add a new Prisma folder with some starter files.\n\n## Set database\n\nFor the purposes of this demo we'll be using SQLite as its easier for people to get started, If you're familiar with docker, you can also run a docker container with postgres.\n\n```typescript\ndatasource db {\n  provider = \"sqlite\"\n  url      = \"file:./dev.db\"\n}\n```\n\n## Data modelling in the Prisma schema\n\nCentral to Prisma is the schema - a declarative way to define your app's data models and their relations that's human-readable. And you don't have to painstakingly create it from scratch if you already have a database - prisma introspect takes care of that.\n\nFor our demo we'll use the following Shoe model\n\n```typescript\nmodel Shoe {\n  shoeId     String  @id @default(uuid())\n  name       String\n  price      Int\n  isTrending Boolean\n  isSoldOut  Boolean\n}\n```\n\n## Run migrations\n\nNow that we have a basic model, let's run our initial migration.\n\n```bash\nnpx prisma migrate dev\n```\n\nThe migrations will generate a SQL statement before applying the changes to the database.\n\n```SQL\n-- CreateTable\nCREATE TABLE \"Shoe\" (\n    \"shoeId\" TEXT NOT NULL PRIMARY KEY,\n    \"name\" TEXT NOT NULL,\n    \"price\" INTEGER NOT NULL,\n    \"isTrending\" BOOLEAN NOT NULL,\n    \"isSoldOut\" BOOLEAN NOT NULL\n);\n```\n\n## Context\n\nLets add prisma and the generated prisma client to our graphql context\n\n```bash\n cd src/app/graphql/\n touch context.ts\n```\n\n## Schema first approach\n\nWe'll use the schema first approach and then hook up our graphql resolvers with the generated prisma client for typesafe data querying.\n\n```graphql\ntype Query {\n  getAllShoes: [Shoe!]\n  getShoeById(shoeId: String!): Shoe!\n  getAllTrendingShoes: [Shoe!]\n  getAllSoldOutShoes: [Shoe!]\n}\n\ntype Mutation {\n  createAShoe(name: String!, price: Int!, isTrending: Boolean!, isSoldOut: Boolean!): Shoe!\n  updateAShoe(name: String!, price: Int!, isTrending: Boolean!, isSoldOut: Boolean!): Shoe!\n  deleteAShoe(shoeId: String!): Shoe!\n  markAShoeAsSoldOut(shoeId: String!): Shoe!\n}\n\ntype Shoe {\n  shoeId: String!\n  name: String!\n  price: Int!\n  isTrending: Boolean!\n  isSoldOut: Boolean!\n}\n```\n\n## Resolvers\n\nFor the purposes of this demo, we'll add all our resolvers in a single schema.ts file, however for productions use cases these should be separated to individual node/typescript modules for better testing and maintainability. The resolvers are written using the async/await syntax.\n\n```typescript\nconst resolvers = {\n  Query: {\n    getAllShoes: async (_obj: any, _args: any, context: Context, _info: any) =\u003e {\n      const response = await context.prisma.shoe.findMany()\n\n      return response\n    },\n    getShoeById: async (_obj: any, args: Prisma.ShoeWhereUniqueInput, context: Context, _info: any) =\u003e {\n      const { shoeId } = args\n\n      const response = await context.prisma.shoe.findUnique({\n        where: {\n          shoeId,\n        },\n      })\n\n      return response\n    },\n    getAllTrendingShoes: async (_obj: any, _args: any, context: Context, _info: any) =\u003e {\n      const response = await context.prisma.shoe.findMany({\n        where: {\n          isTrending: true,\n        },\n      })\n\n      return response\n    },\n    getAllSoldOutShoes: async (_obj: any, _args: any, context: Context, _info: any) =\u003e {\n      const response = await context.prisma.shoe.findMany({\n        where: {\n          isSoldOut: true,\n        },\n      })\n\n      return response\n    },\n  },\n  Mutation: {\n    createAShoe: async (_parent: any, args: Prisma.ShoeCreateInput, context: Context, info: any) =\u003e {\n      const { name, price, isTrending, isSoldOut } = args\n\n      const response = await context.prisma.shoe.create({\n        data: {\n          name,\n          price,\n          isTrending,\n          isSoldOut,\n        },\n      })\n\n      return response\n    },\n    updateAShoe: async (_parent: any, args: Prisma.ShoeCreateInput, context: Context, info: any) =\u003e {\n      const { shoeId, name, price, isTrending, isSoldOut } = args\n\n      const response = await context.prisma.shoe.update({\n        where: {\n          shoeId,\n        },\n        data: {\n          name,\n          price,\n          isTrending,\n          isSoldOut,\n        },\n      })\n\n      return response\n    },\n    deleteAShoe: async (_parent: any, args: Prisma.ShoeWhereUniqueInput, context: Context, info: any) =\u003e {\n      const { shoeId } = args\n\n      const response = await context.prisma.shoe.delete({\n        where: {\n          shoeId,\n        },\n      })\n\n      return response\n    },\n    markAShoeAsSoldOut: async (_parent: any, args: Prisma.ShoeWhereUniqueInput, context: Context, info: any) =\u003e {\n      const { shoeId } = args\n\n      const response = await context.prisma.shoe.update({\n        where: {\n          shoeId,\n        },\n        data: {\n          isSoldOut: true, // mark shoe as sold out\n        },\n      })\n\n      return response\n    },\n  },\n}\n```\n\n## Seed\n\nLets seed some data...\n\nThe seed.ts file contains three Shoe records. These records will be added to the database after running the commands\n\nRun the following commands.\n\n```bash\nnpx prisma db seed --preview-feature\n```\n\n```json\nResult:\n{\n  nike: {\n    shoeId: 'abb378df-f975-4b1e-8529-c90597ff477e',\n    name: 'Nike ',\n    price: 140,\n    isTrending: true,\n    isSoldOut: false\n  },\n  addidas: {\n    shoeId: 'fc1a0e73-54cc-41ef-8a65-d5c959d2010c',\n    name: 'Adidas',\n    price: 220,\n    isTrending: false,\n    isSoldOut: false\n  },\n  timberland: {\n    shoeId: '06ea4798-7aec-4920-8079-4ce8797551eb',\n    name: 'Timberland',\n    price: 240,\n    isTrending: false,\n    isSoldOut: true\n  }\n}\n\n🌱  Your database has been seeded.\n```\n\nInitialise a new PrismaClient create an interface for the context and export the context, we'll now use this context in the main.ts file. Context is the third argument in a graphql resolver and we'll be able to use the prisma client to make calls to our database. Just a note, in this example we'll assume that we only have one client.\n\n```typescript\nimport { PrismaClient } from '@prisma/client'\n\nconst prisma = new PrismaClient()\n\nexport interface Context {\n  prisma: PrismaClient\n}\n\nexport const context: Context = {\n  prisma: prisma,\n}\n```\n\n## Start server\n\n```bash\nnpm run dev\n```\n\n```bash\napi ready at http://localhost:4000/graphql\n```\n\n## Lets explore via graphql playground\n\n```bash\nhttp://localhost:4000/graphql\n```\n\n## Available graphql queries\n\n### getAllShoes\n\nReturns a list of all shoes\n\n```gql\nquery getAllShoes {\n  getAllShoes {\n    shoeId\n    name\n    price\n    isTrending\n    isSoldOut\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"getAllShoes\": [\n      {\n        \"shoeId\": \"0080a037-e338-4898-9ab3-5932473ad21a\",\n        \"name\": \"Nike \",\n        \"price\": 140,\n        \"isTrending\": true,\n        \"isSoldOut\": false\n      },\n      {\n        \"shoeId\": \"d4bda185-89d8-4c7c-873a-371388461874\",\n        \"name\": \"Adidas\",\n        \"price\": 160,\n        \"isTrending\": false,\n        \"isSoldOut\": false\n      },\n      {\n        \"shoeId\": \"7e3eff3c-bd63-4b68-b844-5373894603e4\",\n        \"name\": \"Timberland\",\n        \"price\": 240,\n        \"isTrending\": false,\n        \"isSoldOut\": true\n      }\n    ]\n  }\n}\n```\n\n### getShoeById\n\nReturns a shoe by uuid\n\n```gql\nquery getShoeById {\n  getShoeById(shoeId: \"0080a037-e338-4898-9ab3-5932473ad21a\") {\n    shoeId\n    name\n    price\n    isTrending\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"getShoeById\": {\n      \"shoeId\": \"0080a037-e338-4898-9ab3-5932473ad21a\",\n      \"name\": \"Nike \",\n      \"price\": 140,\n      \"isTrending\": true\n    }\n  }\n}\n```\n\n### getAllTrendingShoes\n\nReturns a list of all trending shoes\n\n```gql\nquery getAllTrendingShoes {\n  getAllTrendingShoes {\n    shoeId\n    name\n    price\n    isTrending\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"getAllTrendingShoes\": [\n      {\n        \"shoeId\": \"0080a037-e338-4898-9ab3-5932473ad21a\",\n        \"name\": \"Nike \",\n        \"price\": 140,\n        \"isTrending\": true\n      }\n    ]\n  }\n}\n```\n\n### getAllSoldOutShoes\n\nReturns a list of all sold out shoes\n\n```gql\nquery getAllSoldOutShoes {\n  getAllSoldOutShoes {\n    shoeId\n    name\n    price\n    isTrending\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"getAllSoldOutShoes\": [\n      {\n        \"shoeId\": \"7e3eff3c-bd63-4b68-b844-5373894603e4\",\n        \"name\": \"Timberland\",\n        \"price\": 240,\n        \"isTrending\": false\n      }\n    ]\n  }\n}\n```\n\n## Available graphql mutations\n\n### createAShoe\n\nAdds a new shoe\n\n```gql\nmutation {\n  createAShoe(name: \"yeezys 350\", price: 600, isTrending: true, isSoldOut: false) {\n    shoeId\n    name\n    price\n    isTrending\n    isSoldOut\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"createAShoe\": {\n      \"shoeId\": \"249d54dc-c7fa-48fe-a657-fbf6349fb308\",\n      \"name\": \"yeezys 350\",\n      \"price\": 600,\n      \"isTrending\": false,\n      \"isSoldOut\": false\n    }\n  }\n}\n```\n\n### updateAShoe\n\nUpdates a shoe by using a shoeId.\n\nLets update the shoe added in previous mutation set it as trending by setting isTrending to true.\n\n```gql\nmutation updateAShoe {\n  updateAShoe(shoeId: \"249d54dc-c7fa-48fe-a657-fbf6349fb308\", isTrending: true) {\n    shoeId\n    name\n    price\n    isTrending\n    isSoldOut\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"updateAShoe\": {\n      \"shoeId\": \"249d54dc-c7fa-48fe-a657-fbf6349fb308\",\n      \"name\": \"yeezys 350\",\n      \"price\": 600,\n      \"isTrending\": true,\n      \"isSoldOut\": false\n    }\n  }\n}\n```\n\n### markAShoeAsSoldOut\n\nMarks a shoe as sold out.\n\nLets set the shoe we previously updated to be sold out.\n\n```graphql\nmutation {\n  markAShoeAsSoldOut(shoeId: \"249d54dc-c7fa-48fe-a657-fbf6349fb308\") {\n    shoeId\n    name\n    price\n    isTrending\n    isSoldOut\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"markAShoeAsSoldOut\": {\n      \"shoeId\": \"249d54dc-c7fa-48fe-a657-fbf6349fb308\",\n      \"name\": \"yeezys 350\",\n      \"price\": 600,\n      \"isTrending\": true,\n      \"isSoldOut\": true\n    }\n  }\n}\n```\n\n### deleteAShoe\n\nDelete a shoe by shoeId\n\nLets delete the shoe permanently from the database. Note this is a hard delete, in instances where you would like to only soft delete, you can use the update flow and introduce a new field in the to the model called isDeleted and set that to true.\n\n```graphql\nmutation {\n  deleteAShoe(shoeId: \"249d54dc-c7fa-48fe-a657-fbf6349fb308\") {\n    shoeId\n    name\n    price\n    isTrending\n    isSoldOut\n  }\n}\n```\n\n```json\n{\n  \"data\": {\n    \"deleteAShoe\": {\n      \"shoeId\": \"249d54dc-c7fa-48fe-a657-fbf6349fb308\",\n      \"name\": \"yeezys 350\",\n      \"price\": 600,\n      \"isTrending\": true,\n      \"isSoldOut\": true\n    }\n  }\n}\n```\n\n## Inspecting the database directly\n\nYou can inspect the database directly by running the following\n\n```bash\nnpx prisma studio\n\nEnvironment variables loaded from prisma/.env\nPrisma schema loaded from prisma/schema.prisma\nPrisma Studio is up on http://localhost:5555\n```\n\nThis will instantly open a graphical user interface (gui) on \u003chttp://localhost:5555\u003e very helpful for quickly viewing, adding, editing or adding new records.\n\n## Conclusion\n\nWe learnt how to create a new graphql api and use prisma to query our database in a type safe manner.\nPrisma is a solid ORM with many advantages that are yet to be introduced by others. Use this database toolkit to enhance your productivity and delivery velocity.\n\n## Code\n\nFeel free to extend this tutorial by adding more functionality. This tutorial only lightly touches the capabilities of Prisma. You can clone and fork this repository in its entirety via my GitHub here.\n\n## Learn more about Prisma\n\n\u003chttps://www.prisma.io/\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangad777%2Fgraphql-node-typescript-prisma","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fangad777%2Fgraphql-node-typescript-prisma","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangad777%2Fgraphql-node-typescript-prisma/lists"}