Gel Data
GelDB Gel is a scalable, integrated data platform on top of Postgres.
Gel gives the relational model a fresh facelift, solves n+1, simplifies migrations, and streamlines your entire database workflow.
Gel can be used in Qwik with routeLoader$, routeAction$ and server$ functions. These are Qwik APIs to allow code to execute only on the server-side.
The simplest way to add Gel to your Qwik project is by running the Qwik CLI command. This will automatically install all necessary dependencies, set up a basic schema in the dbschema folder, and generate a queries directory to help you start building your own API queries. Additionally, it will scaffold an actions folder with example routes and files, giving you a ready-to-use foundation for working with Gel in your app.
It will also create a gel.toml file to configure the gel instance. Everything you need to start building your app with Gel is there.
pnpm run qwik add gelnpm run qwik add gelyarn run qwik add gelbun run qwik add gelGel is a modern data platform built on PostgreSQL that provides a unified interface for managing, querying, and scaling your data. It offers features like real-time analytics, seamless migrations, and integrated workflows to simplify database operations for developers and teams.
Auto-generating queries
Gel lets you automatically generate queries for your database schema by using their query language EdgeQL. It is already installed for you and you can use the following scripts to utilize it:
*** Before you start, make sure you have run the following command:
pnpm gel:generate:queries &&
pnpm gel:generate:types
The following <generator>s are currently supported:
- Command:
gel:generate:queries>queries: Generate typed functions from *.edgeql files
- Command:
gel:generate:types>interfaces: Generate interfaces for your schema typesedgeql-js: Generate the query builder
Gel UI
You can also use the Gel UI to view and edit your database schema, query your data, among other things. To do so, run the following command:
pnpm gel:uinpm gel:uiyarn gel:uibun gel:uiClient user actions
We will use these client actions to query and insert users in the DB below.
import { server$ } from "@builder.io/qwik-city";
import { executeQuery } from "../../actions/client";
import * as queries from "../../../dbschema/queries";
export const getAllUsers = server$(async () => {
return await executeQuery(queries.getAllUsers);
});
export const insertUser = server$(
async (name: string, email: string, has_profile: boolean) => {
return await executeQuery(queries.insertUser, {
name: name,
email: email,
has_profile: has_profile,
});
},
);
Listing users
We will use routeLoader$ to query all users in the DB, and return the result.
import { component$ } from "@builder.io/qwik";
import { routeLoader$ } from "@builder.io/qwik-city";
import { getAllUsers } from "../../actions/user";
export const useGetAllUsers = routeLoader$(async () => {
const users = await getAllUsers();
return users;
});
export default component$(() => {
const users = useGetAllUsers().value;
return (
<section>
<h1>Users Directory</h1>
<ul>
{Array.isArray(users) && users.length > 0 ? (
users.map((user: any) => (
<li key={user.id ?? user.name}>
<b>Name:</b> {user.name}
{user.email && (
<div style={{ marginLeft: "1rem" }}>
<span>
<b>Email:</b> {user.email}
</span>
</div>
)}
</li>
))
) : (
<li>No users found.</li>
)}
</ul>
</section>
);
});
Adding users
We will use routeAction$ and zod$ form to create user.
import { component$ } from "@builder.io/qwik";
import { routeAction$, zod$, z, Form } from "@builder.io/qwik-city";
import { insertUser } from "../../actions/user";
export const useCreateUser = routeAction$(
async ({ name, email }) => {
const user = await insertUser(name, email, true);
if (!user)
return { error: "A user already exists with that email.", user: null };
return { error: null, user };
},
zod$({
name: z.string().min(1, { message: "Name is required" }),
email: z.string().email({ message: "Invalid email address" }),
}),
);
export default component$(() => {
const action = useCreateUser();
const errors = action.value?.fieldErrors;
const customError = action.value?.error;
return (
<section>
<h1>Create User</h1>
<Form action={action}>
<label>
Name
<input name="name" value={action.formData?.get("name") ?? ""} />
</label>
<label>
Email
<input name="email" value={action.formData?.get("email") ?? ""} />
</label>
<button type="submit">Create</button>
</Form>
{action.value?.user && <h2>User created successfully!</h2>}
{(errors || customError) && (
<div style={{ color: "red" }}>
{errors?.name && (
<div>
<h2>{errors.name}</h2>
</div>
)}
{errors?.email && (
<div>
<h2>{errors.email}</h2>
</div>
)}
{customError && (
<div>
<h2>{customError}</h2>
</div>
)}
</div>
)}
</section>
);
});