Article original : How to Use SurrealDb with the Fresh Framework and Deno
SurrealDB est une base de données récemment lancée qui a commencé à gagner en popularité dans le monde de la programmation.
SurrealDB a été construite avec le langage Rust et a été créée par Tobie Morgan Hitchcock et Jaime Morgan Hitchcock.
La nouvelle base de données de SurrealDB est dotée de nombreuses fonctionnalités, mais je suis particulièrement intéressé par la bibliothèque Deno surrealDB.
Dans cet article, nous allons créer une application de liste de tâches (todo app) simple avec le framework Fresh et la base de données SurrealDB. Nous utiliserons le framework Fresh pour construire l'API avec SurrealDB.
Le framework Fresh est un nouveau framework JavaScript introduit par Deno lui-même. Fresh utilise la bibliothèque Preact pour concevoir et construire des composants. Fresh est livré avec un support intégré pour TypeScript et Tailwind CSS, ainsi qu'une architecture basée sur les Islands (îlots). De plus, aucune configuration n'est nécessaire.
Deno et Fresh sont prêts pour la production. Vous pouvez donc créer n'importe quelle application web et la déployer en un seul clic. Gardez toutefois à l'esprit que SurrealDB ne l'est peut-être pas encore tout à fait. Selon leur documentation, SurrealDB est prêt pour la production, mais la documentation n'est pas extrêmement claire sur le sujet.
Tout le code est disponible sur GitHub.
Voici une démo de ce que nous allons construire :
Démo de l'application TODO
Comment installer SurrealDB, Deno et le framework Fresh
Il y a trois conditions préalables pour suivre ce tutoriel : la première est d'avoir Deno installé, la deuxième est d'avoir la base de données SurrealDB, et la dernière est d'utiliser le framework Fresh.
Tout d'abord, nous allons installer la base de données SurrealDB et le framework Fresh avec Deno. Vous pouvez ignorer cette partie si vous avez déjà installé Deno et les packages SurrealDB.
Comment installer la base de données SurrealDB sur Linux
Le processus d'installation de SurrealDB est assez simple pour tous les systèmes d'exploitation. Par exemple, sous Linux, vous pouvez installer la base de données avec une seule commande curl.
Si vous avez un système d'exploitation différent, je vous suggère de lire la documentation d' installation de SurrealDB.
Sous Linux, utilisez cette commande :
curl -sSf https://install.surrealdb.com | sh
Installer la base de données SurrealDB sous Linux.
Pour démarrer la base de données SurrealDB sous Linux, exécutez la commande suivante :
surreal start --log debug --user root --pass root memory
- Vous utilisez le drapeau
--userpour votre nom d'utilisateur. Dans mon cas, mon nom d'utilisateur est root. - Vous utilisez le drapeau
--passpour votre mot de passe. Dans mon cas, mon mot de passe est root.
Pour en savoir plus sur tous les drapeaux ou options, exécutez la commande surreal start --help. Voici ce que vous verrez :

Vous êtes maintenant prêt à utiliser la base de données SurrealDB.
Comment installer Deno sur Linux
Deno est un environnement d'exécution JavaScript récent. Il est rapide et sécurisé par rapport à Node.js.
Pour en savoir plus sur Deno, vous pouvez lire ce tutoriel utile que j'ai trouvé sur freeCodeCamp, écrit par Brian Barrow.
Pour installer Deno sur Linux, vous avez besoin d'une seule commande :
curl -fsSL https://deno.land/install.sh | sh
Installer deno sous Linux
Comment installer le framework Fresh avec Deno
Fresh est un nouveau framework JavaScript basé sur Deno. Le framework Fresh supporte TypeScript par défaut. De plus, Fresh envoie par défaut zéro Ko de JavaScript au client.
Vous pouvez configurer un projet Fresh avec la commande suivante :
deno run -A -r https://fresh.deno.dev mon-nouveau-projet-fresh

