Jeg skrev for nylig om, hvordan man laver en Todo API i Deno + Oak (uden at bruge en database) . Du kan finde repoen under chapter_1:oak på GitHub.
Denne vejledning fortsætter, hvor den anden slap, og jeg vil gennemgå, hvordan man integrerer MySQL i et Deno og Oak-projekt.
Hvis du på noget tidspunkt ønsker at se hele kildekoden, der er brugt i denne øvelse, er den tilgængelig på chapter_2:mysql . Giv den gerne en stjerne på GitHub, hvis du kan lide den.
Jeg går ud fra, at du allerede har gennemført den sidste tutorial nævnt ovenfor. Hvis ikke, så tjek det ud her og vend tilbage, når du er færdig.
Før vi starter, skal du sørge for, at du har en MySQL-klient installeret og kørende:
- MySQL-fællesskabsserver [Download her]
- MySQL Workbench [Download her]
Jeg skrev en lille guide til Mac OS-brugere om opsætning af MySQL, fordi jeg også kæmpede med det. Tjek det ud her.
Hvis du er på en Windows-maskine, kan du bruge de samme værktøjer, eller du kan også bruge XAMPP til at have en MySQL-instans kørende i dit dashboard.
Når du har en MySQL-instans kørende, kan vi begynde vores tutorial.
Lad os begynde
Forudsat at du kommer fra denne artikel, Todo API i Deno + Oak (uden at bruge en database) , vil vi gøre følgende:
- Opret en MySQL-databaseforbindelse
- Skriv et lille script, der nulstiller databasen, hver gang vi starter vores Deno-server
- Udfør CRUD-handlinger på et bord
- Tilføj CRUD-funktionaliteten til vores API-controllere
En sidste ting – her er hele commit-forskellen, der blev lavet i kapitel 1 for at tilføje MySQL til projektet (kildekode, der viser de nye tilføjelser fra kapitel 1).
I din projektrodmappe – min hedder chapter_2:mysql
, dog din kan hedde hvad du vil – opret en mappe kaldet db . Inde i den mappe skal du oprette en fil kaldet config.ts and tilføje følgende indhold til det:
export const DATABASE: string = "deno";
export const TABLE = {
TODO: "todo",
};
Ikke noget fancy her, bare at definere vores databasenavn sammen med et objekt til tabeller og derefter eksportere det. Vores projekt vil have en database kaldet "deno", og inde i den db vil vi kun have en tabel kaldet "todo".
Dernæst inde i db mappe, skal du oprette en anden fil kaldet client.ts og tilføj følgende indhold:
import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";
const client = await new Client();
client.connect({
hostname: "127.0.0.1",
username: "root",
password: "",
db: "",
});
export default client;
Der sker et par ting her.
Vi importerer Client
fra mysql
bibliotek. Client
hjælper os med at oprette forbindelse til vores database og udføre handlinger i databasen.
client.connect({
hostname: "127.0.0.1",
username: "root",
password: "",
db: "",
});
Client
giver en metode kaldet connect
som tager et objekt ind, hvor vi kan give hostname
, username
, password
og db
. Med disse oplysninger kan den etablere en forbindelse til vores MySQL-instans.
Sørg for, at dit username
har ingen password
, da det vil være i konflikt med at oprette forbindelse til Denos MySQL-bibliotek. Hvis du ikke ved, hvordan du gør det, så læs denne vejledning, jeg skrev.
Jeg har forladt database
felt tomt her, fordi jeg vil vælge det manuelt senere i mit script.
Lad os tilføje et script, der vil initialisere en database kaldet "deno", vælge det, og inde i den db oprette en tabel kaldet "todo".
Inde i db/client.ts
fil lad os lave nogle nye tilføjelser:
import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";
const client = await new Client();
client.connect({
hostname: "127.0.0.1",
username: "root",
password: "",
db: "",
});
const run = async () => {
// create database (if not created before)
await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
// select db
await client.execute(`USE ${DATABASE}`);
// delete table if it exists before
await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
// create table
await client.execute(`
CREATE TABLE ${TABLE.TODO} (
id int(11) NOT NULL AUTO_INCREMENT,
todo varchar(100) NOT NULL,
isCompleted boolean NOT NULL default false,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`);
};
run();
export default client;
Her importerer vi DATABASE
og TABLE
fra vores konfigurationsfil og derefter bruge disse værdier i en ny funktion kaldet run()
.
Lad os nedbryde denne run()
fungere. Jeg har tilføjet kommentarer i filen for at hjælpe dig med at forstå arbejdsgangen:
const run = async () => {
// create database (if not created before)
await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
// select db
await client.execute(`USE ${DATABASE}`);
// delete table if it exists before
await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
// create table
await client.execute(`
CREATE TABLE ${TABLE.TODO} (
id int(11) NOT NULL AUTO_INCREMENT,
todo varchar(100) NOT NULL,
isCompleted boolean NOT NULL default false,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`);
};
run();
- Opret en database kaldet
deno
. Hvis det allerede findes, så gør ingenting. - Vælg derefter den database, der skal bruges, som kaldes
deno
- Slet tabellen inde i
deno
kaldettodo
hvis den allerede eksisterer. - Opret derefter en ny tabel inde i
deno
db, kald dettodo
, og definere dens struktur:Den vil have en unik automatisk stigningid
som vil være et heltal, et andet felt kaldettodo
som vil være en streng, og til sidst et felt kaldetisCompleted
som er en boolsk. Jeg definerer ogsåid
som min primære nøgle.
Grunden til, at jeg skrev dette script, var, at jeg ikke ønsker at have ekstra information i MySQL-instansen. Hver gang scriptet kører, geninitialiserer det bare alt.
Du behøver ikke at tilføje dette script. Men hvis du ikke gør det, bliver du nødt til manuelt at oprette en db og tabellen.
Tjek også Deno MySQL-bibliotekets dokumenter om db-oprettelse og om tabeloprettelse.
Går vi tilbage til vores dagsorden, har vi netop opnået to ting ud af de fire nævnte øverst i artiklen:
- Opret en MySQL-databaseforbindelse
- Skriv et lille script, der nulstiller databasen, hver gang vi starter vores Deno-server
Det er allerede 50% af selvstudiet. Desværre kan vi ikke se så meget der sker lige nu. Lad os hurtigt tilføje noget funktionalitet for at se det fungere.
Udførelse af CRUD-operationer på en tabel og tilføjelse af funktionalitet til vores API-controllere
Vi skal først opdatere vores Todo-grænseflade. Gå til interfaces/Todo.ts
fil og tilføj følgende:
export default interface Todo {
id?: number,
todo?: string,
isCompleted?: boolean,
}
Hvad denne ?
gør, er det gør nøglen i objektet valgfri. Jeg gjorde dette, fordi jeg senere vil bruge forskellige funktioner til at sende objekter med kun et id
, todo
, isCompleted
, eller dem alle på én gang.
Hvis du vil lære mere om valgfri egenskaber i TypeScript, så gå over til deres dokumenter her.
Opret derefter en ny mappe kaldet modeller og inde i den mappe skal du oprette en fil kaldet todo.ts . Tilføj følgende indhold til filen:
import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";
export default {
/**
* Takes in the id params & checks if the todo item exists
* in the database
* @param id
* @returns boolean to tell if an entry of todo exits in table
*/
doesExistById: async ({ id }: Todo) => {},
/**
* Will return all the entries in the todo column
* @returns array of todos
*/
getAll: async () => {},
/**
* Takes in the id params & returns the todo item found
* against it.
* @param id
* @returns object of todo item
*/
getById: async ({ id }: Todo) => {},
/**
* Adds a new todo item to todo table
* @param todo
* @param isCompleted
*/
add: async (
{ todo, isCompleted }: Todo,
) => {},
/**
* Updates the content of a single todo item
* @param id
* @param todo
* @param isCompleted
* @returns integer (count of effect rows)
*/
updateById: async ({ id, todo, isCompleted }: Todo) => {},
/**
* Deletes a todo by ID
* @param id
* @returns integer (count of effect rows)
*/
deleteById: async ({ id }: Todo) => {},
};
Lige nu er funktionerne tomme, men det er okay. Vi fylder dem op én efter én.
Gå derefter til controllers/todo.ts
fil, og sørg for at tilføje følgende:
// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";
export default {
/**
* @description Get all todos
* @route GET /todos
*/
getAllTodos: async ({ response }: { response: any }) => {},
/**
* @description Add a new todo
* @route POST /todos
*/
createTodo: async (
{ request, response }: { request: any; response: any },
) => {},
/**
* @description Get todo by id
* @route GET todos/:id
*/
getTodoById: async (
{ params, response }: { params: { id: string }; response: any },
) => {},
/**
* @description Update todo by id
* @route PUT todos/:id
*/
updateTodoById: async (
{ params, request, response }: {
params: { id: string };
request: any;
response: any;
},
) => {},
/**
* @description Delete todo by id
* @route DELETE todos/:id
*/
deleteTodoById: async (
{ params, response }: { params: { id: string }; response: any },
) => {},
};
Her har vi også tomme funktioner. Lad os begynde at fylde dem op.
[Hent] alle todos API
Inde i models/todo.ts
, tilføje en definition for en funktion kaldet getAll
:
import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";
export default {
/**
* Will return all the entries in the todo column
* @returns array of todos
*/
getAll: async () => {
return await client.query(`SELECT * FROM ${TABLE.TODO}`);
},
}
Client
afslører også en anden metode udover connect
(vi brugte en "connect"-metode i db/client.ts
fil), og det er query
. client.query
metode lader os køre MySQL-forespørgsler direkte fra vores Deno-kode, som den er.
Gå derefter til controllers/todo.ts
tilføje definition for getAllTodos
:
// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";
export default {
/**
* @description Get all todos
* @route GET /todos
*/
getAllTodos: async ({ response }: { response: any }) => {
try {
const data = await TodoModel.getAll();
response.status = 200;
response.body = {
success: true,
data,
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
}
},
}
Alt, hvad vi gør, er at importere TodoModel
og bruger dens metode kaldet getAll
, som vi lige har defineret nu. Da det vender tilbage som et løfte, har vi pakket det ind i async/wait.
Metoden TodoModel.getAll()
vil returnere os et array, som vi blot returnerer til response.body
med status
indstillet til 200
.
Hvis løftet fejler, eller der er en anden fejl, går vi blot til vores catch-blok og returnerer en status på 400 med success
indstillet til falsk. Vi indstiller også message
til det, vi får fra fangblokken.
Det er det, vi er færdige. Lad os nu fyre op i vores terminal.
Sørg for, at din MySQL-instans kører. Indtast i din terminal:
$ deno run --allow-net server.ts
Din terminal skulle se nogenlunde sådan ud:
Min konsol fortæller mig to ting her.
- At min Deno API-server kører på port 8080
- At min MySQL-instans kører på
127.0.0.1
, som erlocalhost
Lad os teste vores API. Jeg bruger Postman her, men du kan bruge din foretrukne API-klient.
Lige nu returnerer den kun tomme data. Men når vi føjer data til vores todo
tabel, vil den returnere disse todos her.
Fantastisk. En API nede og fire mere tilbage.
[Post] tilføj en todo API
I models/todo.ts
fil, skal du tilføje følgende definition for add()
funktion:
export default {
/**
* Adds a new todo item to todo table
* @param todo
* @param isCompleted
*/
add: async (
{ todo, isCompleted }: Todo,
) => {
return await client.query(
`INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
[
todo,
isCompleted,
],
);
},
}
Tilføj-funktionen tager objekt ind som et argument, der har to elementer:todo
og isCompleted
.
Så add: async ({ todo, isCompleted }: Todo) => {}
kan også skrives som ({todo, isCompleted}: {todo:string, isCompleted:boolean})
. Men da vi allerede har en grænseflade defineret i vores interfaces/Todo.ts
fil, som er
export default interface Todo {
id?: number,
todo?: string,
isCompleted?: boolean,
}
vi kan simpelthen skrive dette som add: async ({ todo, isCompleted }: Todo) => {}
. Dette fortæller TypeScript, at denne funktion har to argumenter, todo
, som er en streng, og isCompleted
, som er en boolsk.
Hvis du vil læse mere om grænseflader, har TypeScript et fremragende dokument om det, som du kan finde her.
Inde i vores funktion har vi følgende:
return await client.query(
`INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
[
todo,
isCompleted,
],
);
Denne forespørgsel kan opdeles i to dele:
INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)
. De to spørgsmålstegn her angiver en brug af variabler i denne forespørgsel.- Den anden del,
[todo, isCompleted]
, er de variabler, der vil gå i første del af forespørgslen og erstattes med(?, ?)
Table.Todo
er kun en streng, der kommer fra filendb/config.ts
hvorTable.Todo
værdien er "todo
"
Næste inde i vores controllers/todo.ts
fil, skal du gå til definitionen af createTodo()
funktion:
export default {
/**
* @description Add a new todo
* @route POST /todos
*/
createTodo: async (
{ request, response }: { request: any; response: any },
) => {
const body = await request.body();
if (!request.hasBody) {
response.status = 400;
response.body = {
success: false,
message: "No data provided",
};
return;
}
try {
await TodoModel.add(
{ todo: body.value.todo, isCompleted: false },
);
response.body = {
success: true,
message: "The record was added successfully",
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
}
},
}
Lad os opdele dette i to dele:
Del 1
const body = await request.body();
if (!request.hasBody) {
response.status = 400;
response.body = {
success: false,
message: "No data provided",
};
return;
}
Det eneste, vi gør her, er at tjekke, om brugeren sender data i kroppen. Hvis ikke, returnerer vi en status 400
og returnerer success: false
i brødteksten og message: <erromessage-string>
.
Del 2
try {
await TodoModel.add(
{ todo: body.value.todo, isCompleted: false },
);
response.body = {
success: true,
message: "The record was added successfully",
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
}
Hvis der ikke er nogen fejl, vises TodoModel.add()
funktionen kaldes og returnerer blot en status på 200
og en bekræftelsesmeddelelse til brugeren.
Ellers giver det bare en lignende fejl, som vi gjorde i den forrige API.
Nu er vi færdige. Tænd din terminal og sørg for, at din MySQL-instans kører. Indtast i din terminal:
$ deno run --allow-net server.ts
Gå til Postman og kør API-ruten for denne controller:
Det er fantastisk, nu har vi to fungerende API'er. Kun tre tilbage.
[GET] opgave efter id API
I dine models/todo.ts
fil, tilføje definition for disse to funktioner, doesExistById()
og getById()
:
export default {
/**
* Takes in the id params & checks if the todo item exists
* in the database
* @param id
* @returns boolean to tell if an entry of todo exits in table
*/
doesExistById: async ({ id }: Todo) => {
const [result] = await client.query(
`SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
[id],
);
return result.count > 0;
},
/**
* Takes in the id params & returns the todo item found
* against it.
* @param id
* @returns object of todo item
*/
getById: async ({ id }: Todo) => {
return await client.query(
`SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
[id],
);
},
}
Lad os tale om hver funktion en efter en:
doesExistById
tager etid
ind og returnerer enboolean
angiver, om en bestemt opgave findes i databasen eller ej.
Lad os opdele denne funktion:
const [result] = await client.query(
`SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
[id],
);
return result.count > 0;
Vi tjekker blot antallet her i tabellen mod et bestemt todo-id. Hvis antallet er større end nul, returnerer vi true
. Ellers returnerer vi false
.
getById
returnerer opgaveelementet mod et bestemt id:
return await client.query(
`SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
[id],
);
Vi kører simpelthen en MySQL-forespørgsel her for at få en opgave efter id og returnere resultatet, som det er.
Gå derefter til dine controllers/todo.ts
fil og tilføje en definition for en getTodoById
controller metode:
export default {
/**
* @description Get todo by id
* @route GET todos/:id
*/
getTodoById: async (
{ params, response }: { params: { id: string }; response: any },
) => {
try {
const isAvailable = await TodoModel.doesExistById(
{ id: Number(params.id) },
);
if (!isAvailable) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
const todo = await TodoModel.getById({ id: Number(params.id) });
response.status = 200;
response.body = {
success: true,
data: todo,
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
}
},
}
Lad os opdele dette i to mindre dele:
const isAvailable = await TodoModel.doesExistById(
{ id: Number(params.id) },
);
if (!isAvailable) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
Først tjekker vi om opgaven findes i databasen mod et id ved at bruge denne metode:
const isAvailable = await TodoModel.doesExistById(
{ id: Number(params.id) },
);
Her skal vi konvertere params.id
ind i et Number
fordi vores todo-grænseflade kun accepterer id
som et tal. Dernæst sender vi bare params.id
til doesExistById
metode. Denne metode vender tilbage som en boolesk.
Så tjekker vi blot, om opgaven ikke er tilgængelig, og returnerer en 404
metode med vores standardsvar ligesom med de tidligere endepunkter:
if (!isAvailable) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
Så har vi:
try {
const todo: Todo = await TodoModel.getById({ id: Number(params.id) });
response.status = 200;
response.body = {
success: true,
data: todo,
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
Dette svarer til, hvad vi gjorde i vores tidligere API'er. Her henter vi blot data fra db'en, og indstiller variablen todo
, og returnerer derefter svaret. Hvis der er en fejl, returnerer vi blot en standard fejlmeddelelse i catch-blokken tilbage til brugeren.
Tænd nu din terminal og sørg for, at din MySQL-instans kører. Indtast i din terminal:
$ deno run --allow-net server.ts
Gå til Postman og kør API-ruten for denne controller.
Husk, at hver gang vi genstarter vores server, nulstiller vi db. Hvis du ikke ønsker denne adfærd, kan du blot kommentere run
funktion i filen db/client.ts
.
Indtil videre har vi lavet API'er til:
- Hent alle gøremål
- Opret en ny opgave
- Få en opgave efter ID
Og her er de resterende API'er:
- Opdater en opgave efter ID
- Slet en opgave efter ID
[PUT] opdater opgave efter id API
Lad os først oprette en model for denne API. Gå ind i vores models/todo.ts
fil og tilføje en definition for en updateById
funktion:
**
* Updates the content of a single todo item
* @param id
* @param todo
* @param isCompleted
* @returns integer (count of effect rows)
*/
updateById: async ({ id, todo, isCompleted }: Todo) => {
const result = await client.query(
`UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
[
todo,
isCompleted,
id,
],
);
// return count of rows updated
return result.affectedRows;
},
updateById
tager 3 parametre:id
, todo
, og isCompleted
.
Vi kører simpelthen en MySQL-forespørgsel i denne funktion:
onst result = await client.query(
`UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
[
todo,
isCompleted,
id,
],
);
Dette opdaterer et enkelt opgaveelements todo
og isCompleted
med et specifikt id
.
Dernæst returnerer vi et antal rækker opdateret af denne forespørgsel ved at gøre:
// return count of rows updated
return result.affectedRows;
Antallet vil enten være 0 eller 1, men aldrig mere end 1. Dette skyldes, at vi har unikke id'er i vores database – flere todos med det samme id kan ikke eksistere.
Gå derefter til vores controllers/todo.ts
fil og tilføje en definition for en updateTodoById
funktion:
updateTodoById: async (
{ params, request, response }: {
params: { id: string };
request: any;
response: any;
},
) => {
try {
const isAvailable = await TodoModel.doesExistById(
{ id: Number(params.id) },
);
if (!isAvailable) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
// if todo found then update todo
const body = await request.body();
const updatedRows = await TodoModel.updateById({
id: Number(params.id),
...body.value,
});
response.status = 200;
response.body = {
success: true,
message: `Successfully updated ${updatedRows} row(s)`,
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
}
},
Dette er næsten det samme som for vores tidligere API'er, vi skrev. Den del, der er ny her, er denne:
// if todo found then update todo
const body = await request.body();
const updatedRows = await TodoModel.updateById({
id: Number(params.id),
...body.value,
});
Vi får simpelthen den brødtekst, som brugeren sender os i JSON, og sender brødteksten til vores TodoModel.updateById
funktion.
Vi skal konvertere id
til et nummer for at overholde vores Todo-grænseflade.
Forespørgslen udføres og returnerer antallet af opdaterede rækker. Derfra returnerer vi det blot i vores svar. Hvis der er en fejl, går den til catch-blokken, hvor vi returnerer vores standardsvarmeddelelse.
Lad os køre dette og se, om det virker. Sørg for, at din MySQL-instans kører, og kør følgende fra din terminal:
$ deno run --allow-net server.ts
Gå til Postman og kør API-ruten for denne controller:
[DELETE] opgave efter id API
I dine models/todo.ts
fil oprette en funktion kaldet deleteById
:
/**
* Deletes a todo by ID
* @param id
* @returns integer (count of effect rows)
*/
deleteById: async ({ id }: Todo) => {
const result = await client.query(
`DELETE FROM ${TABLE.TODO} WHERE id = ?`,
[id],
);
// return count of rows updated
return result.affectedRows;
},
Her sender vi blot et id
som en param, og brug derefter slette MySQL-forespørgslen. Vi returnerer derefter det opdaterede antal rækker. Det opdaterede antal vil enten være 0 eller 1, fordi ID'et for hver opgave er unikt.
Gå derefter ind i dine controllers/todo.ts
fil og definere en deleteByTodoId
metode:
/**
* @description Delete todo by id
* @route DELETE todos/:id
*/
deleteTodoById: async (
{ params, response }: { params: { id: string }; response: any },
) => {
try {
const updatedRows = await TodoModel.deleteById({
id: Number(params.id),
});
response.status = 200;
response.body = {
success: true,
message: `Successfully updated ${updatedRows} row(s)`,
};
} catch (error) {
response.status = 400;
response.body = {
success: false,
message: `Error: ${error}`,
};
}
},
Dette er ret ligetil. Vi videregiver params.id
til vores TodoModel.deleteById
metode og returner antallet af rækker, der er opdateret med denne forespørgsel.
Hvis noget går galt, kastes en fejl i catch-blokken, som returnerer vores standardfejlsvar.
Lad os tjekke dette ud.
Sørg for, at din MySQL-instans kører. Skriv:
i din terminal$ deno run --allow-net server.ts
Gå til Postman og kør API-ruten for denne controller:
Med dette er vi færdige med vores Deno + Oak + MySQL tutorial.
Hele kildekoden er tilgængelig her:https://github.com/adelibr/deno-playground. Hvis du finder et problem, skal du bare fortælle mig det. Eller du er velkommen til at lave en pull-anmodning, så giver jeg dig kredit i lageret.
Hvis du fandt denne tutorial nyttig, så del den. Og som altid er jeg tilgængelig på Twitter under @adelibr. Jeg ville elske at høre dine tanker om det.