Bli kjent med denne sikkerhetsfokuserte JS-kjøringen med et praktisk eksempelprosjekt.

Deno er en JavaScript-runtime bygget på V8, den samme JavaScript-motoren som driver Google Chrome. Den opprinnelige skaperen av Node.js opprettet Deno for å løse noen av manglene og sikkerhetsproblemene til Node.js.

Selv om den er relativt ny, har Deno blitt populær som en sikker og moderne JavaScript-runtime. Fokuset på sikkerhet, støtte for moderne språkfunksjoner og utviklervennlige verktøy gjør det til et tiltalende valg. Du kan bruke den til å bygge applikasjoner på serversiden, kommandolinjeverktøy og andre JavaScript/TypeScript-prosjekter, som en enkel API.

Installerer Deno

Før du kan bruke Deno må du laste ned og installere den. Denos installasjon varierer avhengig av operativsystemet ditt.

På macOS og Linux kan du installere Deno ved å kjøre denne kommandoen:

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

På Windows kan du installere Deno med Powershell ved å bruke denne kommandoen:

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

Du kan bekrefte at installasjonen var vellykket ved å kjøre kommandoen nedenfor:

deno --version

Kommandoen ovenfor skal skrive ut Deno-versjonen til konsollen.

Hvis du bruker VS-kode som en IDE, kan du laste ned Denos VS Code-utvidelse for å legge til IntelliSense, og forbedre produktiviteten og utviklingsopplevelsen når du arbeider med Deno-prosjekter.

Etter å ha installert utvidelsen, oppretter du en .vscode mappe i prosjektets rotkatalog og opprett en settings.json fil i den.

Deretter legger du til kodeblokken nedenfor til settings.json fil for å aktivere IntelliSense:

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

Koble til en database

For denne opplæringen vil du bruke MongoDB som en database for å opprettholde data fra API-en din.

For å koble Deno-appen din til en MongoDB-database, opprett en db.js fil i prosjektets rotkatalog og legg til kodeblokken nedenfor til 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;

I motsetning til Node.js, som avhenger av pakkeforvaltere som Node Package Manager (npm) eller garn, har Deno et innebygd pakkehåndteringssystem for å importere og administrere avhengigheter direkte fra URL-er.

For eksempel importerer kodeblokken over MongoClient fra URL-en https://deno.land/x/[email protected]/mod.ts, som fører til pakken.

Deretter bruker du den importerte Deno MongoDB-driveren (MongoClient), Deno etablerer en forbindelse mellom applikasjonen din og en lokal MongoDB-database.

I live-scenarier er det sikrere å lagre databaselegitimasjonen din i en .env fil i stedet for å lagre dem i ren tekst, som gjort ovenfor.

Opprette en databasemodell

Mens det er mulig å samhandle med en MongoDB-database uten en databasemodell kan dette føre til ustrukturert og mindre vedlikeholdbar kode.

For å unngå dette, lag en TodoModel.ts fil i prosjektets rotkatalog og strukturer dataene dine ved å legge til kodeblokken nedenfor i filen:

import db from"./db.ts";

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

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

exportdefault Todo;

Kodeblokken ovenfor definerer et grensesnitt Å gjøre som representerer strukturen til et enkelt gjøremål. Ved å bruke Todo-grensesnittet oppretter den en Todo-samling ved å kalle innsamlingsmetoden som er eksponert av din tidligere opprettede MongoDB-forekomst.

Opprette en server med eik

Oak er en mellomvare for Denos opprinnelige HTTP-server. Den var inspirert av Koa, som er en alternativ til Express.js.

For å opprette en server med Oak, opprette en main.ts fil i prosjektets rotkatalog og legg til kodeblokken nedenfor i filen.

// 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");

Kodeblokken over importerer applikasjon fra Oak URL og oppretter en applikasjonsforekomst (app) som lytter etter innkommende trafikk på port 8000.

De app.use (router.routes()) line registrerer ruterens ruter som mellomvare i Oak-applikasjonen. Dette betyr at applikasjonen vil matche de registrerte rutene mot innkommende forespørsler, og de korresponderende behandlerne vil kjøre hvis en match eksisterer.

De app.use (router.allowedMethods()) line håndterer HTTP-metoder som ikke er eksplisitt definert i ruteren. For eksempel, hvis den mottar en forespørsel med en metode som ikke støttes, for eksempel en uregistrert PUT-forespørsel, tillatte metoder() mellomvare vil automatisk sende et passende svar (f.eks. 405 Metode ikke tillatt).

Implementering av CRUD-funksjonalitet

Denne opplæringen vil inneholde et enkelt gjøremåls-API med CRUD-funksjonalitet.

Lage en router.ts fil i prosjektets rotkatalog og legg til kodeblokken nedenfor i filen din:

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

Kodeblokken ovenfor importerer og oppretter en forekomst av Oak-ruteren. Ved å bruke denne forekomsten kan du opprette rutebehandlere for ulike HTTP-metoder ved å kalle de respektive metodenavnene (, post, sette, slette).

For eksempel er kodeblokken nedenfor et eksempel på hvordan du kan lage en GET-rutebehandler som returnerer alle dokumentene i Todo-samlingen din.

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

For å sende et svarobjekt ved hjelp av Deno, må du tilordne response.body objekt på RouterContex til responsobjektet. Det samme gjelder statuskoder.

For å legge til andre rutebehandlere, kan du lenke dem til forrige rutebehandler.

Som så:

.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,
};
}
})

Kodeblokken ovenfor definerer en GET-rutebehandler som returnerer et enkelt Todo-element som samsvarer med ID-en i URL-paramene.

Deretter definerer du en CREATE-rutebehandler som legger til nye dokumenter i samlingen din:

.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,
};
}
})

Deretter legger du til en PUT-rutebehandler som oppdaterer en Todo basert på id parameter, med dataene sendt i forespørselsteksten.

.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,
};
}
})

Til slutt, lag en DELETE-rutebehandler som fjerner en Todo fra MongoDB-samlingen din:

.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 starte Deno-appen med denne kommandoen:

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

Som standard kan ikke et Deno-skript få tilgang til noe utenfor dets omfang, for eksempel nettverket eller filsystemet. Så for å starte søknaden din, må du inkludere forskjellige flagg for å gi Deno de nødvendige tillatelsene.

--allow-net lar Deno komme med nettverksforespørsler. -- tillate-lese lar Deno få tilgang til filsystemet og lese filer. --allow-env gir Deno tilgang til miljøvariabler. De --se flagget starter Deno-appen din i klokkemodus.

Migrerer fra Node.js til Deno

Migrering fra Node.js til Deno for å bygge REST APIer kan gi betydelige fordeler for sikkerhet, utviklerproduktivitet og avhengighetsadministrasjon. Ved å bruke Denos sikre kjøretid, native TypeScript-støtte og forenklet avhengighetsadministrasjon kan du enkelt lage robuste og effektive REST APIer.

Imidlertid kan Denos umodne økosystem få deg til å revurdere. Hvis du velger å migrere, vei fordeler og ulemper nøye.