Lektion 17 — Forberedelse

I lektion 13 bor patientlisten i et array i server.js. I lektion 15 lagde I de samme patienter i en tabel i Neon. I dag forbinder vi de to: routen henter og gemmer i tabellen, og listen husker, når serveren genstarter. Forberedelsen er, hvordan koden deles i lag, hvordan Node taler med PostgreSQL, og et lille script, der henter fra din egen Neon-database.

Forberedelsen er ca. 70 minutter.

1. Lag i koden (~30 min)

Læs først: route og repository

I lektion 11 delte vi et system i tre lag: præsentation, applikation og data. Indtil nu har applikation og data siddet i samme fil: routen i server.js både besluttede, hvad der skulle svares, og holdt listen.

Når data flytter ind i en database, deler vi koden i to dele:

  • Routen taler HTTP. Den læser requestet, tjekker at felterne er der, og vælger statuskode: 200, 201, 400, 500.
  • Repositoryet taler SQL. Det er de få funktioner, der kender tabellen — fx hentPatienter() og opretPatient(cpr, navn). Det er det eneste sted i koden, hvor der står SQL.

Routen ved ikke, at der findes en tabel. Den kalder bare en funktion og får rækker tilbage. Repositoryet ved ikke, at der findes HTTP. Skifter I database, retter I ét sted. Skal I finde en SQL-fejl, ved I, hvor I skal kigge.

Et repository er ikke et bibliotek eller et framework. Det er en fil med funktioner, I selv skriver. I dag hedder den patients.js.

Databasen svarer ikke med det samme. Funktionerne i repositoryet er derfor async, og routen venter med await — samme mønster som fetch i lektion 7.

Derefter: to lectures på freeCodeCamp

  1. What Is SQL Injection, and What Are Some Ways to Prevent It? (modulet SQL and Bash). Fokusér på, hvordan brugerens input bliver til SQL, når det sættes ind med +, og på parameterized queries. Afsnittet om databaserettigheder kan du skimme.
  2. What are HTTP Response Status Codes? Fokusér på 200, 201, 400, 404 og 500. Dem bruger vi i dag. 1xx og 3xx kan du springe over.

Til sidst: forespørgsler i node-postgres

node-postgres: Queries

Læs de to første afsnit, Text only og Parameterized query. Spring Query config object over.

pg er den pakke, Node bruger til at tale med PostgreSQL. Her ser du parameterized queries i den syntaks, I skal skrive: SQL'en har pladsholdere — $1, $2 — og værdierne sendes ved siden af, i et array.

Eksemplerne bruger client.query. Vi bruger pool.query. Siden siger selv, at de virker ens.

2. Hent fra din egen database (~40 min)

Du skriver et kort script, der henter patienterne fra dit Neon-projekt lektion15. Arbejd i en ny mappe, l17-forberedelse. Ikke i gruppens projekt.

  1. Opret mappen, og installér pg:
npm init -y
npm install pg
  1. Find connection-stringen til dit eget projekt lektion15 i Neon: Connect → Copy snippet. Det er samme dialog som i lektion 15, øvelse 3.
  2. Lav filen .env i mappen i VS Code — ikke med > i PowerShell, det giver forkert tegnsæt. Én linje, og variablen skal hedde præcis DATABASE_URL. Ret sslmode=require til sslmode=verify-full i strengen — ellers skriver pg en lang sikkerhedsadvarsel:
DATABASE_URL=postgresql://neondb_owner:…@…neon.tech/neondb?sslmode=verify-full&channel_binding=require
  1. Lav filen .gitignore med to linjer, så hverken passwordet eller pakkerne kommer i git:
.env
node_modules/
  1. Lav hent.js:
const { Pool } = require("pg");

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

async function main() {
  const alle = await pool.query("SELECT cpr, navn FROM patients ORDER BY id");
  console.log(alle.rows);

  const max = await pool.query(
    "SELECT navn FROM patients WHERE cpr = $1",
    ["0107729995"]
  );
  console.log(max.rows);

  await pool.end();
}

main();
  1. Kør det:
node --env-file=.env hent.js

Du skal se de fem testpatienter som et array, og derefter [ { navn: 'Max Test Berggren' } ]. --env-file=.env lægger linjen fra .env i process.env, før scriptet starter.

  1. Ret CPR'en i $1-arrayet til en, der ikke findes. Kør igen. Hvad får du tilbage — en fejl eller et tomt array?

Når du er færdig

Du skal kunne forklare:

  • forskellen på en route og et repository, og hvilken af dem der kender SQL
  • hvorfor $1 og et array er bedre end at sætte CPR'en ind i SQL-teksten med +
  • hvad .env og --env-file gør, og hvorfor .env står i .gitignore
  • at pool.query returnerer et objekt, hvor rækkerne ligger i .rows

Og du skal have kørt hent.js mod din egen database.

At lægge repositoryet ind i gruppens server.js, POST og fejlkoder tager vi i timen.

Praktisk

  • Har du ikke patients i dit Neon-projekt lektion15, så kør CREATE TABLE og de fem INSERT fra lektion 15, øvelse 1 og 2 i SQL-editoren først.
  • ECONNREFUSED betyder, at pg ikke fik nogen connection-string og prøver din egen maskine. Du har glemt --env-file=.env, linjen hedder ikke præcis DATABASE_URL=, eller filen er lavet i PowerShell med >.
  • node: .env: not found: filen findes ikke i den mappe, du står i — eller den hedder .env.txt.
  • password authentication failed: strengen i .env er forkert. Kopiér den igen med Copy snippet.
  • Hav connection-stringen til gruppens database klar til timen. Den fik I i lektion 15, øvelse 3.
  • server.js skal blive stående, som den er fra lektion 13.