Simplifying database schema management can be a challenging task, especially when dealing with complex data structures.
However, with the help of GraphQL, Apollo, Prisma, and generative types, this process can be made much easier. Prisma is a next-generation ORM that simplifies working with SQL in JavaScript and TypeScript, while Apollo provides a powerful and flexible way to build GraphQL APIs.
By using generative types, developers can create type-safe database access and simplify the management of their database schema. In this article, we will explore how these technologies can be used together to simplify database schema management and improve the efficiency of your development process.
Understanding the Basics π¨
In this section, we will take a closer look at the four tools that we will be using to simplify database schema management: GraphQL, Apollo, Prisma, and Generative Types. We will discuss what each tool does, how they work together, and why they are a good fit for this task. Let's get started!
GraphQL and Apollo π
GraphQL is a query language and server-side runtime that makes it easier for frontend developers to perform data fetching. It is designed to make APIs fast, flexible, and developer-friendly. As an alternative to REST, GraphQL allows us to pull data from multiple data sources from only a single API call. Here are some key features of GraphQL :
- Declarative Query Language : GraphQL is a declarative query language that allows us to specify what data we need and how it should be structured.
- Queries and Mutations : Two ways of interaction with a database using GraphQL are with queries and mutations. Query allows us to get data, while mutation allows us to modify data.
- Non-Language Dependent : Since GraphQL is non-language dependent, it allows different types of projects to have the ability to use it.
Apollo Server is a lightweight and flexible server that makes it easy to build scalable and performant GraphQL APIs. It supports a wide range of data sources, including databases, REST APIs, and other services, making it easy to integrate with existing systems. The Apollo Client makes it easy to query and mutate data, and provides advanced features like caching, optimistic UI, and real-time updates.
Prisma for Database Management π©οΈ
Prisma is an open-source ORM that simplifies and enhances database interactions in software development projects. It provides a modern data access tool that allows developers to write safe and efficient database queries in a way that is easy to understand and manage.
Prisma replaces traditional ORMs and simplifies database workflows by providing a custom and auto-generated client that enables type-safe database access. It also provides a declarative data modeling and migration system that simplifies the process of making changes to the database schema. Prisma is a powerful tool that can be used to build GraphQL, REST, gRPC APIs, and a lot more.
Generating Types in GraphQL π
The power of generative types in GraphQL lies in its ability to provide a strongly-typed system that ensures data consistency and enables efficient development workflows. Here are some key points to understand about the power of generative types in GraphQL :
1. Type Safety βοΈ
GraphQL uses a type system to define the available data for each type and field in a schema. This allows developers to have clear and explicit expectations about the shape and structure of the data they are working with
2. Automatic Type Generation π€
Tools like the GraphQL Code Generator library can automatically generate types based on the GraphQL schema. This saves developers from manually writing and maintaining types, reducing the chances of errors and inconsistencies
3. Efficient Development βοΈ
With generative types, developers can leverage the benefits of static typing, such as autocompletion, type checking, and IDE support. This leads to faster development cycles and fewer runtime errors
4. Schema Consistency π
Generative types ensure that the schema and the corresponding types are always in sync. Any changes made to the schema will automatically trigger updates to the generated types, maintaining consistency throughout the development process.
Step-by-Step Guide to Simplifying Your Database Schema
Using GraphQL, Apollo, Prisma, and Generative Types
This section will walk you through the steps of setting up a GraphQL API with Apollo, Prisma, and Generative Types. By the end of this guide, you will have a simple and easy-to-manage database schema that can be used to power your GraphQL API.
Without further ado, letβs get started ! π
1 : Setting up our new project
Create a new directory for your project and initialize a new npm project.
mkdir graphql-project
cd graphql-project
npm init -y
2 : Install the required packages
Install the necessary packages for our project :
npm install apollo-server graphql dotenv @prisma/client prisma typescript mongodb --save
3 : Set up TypeScript Configurations
Create a tsconfig.json
file in the project's root directory. This code configures TypeScript to use ES2020, CommonJS modules, strict mode, and outputs compiled files to a "dist" folder. :
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true}
}
4 : Set up Apollo Server
Create a new file index.ts
in the project's root directory. This file will serve as the entry point to our application. The code below sets up an Apollo Server with type definitions and resolvers, then starts the server and logs the URL.
// index.ts
import { ApolloServer } from "apollo-server";
import { typeDefs } from "./src/schema";
import { resolvers } from "./src/resolvers";
const server = new ApolloServer({
typeDefs,
resolvers,
});
server.listen().then(({ url }) => {
console.log(`π Server ready at ${url}`);
});
5 : Defining GraphQL Schemas
Create a new directory src
in the project's root directory. Inside the src
directory, create two new files: schema.ts
and resolvers.ts
.
schema.ts
: This code defines a GraphQL schema with a "User" type having fields "id," "name," and "email," and a "users" query.
//schema.ts
import { gql } from "apollo-server";
export const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
}
type Query {
users: [User!]!
}
`;
resolvers.ts
: The code snippet below defines GraphQL resolvers using PrismaClient to fetch "users" data from the database, handling errors and returning results.
// resolvers.ts
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
export const resolvers = {
Query: {
users: async () => {
try {
const users = await prisma.user.findMany();
if (users.length > 0) {
// Data exists in the database
return users;
} else {
// Data is empty in the database
console.log("No data found in the database.");
return [];
}
} catch (error) {
console.error("Error fetching users from the database:", error);
throw new Error("Failed to fetch users from the database.");
}
},
},
};
6 : Prisma Initialization
Initialize Prisma in your project :
# init prisma project with npx
npx prisma init
This command will create a new prisma
folder in your project directory.
7 : Configure Database Connection
In the prisma
folder, you'll find a file called schema.prisma
. Update it to use MongoDB Atlas as the database provider :
// prisma/schema.prisma
datasource db {
provider = "mongodb"
url = env("MONGODB_URI")
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
}
8 : Generate The Prisma Client
Run the following command to generate the Prisma Client :
# generate the client!
npx prisma generate
9 : Store credentials in .env
Create a .env
file in the project's root directory and store your MongoDB Atlas connection string :
MONGODB_URI=mongodb+srv://<USERNAME>:<PASSWORD>@<YOUR_CLUSTER_URL>/<DATABASE_NAME>?retryWrites=true&w=majority
Replace <USERNAME>
, <PASSWORD>
, <YOUR_CLUSTER_URL>
, and <DATABASE_NAME>
with your actual MongoDB Atlas credentials.
10 : Add build script
Open the package.json
file in the project's root directory and add the build
script :
{
"name": "graphql-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "ts-node index.ts",
"build": "tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@prisma/client": "^5.0.0",
"apollo-server": "^3.12.0",
"dotenv": "^16.3.1",
"graphql": "^16.7.1",
"mongodb": "^5.7.0",
"prisma": "^5.0.0",
"typescript": "^5.1.6"
}
}
11 : Build and Run
Build the TypeScript files and start the server :
# build with tsc
npm run build
# run the server
node dist/index.js
If your setup is successful, you should see a webpage similar to the shown below if you click the port shown after running node dist/index.js
12 : Test the GraphQL API
Open your browser and navigate to http://localhost:4000/.
You can now test your GraphQL API using Apollo Server's built-in GraphQL Playground π₯
Youβre seeing the userβs data because I already have that in my database. Youβll get an empty array if youβre querying an empty database.
You can download the project file below :
Conclusion
Combining GraphQL, Apollo, Prisma, and generating TypeScript types can simplify database schema management. This approach can help create an easy-to-manage database schema that powers your GraphQL API.
By using the strongly-typed nature of a GraphQL schema, type generation libraries can automatically generate TypeScript types based on that schema.
You can use these generated types to ensure type safety for the inputs and results of your GraphQL operations. Prisma is an ORM that can be used inside the GraphQL resolvers of your Apollo Server to query your database.