Zapoznaj się z tym zorientowanym na bezpieczeństwo środowiskiem wykonawczym JS za pomocą praktycznego przykładowego projektu.
Deno to środowisko wykonawcze JavaScript zbudowane na V8, tym samym silniku JavaScript, który napędza Google Chrome. Pierwotny twórca Node.js stworzył Deno, aby rozwiązać niektóre niedociągnięcia i obawy związane z bezpieczeństwem Node.js.
Chociaż jest stosunkowo nowy, Deno zyskał popularność jako bezpieczne i nowoczesne środowisko uruchomieniowe JavaScript. Koncentracja na bezpieczeństwie, obsługa nowoczesnych funkcji językowych i narzędzia przyjazne dla programistów sprawiają, że jest to atrakcyjny wybór. Możesz go używać do tworzenia aplikacji po stronie serwera, narzędzi wiersza poleceń i innych projektów JavaScript/TypeScript, takich jak prosty interfejs API.
Instalacja Deno
Zanim będziesz mógł korzystać z Deno, musisz go pobrać i zainstalować. Instalacja Deno różni się w zależności od systemu operacyjnego.
W systemach macOS i Linux możesz zainstalować Deno, uruchamiając to polecenie:
curl -fsSL https://deno.land/x/install/install.sh | sh
W systemie Windows możesz zainstalować Deno za pomocą Powershell, używając tego polecenia:
irm https://deno.land/install.ps1 | iex
Możesz potwierdzić, że instalacja przebiegła pomyślnie, uruchamiając poniższe polecenie:
deno --version
Powyższe polecenie powinno wydrukować wersję Deno na konsoli.
Jeśli używasz VS Code jako IDE, możesz pobrać Rozszerzenie VS Code firmy Deno aby dodać IntelliSense, zwiększając produktywność i doświadczenie programistyczne podczas pracy z projektami Deno.
Po pomyślnym zainstalowaniu rozszerzenia utwórz plik .vscode folder w katalogu głównym projektu i utwórz plik ustawienia.json plik w nim.
Następnie dodaj poniższy blok kodu do pliku ustawienia.json plik, aby włączyć funkcję IntelliSense:
{
"deno.enable": true,
"deno.unstable": true,
}
Łączenie z bazą danych
W tym samouczku użyjesz MongoDB jako bazy danych do utrwalania danych z interfejsu API.
Aby połączyć aplikację Deno z bazą danych MongoDB, utwórz plik db.js plik w katalogu głównym projektu i dodaj do niego poniższy blok kodu:
// 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;
W przeciwieństwie do Node.js, który zależy od menedżerowie pakietów podobnie jak Menedżer pakietów Node (npm) lub przędza, Deno ma wbudowany system zarządzania pakietami do importowania i zarządzania zależnościami bezpośrednio z adresów URL.
Na przykład blok kodu powyżej importuje Klient Mongo z adresu URL https://deno.land/x/[email protected]/mod.ts, co prowadzi do pakietu.
Następnie, używając zaimportowanego sterownika Deno MongoDB (Klient Mongo), Deno ustanawia połączenie między Twoją aplikacją a lokalną bazą danych MongoDB.
W scenariuszach na żywo bezpieczniejsze jest przechowywanie poświadczeń bazy danych w pliku .env zamiast przechowywać je w postaci zwykłego tekstu, jak to zrobiono powyżej.
Tworzenie modelu bazy danych
O ile jest to możliwe współdziałać z bazą danych MongoDB bez modelu bazy danych może to prowadzić do nieustrukturyzowanego i trudniejszego w utrzymaniu kodu.
Aby tego uniknąć, utwórz plik TodoModel.ts w katalogu głównym projektu i uporządkuj swoje dane, dodając poniższy blok kodu do pliku:
import db from"./db.ts";
interface Todo {
title: string;
description: string;
completed?: boolean;
}const Todo = db.collection
("todos");
exportdefault Todo;
Powyższy blok kodu definiuje interfejs Do zrobienia który reprezentuje strukturę pojedynczego elementu do zrobienia. Następnie za pomocą interfejsu Todo tworzy kolekcję Todo, wywołując metodę kolekcji udostępnioną przez wcześniej utworzoną instancję MongoDB.
Tworzenie serwera za pomocą dębu
Oak to oprogramowanie pośrednie dla natywnego serwera HTTP Deno. Został zainspirowany Koa, który jest alternatywa dla Express.js.
Aby utworzyć serwer za pomocą Oak, utwórz plik główne.ts plik w katalogu głównym projektu i dodaj poniższy blok kodu do swojego pliku.
// 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");
Blok kodu powyżej importu Aplikacja z adresu URL Oak i tworzy instancję aplikacji (aplikacja), który nasłuchuje ruchu przychodzącego na porcie 8000.
The app.use (router.routes()) line rejestruje trasy routera jako oprogramowanie pośrednie w aplikacji Oak. Oznacza to, że aplikacja będzie dopasowywać zarejestrowane trasy do przychodzących żądań, a odpowiednie procedury obsługi będą uruchamiane, jeśli istnieje dopasowanie.
The app.use (router.allowedMethods()) line obsługuje metody HTTP, które nie są jawnie zdefiniowane w routerze. Na przykład, jeśli otrzyma żądanie z nieobsługiwaną metodą, na przykład niezarejestrowane żądanie PUT, dozwoloneMetody() oprogramowanie pośredniczące automatycznie wyśle odpowiednią odpowiedź (np. Metoda 405 niedozwolona).
Implementacja funkcjonalności CRUD
Ten samouczek będzie zawierał prosty interfejs API zadań do wykonania z funkcją CRUD.
Stwórz router.ts plik w katalogu głównym projektu i dodaj poniższy blok kodu do swojego pliku:
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
Powyższy blok kodu importuje i tworzy instancję routera Oak. Korzystając z tej instancji, możesz utworzyć procedury obsługi tras dla różnych metod HTTP, wywołując odpowiednie nazwy metod (Dostawać, post, umieścić, usuwać).
Na przykład poniższy blok kodu jest przykładem tego, jak można utworzyć procedurę obsługi trasy GET, która zwraca wszystkie dokumenty w Twojej kolekcji Todo.
router
.get("/api/todos", (ctx: RouterContextapi/todos">) => {
ctx.response.body = Todo.find();
})
Aby wysłać obiekt odpowiedzi za pomocą Deno, musisz przypisać odpowiedź.ciało obiekt na RouterContex do obiektu odpowiedzi. To samo dotyczy kodów statusu.
Aby dodać inne procedury obsługi tras, możesz połączyć je łańcuchowo z poprzednią obsługą tras.
jak tak:
.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,
};
}
})
Powyższy blok kodu definiuje procedurę obsługi trasy GET, która zwraca pojedynczy element Todo pasujący do identyfikatora w parametrach adresu URL.
Następnie zdefiniuj procedurę obsługi trasy CREATE, która dodaje nowe dokumenty do Twojej kolekcji:
.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,
};
}
})
Następnie dodaj procedurę obsługi trasy PUT, która aktualizuje Todo na podstawie ID parametr, z danymi przesłanymi w treści żądania.
.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,
};
}
})
Na koniec utwórz procedurę obsługi trasy DELETE, która usuwa Todo z Twojej kolekcji MongoDB:
.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",
};
});
Możesz uruchomić aplikację Deno za pomocą tego polecenia:
deno run --allow-net --allow-read --allow-env --watch main.ts
Domyślnie skrypt Deno nie może uzyskać dostępu do niczego poza jego zakresem, na przykład do sieci lub systemu plików. Aby więc uruchomić aplikację, musisz dołączyć różne flagi, aby przyznać Deno wymagane uprawnienia.
--allow-net pozwala Deno na wysyłanie żądań sieciowych. --pozwól na odczyt pozwala Deno na dostęp do systemu plików i odczyt plików. --allow-env umożliwia Deno dostęp do zmiennych środowiskowych. The --oglądać flaga uruchamia aplikację Deno w trybie zegarka.
Migracja z Node.js do Deno
Migracja z Node.js do Deno w celu tworzenia interfejsów API REST może przynieść znaczne korzyści w zakresie bezpieczeństwa, produktywności programistów i zarządzania zależnościami. Korzystając z bezpiecznego środowiska uruchomieniowego Deno, natywnej obsługi języka TypeScript i uproszczonego zarządzania zależnościami, możesz łatwo tworzyć solidne i wydajne interfejsy API REST.
Jednak niedojrzały ekosystem Deno może skłonić Cię do ponownego rozważenia. Jeśli zdecydujesz się na migrację, rozważ dokładnie wszystkie za i przeciw.