Lär känna denna säkerhetsfokuserade JS-runtime med ett praktiskt exempelprojekt.

Deno är en JavaScript-runtime byggd på V8, samma JavaScript-motor som driver Google Chrome. Den ursprungliga skaparen av Node.js skapade Deno för att åtgärda några av bristerna och säkerhetsproblemen hos Node.js.

Även om den är relativt ny, har Deno vunnit popularitet som en säker och modern JavaScript-runtime. Dess fokus på säkerhet, stöd för moderna språkfunktioner och utvecklarvänliga verktyg gör det till ett tilltalande val. Du kan använda den för att bygga applikationer på serversidan, kommandoradsverktyg och andra JavaScript/TypeScript-projekt, som ett enkelt API.

Installerar Deno

Innan du kan använda Deno måste du ladda ner och installera den. Denos installation varierar beroende på ditt operativsystem.

På macOS och Linux kan du installera Deno genom att köra detta kommando:

curl -fsSL https://deno.land/x/install/install.sh | sh

På Windows kan du installera Deno med Powershell med det här kommandot:

irm https://deno.land/install.ps1 | iex
instagram viewer

Du kan bekräfta att din installation lyckades genom att köra kommandot nedan:

deno --version

Kommandot ovan ska skriva ut Deno-versionen till konsolen.

Om du använder VS-kod som IDE kan du ladda ner Denos VS Code-tillägg att lägga till IntelliSense, vilket förbättrar din produktivitet och utvecklingsupplevelse när du arbetar med Deno-projekt.

När du har installerat tillägget, skapa en .vscode mapp i ditt projekts rotkatalog och skapa en settings.json fil i den.

Lägg sedan till kodblocket nedan till settings.json fil för att aktivera IntelliSense:

{
"deno.enable": true,
"deno.unstable": true,
}

Ansluter till en databas

För den här handledningen kommer du att använda MongoDB som en databas för att bevara data från ditt API.

För att ansluta din Deno-app till en MongoDB-databas, skapa en db.js fil i ditt projekts rotkatalog och lägg till kodblocket nedan till den:

// db.js
import { MongoClient } from"https://deno.land/x/[email protected]/mod.ts";

const client = new MongoClient();

try {
await client.connect("mongodb://localhost: 27017/todo");

console.log("Connected to database");
} catch (err) {
console.log("Error connecting to database", err);
}

const db = client.database("todo");

exportdefault db;

Till skillnad från Node.js, som beror på pakethanterare som Node Package Manager (npm) eller garn, har Deno ett inbyggt pakethanteringssystem för att importera och hantera beroenden direkt från URL: er.

Till exempel importerar kodblocket ovan MongoClient från URL: en https://deno.land/x/[email protected]/mod.ts, vilket leder till paketet.

Använd sedan den importerade Deno MongoDB-drivrutinen (MongoClient), upprättar Deno en anslutning mellan din applikation och en lokal MongoDB-databas.

I livescenarier är det säkrare att lagra dina databasuppgifter i en .env fil istället för att lagra dem i vanlig text, som gjorts ovan.

Skapa en databasmodell

Medan det är möjligt att interagera med en MongoDB-databas utan en databasmodell kan det leda till ostrukturerad och mindre underhållbar kod.

För att undvika detta, skapa en TodoModel.ts fil i ditt projekts rotkatalog och strukturera dina data genom att lägga till kodblocket nedan i filen:

import db from"./db.ts";

interface Todo {
title: string;
description: string;
completed?: boolean;
}

const Todo = db.collection("todos");

exportdefault Todo;

Kodblocket ovan definierar ett gränssnitt Att göra som representerar strukturen för ett enda att göra-objekt. Med hjälp av Todo-gränssnittet skapar den en Todo-samling genom att anropa insamlingsmetoden som exponeras av din tidigare skapade MongoDB-instans.

Skapa en server med ek

Oak är ett mellanprogram för Denos inbyggda HTTP-server. Den var inspirerad av Koa, som är en alternativ till Express.js.

För att skapa en server med Oak, skapa en main.ts fil i ditt projekts rotkatalog och lägg till kodblocket nedan i din fil.

// main.ts

import { Application } from"https://deno.land/x/oak/mod.ts";
import router from"./router.ts";

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });
console.log("Server running on port 8000");

Kodblocket ovan importerar Ansökan från Oak URL och skapar en applikationsinstans (app) som lyssnar efter inkommande trafik på port 8000.

De app.use (router.routes()) line registrerar routerns rutter som middleware i Oak-applikationen. Detta innebär att applikationen kommer att matcha de registrerade rutternas vilja mot inkommande förfrågningar, och motsvarande hanterare kommer att köras om en matchning finns.

