The Future Is Here: Qwik Meets Prisma Innovatively
Ayoub Alouane
Posted on August 17, 2023
If you're coming from PHP, you have Doctrine. From JAVA, you have Hibernate. In Javascript and TypeScript, we have Prisma that allows you to do Object Relational Mapping by providing a type-safe and intuitive query API to work with. The Prisma team, best known for their work on "GraphQL Yoga,” introduced Prisma 1 in 2018, which was a GraphQL data access layer for databases, but in 2019 the team decided to change the vision and deprioritize GraphQL to have a more general solution for databases to cover more use cases. So 2020 was the year of Prisma 2.0. The team announced on different dates of the year the three primary components Prisma Client, Prisma Migrate, and Prisma Studio.
Prisma 2 Components
Prisma Client
Writing SQL queries will not be the case in Prisma 2. Prisma Client provides us with built-in intuitive API calls, which make it simple for developers to manipulate the database and execute complex queries using only pre-defined functions. Prisma Client has multiple features:
- Type-safety: TypeScript is a type-safe programming language that ensures that we are using the data that we should use based on the defined types. Prisma client takes advantage of this because the generated TypeScript types are based on our database schema, so it will help us to catch errors at the compile time.
- Intuitive API: it abstracts complex SQL queries into simple and clear functions, which gives the developer the ability to focus on the logic of his application.
- Performance: Query batching is the key to having a great performance in Prisma Client. This feature enables Prisma to minimize the number of query requests made to the database by grouping queries and sending them as a single batched request to the database. The result of this is reducing the latency.
Prisma Migrate
Prisma Migrate is a special feature of Prisma. Using only files that we call “migration files,” we can implement the process of creating, updating, and managing databases using SQL commands. Prisma Migrate has multiple features:
- Prisma Schema: it's the core of Prisma. It contains the information needed for our Database. It's a file “schema.prisma”, defined using Prisma Schema Language (PSL), used for migration file generation.
- Migration Files: these are the files responsible for keeping the history and the actual state of our Database. Prisma Migrate can detect the changes that we make in our Prisma scheme and generates migration files for that.
- Migrate CLI: it's a command-line interface that helps us to manage our migrations(create new migrations, apply existing ones, and also rollbacking).
- Introspection: it's a feature that allows us to do reverse engineering by generating a Prisma schema file based on an existing database
Prisma Studio
Prisma Studio is a user-friendly Graphical User Interface that allows us to visualize and interact with our database. It supports multiple databases: PostgreSQL, MySQL, SQLite, and SQL Server. Prisma Studio has multiple features:
- Data Management: it allows us to perform queries such (Create, Read, Update, and Delete), so with that, it will be easy to manipulate data using a graphical interface.
- Real-time Data: with Prisma Studio, we can visualize changes in real-time. If a change occurs in the Database, it is automatically displayed on the graphical interface.
- Cross-platform Compatibility: it's is available in multiple OSs Windows, macOS, and Linux, and also it has a web version that we can access via the browser that we use.
Brief Introduction to Qwik
Qwik is a framework created by the creator of Angular, Miško Hevery, with a collaboration of Adam Bradley, who created Ionic, and Manu Almeida, who created Gin Framework.
Qwik, the HTML first framework’s philosophy is clear: make the fastest possible time-to-interactive (to do it faster by doing nothing).
The framework delays the invocation of the javascript as much as possible and invokes it only when it is needed. The focus is on the first load.
If you want to dive deep into Qwik, we already have an article about it:
Qwik – The Post-Modern Framework
Ayoub Alouane for This is Learning ・ Jul 11 '23
Integrate Prisma to Qwik
Prerequisites
To get started with Qwik locally, we need the following:
- Node.js v16.8 or higher
- Your favorite IDE (vscode recommended)
App Creation
Using the Qwik CLI, we will start by starting a new Qwik Project:
Using the Qwik CLI, we will start by starting a new Qwik Project:
npm create qwik@latest
To run the server, we will need the following command:
npm start
On port 5173, we will have our application running. Now we will install Prisma:
npm run qwik add prisma
After installing Prisma, we will have a folder added in the root of our project:
The core file where we will define our scheme is schema.prisma
, in this tutorial, we will define a model named Company and another one named Employee, and we establish between them a relation of one-to-many, so a user can have one company and a company can have multiple employees, here is how we will implement it:
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model Employee {
id Int @id @default(autoincrement())
email String @unique
company Company @relation(fields: [companyId], references: [id])
companyId Int
name String
}
model Company {
id Int @id @default(autoincrement())
website String @unique
name String
descriptions String
employees Employee[]
}
After modifying the file schema.prisma
, we should run this command to update the migration files and create another one:
npx prisma migrate dev
Now we will try to seed some companies in the database. To do that, we will create a file called seed.ts
in Prisma directory:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const companies = [
{
name: "Adservio",
description: "Great Place to Work",
website: "www.adservio.fr",
},
{
name: "Adservio Academy",
description: "Great Place to Learn",
website: "www.adservio-academy.fr",
},
{
name: "Iriguard",
description: "Great Place to be Secure",
website: "www.iriguard.fr",
}
];
async function main() {
for (const company of companies) {
const { name, description, website } = company;
const categoryData = await prisma.company.upsert({
where: { website },
update: {},
create: {
name,
description,
website
},
});
}
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
After that, we should add this line to the package.json
:
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
},
And finally, we should execute this command:
npx prisma migrate reset
If you get this error:
An error occurred while running the seed command:
Error: Command failed with ENOENT: ts-node --compiler-options {"module":"CommonJS"} prisma/seed.ts
spawn ts-node ENOENT
You should install ts-node:
npm install ts-node
After re-executing the command, to show the results, we can execute Prisma Studio with the command:
npx prisma studio
Here are the results:
Now we will create a route that will help us to create users. Here is the code of the index.ts of this route:
import { component$ } from '@builder.io/qwik';
import { routeAction$,routeLoader$, zod$, z, Form } from '@builder.io/qwik-city';
import { PrismaClient } from '@prisma/client';
export const useGetCompanies = routeLoader$(async () => {
const prisma = new PrismaClient();
const companies = await prisma.company.findMany();
return companies;
});
export const useCreateEmployee = routeAction$(
async (data) => {
const prisma = new PrismaClient();
console.log(data);
const employee = await prisma.employee.create({
data
});
return employee;
},
zod$({
name: z.string(),
email: z.string().email(),
companyId: z.string().regex(/^\d+$/).transform(Number)
})
);
export default component$(() => {
const createEmployeeAction = useCreateEmployee();
const companies = useGetCompanies();
return (
<section>
<h1>Create User</h1>
<Form action={createEmployeeAction}>
<label>
Name
<input type="text" name="name" />
</label>
<label>
Email
<input type="email" name="email" />
</label>
<label>
Companies
<select name="companyId" data-choose-theme>
<option value="0">Default</option>
{companies.value.map((company) => (
<option class="text-primary" value={company.id} key={company.id}>{company.name}</option>
))}
</select>
</label>
<button type="submit">Create</button>
</Form>
{createEmployeeAction.value && (
<div>
<h2>Employee created successfully!</h2>
</div>
)}
</section>
);
});
In the creation, we should choose a name, an email, and the company. To get the list of companies, we used routeLoader$
with a findMany()
that will return the list of companies. RouteLoader$
is good for having data rendered in the server and sent it to the client as a serialized HTML.
After that, we use routeAction$
to create a user after submitting the form. It allows us to perform submitting and return from the server a result to the client in order to update our UI.
Here are the results:
And if we click on company:
As we can see, Prisma Studio helps us to visualize all the relations between our tables.
Qwik and Prisma can be integrated easily, and with Qwik, we benefit from using routeLoader$
and routeAction$
, which help us to have a great performance with an exceptional DX because, with these features, we don't have to keep track of which code we will execute in the server or in the client, the framework does that for us.
Posted on August 17, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.