Vous pouvez lancer un serveur de développement local avec deno task start.
Notez que le framework Fresh et SurrealDB utilisent tous deux le même port 8000. Dans la documentation de SurrealDB, je n'ai trouvé aucune information sur le changement de port. Mais dans Fresh, vous pouvez facilement changer le port à l'intérieur du fichier main.ts. Sinon, sans changer le port, votre localhost Fresh redirigera vers le localhost de SurrealDB.
Par exemple, vous pouvez changer le port dans Fresh comme ceci :
// changer le port dans main.ts
await start(manifest, { port:3002, plugins: [twindPlugin(twindConfig)] });
Structure du projet framework Fresh
La structure des dossiers du projet est assez simple. Pour ce projet, nous devons suivre la structure des dossiers et des fichiers pour créer une application de liste de tâches avec SurrealDB.
Structure des fichiers et des dossiers
Discutons plus en détail de certains fichiers essentiels ici :
- Le dossier components permet de contenir tous les composants personnalisés construits avec Preact.
- Dans le fichier
deno.json, vous ajoutez des tâches et le fichier importMap. Les tâches sont similaires aux scripts dans Node, et dans la section importMap, vous passez un fichier JSON qui contient tous vos packages d'importation de Deno. dev.tsest un fichier créé uniquement pour le développement.fresh.gen.tsest généré et mis à jour automatiquement en fonction dedev.ts. Il inclut toutes les routes, les islands et les autres configurations.- Le fichier
import_map.jsoncontient les importations de tous les packages dont vous avez besoin pour exécuter votre projet. - Les Islands permettent une interactivité basée sur le navigateur côté client dans Fresh. Fondamentalement, avec le dossier island, vous envoyez du JavaScript au navigateur. Par défaut, le framework Fresh envoie zéro Ko de JavaScript.
main.tsest le point d'entrée principal qui aide à démarrer votre application.- Le dossier
routesgère vos chemins et votre API. Il est similaire au dossier pages de Next.js. - Le dossier
staticcontient tous les fichiers statiques comme le JavaScript, les images et les polices sous un répertoire racine. Tous sont accessibles par référence et commencent par l'URL de base (/). Par exemple,/logo.svg. twind.config.tsconfigure Tailwind CSS.- Le dossier
utilitycontient la configuration de la base de données.
Vous pouvez en savoir plus sur la structure des dossiers dans la documentation officielle de Fresh.
Encore une fois, pour lancer un serveur de développement local, utilisez la commande deno task start.
Comment installer la bibliothèque de base de données SurrealDB dans le framework Fresh
Vous avez besoin de la bibliothèque SurrealDB (module) basée sur Deno. C'est une bibliothèque SurrealDB créée par l'équipe de SurrealDB.
La bibliothèque (module) SurrealDB vous aide à connecter votre application à votre base de données. Le module SurrealDB connecte très facilement vos bases de données locales et distantes.
Pour installer le module SurrealDB dans le framework Fresh, copiez simplement le code suivant et collez-le dans le fichier import_map.json :
"surrealdb" : "https://deno.land/x/surrealdb@v0.2.0/mod.ts"
_Collez le code suivant dans le fichier import_map.json_
Comment configurer la base de données SurrealDB dans Fresh
La première étape consiste à créer un fichier de configuration pour la base de données SurrealDB. Ce fichier de configuration vous aide à connecter le framework Fresh à la base de données SurrealDB.
Dans mon cas, je crée une configuration de base de données dans un fichier séparé utility/database.ts. Le fichier séparé permet de réduire votre code et est plus facile à gérer.
// utility/database.ts
// importer surrealdb
import Surreal from "surrealdb";
// charger les variables d'environnement
import "https://deno.land/x/dotenv@v3.2.0/load.ts";
// obtenir l'URL DATABASE_URL
const domain = Deno.env.get("DATABASE_URL")
// base de données surreal
const db = new Surreal(domain);
// connexion
await db.signin({
user: 'root',
pass: 'root',
});
// Sélectionner un espace de noms / une base de données spécifique
await db.use('test', 'test');
export default db
Pour connecter la base de données, assurez-vous que votre base de données est en cours d'exécution et que votre mot de passe et votre nom d'utilisateur correspondent aux identifiants de votre base de données.
Par exemple, lancez votre SurrealDB local avec le nom d'utilisateur et le mot de passe identiques à ceux de votre fichier utility/database.ts.
surreal start --log debug --user root --pass root memory
Comment utiliser les méthodes du module (bibliothèque) SurrealDB
Le module SurrealDB est livré avec des méthodes intégrées. Toutes ces méthodes vous aident à effectuer des opérations CRUD sur la base de données SurrealDB. Ces méthodes vous permettent de créer rapidement, ainsi que d' obtenir, mettre à jour et supprimer des éléments de la base de données.
Dans cet article, nous utiliserons quatre méthodes qui sont create(), update(), delete() et select().
Il existe d'autres méthodes fournies par SurrealDB, que vous pouvez découvrir sur la page de documentation du module SurrealDB.
Comment créer les points de terminaison API
Pour créer une application Todo, vous avez besoin de quatre points de terminaison. Nous utiliserons le framework Fresh pour créer les API. Toutes les routes de l'API vont dans le dossier routes/api.
- Get
- Post
- Isdone (Mise à jour)
- Delete
L'API Get
L'API Get vous permet d'afficher toutes les données de la table todo. Pour accéder à toutes les données de la table Todo, vous avez besoin d'une fonction select() fournie par le module SurrealDB.
import { HandlerContext } from "$fresh/server.ts";
import db from "../../utility/database.ts";
export async function handler(_req: Request, _ctx: HandlerContext) {
try {
// obtenir toute la liste des tâches
const todo = await db.select("todo");
// retourner le todo
return Response.json(JSON.stringify(todo))
} catch (error) {
return new Response(error);
}
}
L'API Post
Dans l'API Post, vous allez créer une nouvelle tâche basée sur le titre. Toutes les tâches sont enregistrées dans la table todo. Avec l'API Get, vous accédez à toutes les tâches de la table todo.
Pour créer un nouvel élément de tâche dans la base de données, vous pouvez utiliser la fonction intégrée create() du module SurrealDB.
import { HandlerContext } from "$fresh/server.ts";
// importer le module uuid de deno
import * as mod from "https://deno.land/std@0.156.0/uuid/mod.ts";
// importer la base de données
import db from "../../utility/database.ts";
export async function handler(_req: Request, _ctx: HandlerContext) {
// obtenir l'URL
const url = new URL(_req.url);
// obtenir le titre à partir de l'URL
const title = url.searchParams.get("title") || "";
try {
// Créer une nouvelle personne avec un ID aléatoire
const NAMESPACE_URL = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
// créer un UUID unique à des fins de démonstration
const uuid = await mod.v5.generate(NAMESPACE_URL, new TextEncoder().encode("python.org"));
// créer de nouvelles données basées sur la valeur
const created = await db.create("todo", {
uuid: uuid,
title: title,
isDone: false
});
// retourner les données
return Response.json({ sucessfull: "vos données ont été soumises avec succès", created })
} catch (error) {
return new Response(error);
}
}
L'API Isdone (Mise à jour)
L'API Isdone aide à mettre à jour les éléments de la table todo. Pour mettre à jour les données de la table, le module SurrealDB fournit une fonction intégrée update à cet effet.
Avec la fonction update, vous pouvez mettre à jour rapidement les tâches par un ou plusieurs éléments en une seule requête.
import { HandlerContext } from "$fresh/server.ts";
// importer la base de données
import db from "../../utility/database.ts";
export async function handler(_req: Request, _ctx: HandlerContext) {
// obtenir l'URL
const url = new URL(_req.url);
// obtenir l'ID du todo – nous mettons à jour le todo sur la base de cet ID.
const todoid = url.searchParams.get("todoID") || "";
// obtenir le titre
const todoTitle = url.searchParams.get("todoTitle") || "";
// obtenir l'UUID
const todoUuid = url.searchParams.get("todoUuid") || "";
try {
// mettre à jour le todo
const person = await db.update(todoid, {
isDone: true,
title: todoTitle,
uuid: todoUuid
});
return Response.json({sucessfull:"vos données ont été soumises avec succès ",person})
} catch (error) {
return new Response(error);
}
}
L'API Delete
Vous utilisez l'API Delete pour supprimer une tâche de la liste. Vous utiliserez la fonction intégrée delete(). Avec cette fonction, vous pouvez rapidement supprimer une tâche en fonction de son ID.
import { HandlerContext } from "$fresh/server.ts";
// importer la base de données
import db from "../../utility/database.ts";
export async function handler(_req: Request, _ctx: HandlerContext) {
// obtenir l'URL
const url = new URL(_req.url);
// obtenir l'ID du todo – nous supprimons le todo sur la base de cet ID.
const todoid = url.searchParams.get("todoID") || "";
try {
// supprimer l'élément todo spécifié
await db.delete(todoid);
return Response.json({ sucessfull: "vos données ont été supprimées avec succès " })
} catch (error) {
return new Response(error);
}
}
Comment créer l'UI pour l'application Todo
UI pour le tableau de bord
Les fichiers Box.tsx et Item.tsx proviennent d'un dossier island. Ces deux fichiers sont connus sous le nom de composants. Dans les deux composants, nous avons besoin d'une intégration JavaScript. Pour cette raison, nous créons les deux composants à l'intérieur du dossier island.
Page d'index
La page d'index montre que les fichiers Box.tsx et Item.tsx proviennent de l'island. Nous allons concevoir la mise en page de la page d'accueil (Index) avec eux.
import { Handlers } from "$fresh/server.ts";
// Importer les composants Box depuis island
import Box from "../islands/Box.tsx";
// Importer les composants Item depuis island
import Item from "../islands/Item.tsx";
// pour charger la variable d'environnement
import "https://deno.land/x/dotenv@v3.2.0/load.ts";
// obtenir la variable d'environnement
let domain= Deno.env.get("DOMAIN")
interface todo {
id: string;
title:string;
isDone:boolean
}
// Appeler l'API get avec le handler Fresh
export const handler: Handlers<todo | null> = {
async GET(_, ctx) {
// appeler l'API get
const response = await fetch(domain + "/api/get").then(
(response)=> response.json()
).then(
(response)=> JSON.parse(response)
).catch(
error=> console.log(error)
);
// passer les données dans les props du composant
return ctx.render(response);
}
};
export default function Home({data}: { data: any; }) {
return (
<div class="h-screen w-screen flex flex-col items-center justify-center bg-blue-600 font-sans">
<div class="flex flex-row w-4/6 justify-center mx-auto">
<h2 class="m-2 p-1 text-5xl font-mono font-serif cursor-pointer">Deno</h2>
<h2 class="m-2 p-1 text-5xl font-mono font-serif cursor-pointer">SurrealDB</h2>
</div>
<div class="bg-white rounded shadow container mx-auto p-3 m-4 w-3/6 lg:w-3/6 xl:w-3/6 md:w-3/6 2xl:w-3/6 ">
<div class=" flex mb-4 flex-col py-2">
<h1 class="text-gray-500 text-lg">Todo List</h1>
<Box/>
</div>
<div class="p-2">
{
data.map( (item: any) =>
<Item item={item} />
)
}
</div>
</div>
</div>
);
}
Le composant Box.tsx
Le composant Box aide à appeler l'API post et à créer une nouvelle tâche dans la base de données. Box.tsx est un composant basé sur une island qui est créé avec Preact. Preact est similaire à React, mais Preact est une version légère de la bibliothèque.
Sur le composant Box, nous récupérons la valeur dans l'input avec l'événement onChange. Ensuite, après que l'utilisateur a cliqué sur le bouton d'ajout, nous appelons l'API post pour créer une nouvelle tâche dans la base de données SurrealDB.
Concevoir le composant box avec le framework Fresh
import { useState } from "preact/hooks";
// importer Notification depuis les composants
import Notification from "../components/Notification.tsx";
interface todo {
id: string;
title: string;
isDone: boolean
}
export default function Box({ data }: { data: any; }) {
// titre
const [title, setTitle] = useState("");
// afficher la Notification en fonction du succès
const [successful, setSuccessful] = useState(false);
function submit() {
if (title) {
// appeler l'API post
fetch(`/api/post?title=${encodeURIComponent(title)}`)
.then((res) => res.json())
.then((data) => {
console.log("vos données ont été soumises avec succès ");
// changer false en true
setSuccessful(true)
});
}
}
return (
<>
<Notification successful={successful} setSuccessful={setSuccessful} />
<div class="flex mt-4 justify-between">
<input onChange={(event) => setTitle(event.currentTarget.value)} class="shadow appearance-none border rounded w-full py-2 px-3 mr-4 text-gray-600" placeholder="Add Todo" />
<button onClick={submit} class="flex-shrink p-2 border-2 rounded text-purple-500 border-purple-500 hover:text-white hover:bg-purple-500 w-24">Add</button>
</div>
</>
);
}
Le composant Item.tsx
Le composant Item appelle deux API – l'une est l'API delete et la seconde est l'API update. L'API delete supprime un élément de la table todo et l'API update met à jour l'élément dans la table todo de la base de données.
Item.tsx est un composant island similaire au composant Box. Le composant item est également construit avec Preact.
Notre premier bouton change selon que la tâche est terminée ou en attente, et le second bouton supprime la tâche en fonction de son ID.
Tout d'abord, nous récupérons la valeur dans l'input avec l'événement onChange. Et après que l'utilisateur a cliqué sur le bouton d'ajout, nous appelons l'API post pour créer une nouvelle tâche dans la base de données SurrealDB.
Lorsque le bouton de suppression est cliqué, nous appelons l'API delete avec l'ID du todo pour supprimer la tâche de la base de données. Lorsque le bouton "Not Done" est cliqué, nous appelons l'API Isdone pour mettre à jour l'état dans la base de données.
Composant Item dans le framework Fresh
import { useState } from "preact/hooks";
// importer Notification depuis les composants
import Notification from "../components/Notification.tsx";
interface todo {
id: string;
title: string;
isDone: boolean
}
export default function Item({ item }) {
// todo
const [todo, setTodoID] = useState(
{
id: item.id,
title: item.title,
uuid: item.uuid
}
);
// afficher la Notification en fonction du succès
const [successful, setSuccessful] = useState(false);
// fonction de suppression
function deleteItem() {
if (todo.id) {
// appeler l'API delete
fetch(`/api/delete?todoID=${encodeURIComponent(todo.id)}`)
.then((res) => res.json())
.then((data) => {
console.log("vos données ont été soumises avec succès ");
setSuccessful(true)
});
}
}
// isdone
function isDone() {
if (todo.id) {
// appeler l'API isdone
fetch(`/api/isdone?todoID=${encodeURIComponent(todo.id)}&todoTitle=${encodeURIComponent(todo.title)}&todoUuid=${encodeURIComponent(todo.uuid)}`)
.then((res) => res.json())
.then((data) => {
console.log("vos données ont été soumises avec succès ");
setSuccessful(true)
});
}
}
return (
<>
<Notification successful={successful} setSuccessful={setSuccessful} />
<div class="flex mb-4 items-center">
<p class={`${item.isDone === false ? "w-full text-green-500 cursor-pointer" : " w-full line-through decoration-purple-600 text-green-500 cursor-pointer"}`}>{item.title}</p>
<button onClick={isDone} class="flex-shrink p-2 ml-4 mr-2 border-2 rounded hover:text-white text-gray-500 border-gray-500 hover:bg-gray-500 w-32">
{item.isDone === true ? "Done" : " Not done"}
</button>
<button onClick={deleteItem} class="flex-shrink p-2 ml-2 border-2 rounded text-red-500 border-red-500 hover:text-white hover:bg-red-500 w-24">Remove</button>
</div>
</>
);
}
Et voilà – nous avons implémenté toutes les fonctionnalités de notre application Todo.
Conclusion
SurrealDB est une base de données utile, et j'espère que vous avez apprécié d'en apprendre davantage à son sujet dans ce tutoriel.
Il y a souvent beaucoup d'exigences pour commencer à travailler avec d'autres bases de données, mais SurrealDB est très simple. Vous n'avez besoin que d'une seule commande pour démarrer la base de données localement et travailler avec elle. C'est une nouvelle révolution dans les bases de données.
Le gros problème est que SurrealDB n'est pas clair sur le fait qu'il soit livré avec des capacités de production. À l'heure actuelle, il ne semble pas remplir la promesse d'une application web prête pour la production en un clic (comme MongoDB Atlas, par exemple).
Vous pouvez déployer SurrealDB avec une image Docker. Le problème est que la documentation manque parfois d'informations pour un nouveau développeur (par exemple, comment changer les mots de passe et les utilisateurs dans un conteneur Docker).
Sans infrastructure cloud, vous ne seriez pas en mesure de déployer l'application avec SurrealDB. Pour cette raison, je n'ai pas fourni de démo en direct de l'application Todo. Mais je sais qu'à l'avenir, SurrealDB changera le futur des bases de données.