De app.use (router.allowedMethods()) line hanterar HTTP-metoder som inte är explicit definierade i routern. Till exempel, om den tar emot en begäran med en metod som inte stöds, till exempel en oregistrerad PUT-begäran, tillåtnaMethods() middleware skickar automatiskt ett lämpligt svar (t.ex. 405 Metod ej tillåten).

Implementering av CRUD-funktionalitet

Denna handledning kommer att innehålla ett enkelt att göra-API med CRUD-funktionalitet.

Skapa en router.ts fil i ditt projekts rotkatalog och lägg till kodblocket nedan i din fil:

import { Router } from"https://deno.land/x/oak/mod.ts";
import Todo from"./todoModel.ts";
import { ObjectId } from"https://deno.land/x/[email protected]/mod.ts";

const router = new Router(); // Create Router

Kodblocket ovan importerar och skapar en instans av Oak-routern. Med den här instansen kan du skapa rutthanterare för olika HTTP-metoder genom att anropa respektive metodnamn (skaffa sig, posta, sätta, radera).

Till exempel är kodblocket nedan ett exempel på hur du kan skapa en GET-rutthanterare som returnerar alla dokument i din Todo-samling.

router
.get("/api/todos", (ctx: RouterContextapi/todos">) => {
ctx.response.body = Todo.find();
})

För att skicka ett svarsobjekt med Deno måste du tilldela response.body objekt på RouterContex till responsobjektet. Detsamma gäller statuskoder.

För att lägga till andra rutthanterare kan du koppla dem till den tidigare rutthanteraren.

Såhär:

.get("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
try {
const todo = await Todo.findOne({ _id: new ObjectId(ctx.params.id) });

if (!todo) {
ctx.response.status = 404;

ctx.response.body = {
msg: "Todo not found",
};

return;
}

ctx.response.body = todo;
} catch (error) {
ctx.response.status = 500;

ctx.response.body = {
msg: "Error getting todo",
error,
};
}
})

Kodblocket ovan definierar en GET-rutthanterare som returnerar ett enda Todo-objekt som matchar ID: t i URL-parametrarna.

Definiera sedan en CREATE-rutthanterare som lägger till nya dokument till din samling:

.post("/api/todo/new", async (ctx: RouterContext<"/api/todo/new">) => {
const body = ctx.request.body();
const todo = await body.value;

if (!todo) {
ctx.response.status = 400;
ctx.response.body = { msg: "Invalid data. Please provide a valid todo." };
return;
}

const { title, description } = todo;

if (!(title && description)) {
ctx.response.status = 400;

ctx.response.body = {
msg: "Title or description missing. Please provide a valid todo.",
};

return;
}

try {
await Todo.insertOne({
title: todo.title,
description: todo.description,
completed: false,
});

ctx.response.status = 201;

ctx.response.body = {
msg: "Todo added successfully",
};
} catch (error) {
ctx.response.status = 500;

ctx.response.body = {
msg: "Error adding todo",
error,
};
}
})

Lägg sedan till en PUT-rutthanterare som uppdaterar en Todo baserat på id parameter, med data som skickas i begärandekroppen.

.put("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
try {
const body = ctx.request.body();
const todo = await body.value;

await Todo.updateOne(
{ _id: new ObjectId(ctx.params.id) },
{ $set: { title: todo.title, description: todo.description } }
);

ctx.response.status = 200;

ctx.response.body = {
msg: "Todo updated successfully",
};
} catch (error) {
console.log(error);
ctx.response.status = 500;

ctx.response.body = {
msg: "Error updating todo",
error: error.message,
};
}
})

Slutligen, skapa en DELETE-rutthanterare som tar bort en Todo från din MongoDB-samling:

.delete("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
await Todo.deleteOne({ _id: new ObjectId(ctx.params.id) });

ctx.response.status = 200;

ctx.response.body = {
msg: "Todo deleted successfully",
};
});

Du kan starta din Deno-app med detta kommando:

deno run --allow-net --allow-read --allow-env --watch main.ts

Som standard kan ett Deno-skript inte komma åt något utanför dess räckvidd, till exempel nätverket eller filsystemet. Så för att starta din ansökan måste du inkludera olika flaggor för att ge Deno de nödvändiga behörigheterna.

--allow-net tillåter Deno att göra nätverksförfrågningar. --tillåt-läsa tillåter Deno att komma åt filsystemet och läsa filer. --tillåt-env tillåter Deno att komma åt miljövariabler. De --Kolla på flaggan startar din Deno-app i klockläge.

Migrera från Node.js till Deno

Att migrera från Node.js till Deno för att bygga REST API: er kan ge betydande fördelar för säkerhet, utvecklarproduktivitet och beroendehantering. Genom att använda Denos säkra körtid, inbyggda TypeScript-stöd och förenklade beroendehantering kan du enkelt skapa robusta och effektiva REST-API: er.

Denos omogna ekosystem kan dock få dig att ompröva. Om du väljer att migrera, väg för- och nackdelar noggrant.