\documentclass{slides}
\addbibresource{slides.bib}

\title{Systèmes à objets répartis}
\subtitle{M1 Informatique, S8}
\date{Janvier 2026}
\titlegraphic{\flushright\includegraphics[height=1.3cm]{img/logos.png}\vspace{.5cm}}

\author{
    \texorpdfstring{
        \begin{table}[]
            \begin{flushleft}
                \begin{tabular}{ll}
                                         & Vincent Lannurien~\inst{1} \\
                                         & \url{vincent.lannurien@univ-brest.fr} \\
                \end{tabular}
            \end{flushleft}
        \end{table}
    }
    {
        Vincent Lannurien
    }
}

\institute{
    \texorpdfstring{
        \begin{table}[]
            \centering
            \begin{flushleft}
                \begin{tabular}{L}
                    \inst{1}~Lab-STICC, CNRS UMR 6285, Université de Bretagne Occidentale, Brest
                \end{tabular}
            \end{flushleft}
        \end{table}
    }
    {
        Lab-STICC, CNRS UMR 6285, Université de Bretagne Occidentale, Brest
    }
}

\begin{document}

\maketitle

\begin{frame}{Introduction}
    \begin{center}
        \url{http://info-demo-sor.univ-brest.fr:3000}
    \end{center}
\end{frame}

\begin{framefont}{\footnotesize}
\begin{frame}[t]{Plan du cours}
    \begin{columns}
        \column{0.6\textwidth}
        \tableofcontents%[hideallsubsections]

        \column{0.4\textwidth}
        \begin{center}
            \includegraphics[width=\columnwidth]{img/screenshot.png}
        \end{center}
    \end{columns}
\end{frame}
\end{framefont}

\section{Organisation de l'UE}

\begin{frame}{Organisation de l'UE -- Contenu}
    \begin{itemize}
        \item Objectifs :
        \begin{itemize}
            \item Développer une application suivant l'\textbf{architecture trois tiers}, s'appuyant sur des communications via \textbf{HTTP} et \textbf{WebSockets} ;
            \item Comprendre les mécanismes de l'\textbf{authentification} (avec ou sans état) d'un client auprès d'un serveur ;
            \item S'initier au \textbf{déploiement} d'une application répartie à l'aide d'un \textit{reverse proxy}.
        \end{itemize}
        \item Prérequis :
        \begin{itemize}
            \item Côté client : HTML/CSS
        \end{itemize}
        \item Méthode :
        \begin{itemize}
            \item Un peu de cours...
            \item Beaucoup de pratique !
        \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}{Organisation de l'UE -- Logistique}
    \begin{itemize}
        \item Volume horaire :
        \begin{itemize}
            \item CM : 3 séances de 2h (total : 6h)
            \item TP : 8 séances de 2h (total : 16h)
        \end{itemize}
        \item Contrôle des connaissances :
        \begin{itemize}
            \item TP noté (2h sur cette partie du cours)
            \item Examen final (2h en tout)
        \end{itemize}
    \end{itemize}
\end{frame}

\section{Introduction}

\begin{frame}{Contenu du cours}
    \begin{itemize}
        \item État et gestion de l'état
        \begin{itemize}
            \item Contrats
            \begin{itemize}
                \item Interfaces
                \item \textit{Data Transfer Objects}
            \end{itemize}
            \item Persistance
            \begin{itemize}
                \item Base de données
                \item Transactions
                % \item Cache
            \end{itemize}
        \end{itemize}
        \item Protocoles
        \begin{itemize}
            \item HTTP
            \begin{itemize}
                \item \textit{Status codes}
                \item \textit{CORS} (\textit{Cross-Origin Resource Sharing})
            \end{itemize}
            \item Authentification
            \begin{itemize}
                \item \textit{Tokens}
            \end{itemize}
        \end{itemize}
        \item Performances et profilage
        \begin{itemize}
            \item Instrumentation (serveur)
            \item Inspecteur (client)
            \item Injection de trafic
        \end{itemize}
        \item Déploiement
        \begin{itemize}
            \item SSL, certificats
            \item \textit{Reverse proxy}
        \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}{Technologies utilisées}
    \begin{itemize}
        \item Côté serveur :
        \begin{itemize}
            \item Runtime (Deno)
            \item Langage (TypeScript)
            \item Framework (Oak)
            \item Base de données (SQLite)
            % \item Cache (Redis)
        \end{itemize}
        \item Côté client :
        \begin{itemize}
            \item Bundler (Vite)
            \item Langage (TypeScript)
            \item Framework (React)
        \end{itemize}
        \item Communications :
        \begin{itemize}
            \item Requêtes HTTP
            \item WebSockets
        \end{itemize}
    \end{itemize}
\end{frame}

\section{Cas d'étude applicatif}

\begin{frame}{Présentation de l'application}
    \begin{block}{Description}
        L'application est une \textbf{plateforme de sondages en ligne}.
        
        Elle permet à des utilisateurs de \textbf{créer des sondages} et d'ajouter des \textbf{options de réponse}.
        
        Les participants peuvent \textbf{voter} pour une ou plusieurs options selon des règles définies par le créateur du sondage.
        
        L'application gère également l'\textbf{authentification} des utilisateurs et assure la \textbf{persistance} des données.
    \end{block}
\end{frame}

\begin{frame}{Présentation de l'application}
    \begin{alertblock}{Acteurs}
        Les acteurs de l'application sont les suivants :

        \begin{itemize}
            \item Utilisateur authentifié : peut créer des sondages, voter, et consulter les résultats ;
            \item Utilisateur invité : peut voter (si autorisé) et consulter les résultats (si autorisé) ;
            \item Administrateur : peut gérer les sondages et les utilisateurs.
        \end{itemize}
    \end{alertblock}
\end{frame}

\begin{frame}{Présentation de l'application}
    \begin{alertblock}{Fonctionnalités}
        Les principales fonctionnalités de l'application peuvent être résumées ainsi :

        \begin{itemize}
            \item Création de sondages avec : titre, description, date de création, date d'expiration, statut (actif/inactif) ;
            \item Ajout d'options à un sondage : texte descriptif ;
            \item Vote pour une option de sondage ;
            \item Consultation des résultats (nombre de votes par option) ;
            \item Gestion des utilisateurs (inscription, authentification).
        \end{itemize}
    \end{alertblock}
\end{frame}

\section{Architecture : modèle client/serveur}

\begin{frame}{Vue d'ensemble}
    \centering
    \includegraphics[width=.9\textwidth]{img/architecture.png}
\end{frame}

\begin{frame}{Monolithes ou microservices}
    \centering
    \includegraphics[width=.8\textwidth]{img/scaling-monolith.png}

    \addtocounter{footnote}{1}
    \footnotetext{\fullcite{fowlerMicroservices}}
\end{frame}

\begin{frame}{Monolithes ou microservices}
    \centering
    \includegraphics[width=.8\textwidth]{img/scaling-uservices.png}

    \footnotetext{\fullcite{fowlerMicroservices}}
\end{frame}

\section{JavaScript, TypeScript et \textit{runtime}}

\begin{frame}{JavaScript}
    \centering
    \includegraphics[width=.5\textwidth]{img/javascript-alert.png}
\end{frame}

\begin{frame}{JavaScript}
    \begin{columns}
        \column{.8\textwidth}
        \begin{itemize}
            \item 1995 : Brendan Eich développe en 10 jours un langage simple, interprété par le navigateur, pour dynamiser les pages web
            \item 1997 : première standardisation par ECMA (\textit{European Computer Manufacturers Association}) sous le nom ECMAScript
            \item 2005 : AJAX popularise les applications web dynamiques
            \item 2008 : Google publie la machine virtuelle V8 pour l'exécution du code JavaScript dans Chrome
            \item 2009 : Node.js étend l'utilisation de JavaScript au côté serveur
            \item 2010 -- 2014 : émergence des frameworks et d'un outillage moderne pour JavaScript (jQuery, AngularJS, etc.)
            \item 2015 : ECMAScript Edition 6 (ES6/ES2015) transforme le langage (modules, classes, \textit{arrow functions}, \textit{Promises})
        \end{itemize}

        \column{.2\textwidth}
        \includegraphics[width=\columnwidth]{img/js.png}
        \includegraphics[width=\columnwidth]{img/netscape.png}
        \includegraphics[width=\columnwidth]{img/nodejs.png}
    \end{columns}
\end{frame}

\begin{frame}
    \begin{columns}
        \column{.6\textwidth}
        \centering
        \includegraphics[width=.9\columnwidth]{img/jetbrains-ecosystem-2025-evolution.png}

        \column{.4\textwidth}
        \begin{itemize}
            \item \textit{"Among the most dramatic rises in real-world usage over the last five years is TypeScript."}
        \end{itemize}
    \end{columns}
\end{frame}

\begin{frame}
    \centering
    \includegraphics[width=.7\columnwidth]{img/jetbrains-ecosystem-2025-platforms.png}
    
    \addtocounter{footnote}{1}
    \footnotetext{\url{https://devecosystem-2025.jetbrains.com/tools-and-trends}}
\end{frame}

\begin{frame}{TypeScript}
    \begin{itemize}
        \item Conçu en 2012 par Anders Hejlsberg
        \item Open source, maintenu par Microsoft
        \item Ni interprété, ni compilé : langage \textbf{transpilé} vers JavaScript, \textit{superset} de JS
        \item Exécutable dans n'importe quel \textit{runtime} JS (navigateur, Node.js, etc.)
        \item Multi-paradigme : \textbf{fonctionnel}, générique, impératif, orienté objet
    \end{itemize}
\end{frame}

\begin{frame}{TypeScript}
    \begin{columns}
        \column{.8\textwidth}
        \begin{itemize}
            \item \textbf{Typage statique} : détecter les erreurs et incohérences à la compilation (donc avant l'exécution)
            \item \textbf{Interopérabilité} : typage \textit{progressif} (tout fichier JavaScript valide est un fichier TypeScript valide)
        \end{itemize}

        \column{.2\textwidth}
        \includegraphics[width=\columnwidth]{img/ts.png}
    \end{columns}

    Adoption par l'industrie :
    \begin{itemize}
        \item Slack~\footnote[frame]{\url{https://slack.engineering/typescript-at-slack/}} : migration du frontend React vers TS pour sécuriser les appels d'API et réduire les erreurs au runtime
        \item Airbnb~\footnote[frame]{\url{https://www.youtube.com/watch?v=P-J9Eg7hJwE}} : typage progressif du code JS pour réduire les coûts de maintenance
        \item Microsoft~\footnote[frame]{\url{https://www.git-tower.com/blog/developing-for-the-desktop-vscode}} : migration vers TS pour faciliter l'évolution de VS Code ($>$ 1M SLoC)
        \item Shopify~\footnote[frame]{\url{https://shopify.engineering/migrating-large-typescript-codebases-project-references}} : migration frontend et backend pour fiabiliser les fonctions critiques
    \end{itemize}
\end{frame}

\begin{frame}{TypeScript}
     \begin{itemize}
        \item Ressources :
        \begin{itemize}
            \item \textit{The TypeScript Handbook}~\footnote{\fullcite{HandbookTypeScriptHandbook}}
            \item \textit{The Concise TypeScript Book}~\footnote{\fullcite{poggialiConciseTypeScriptBook2026}}
            \item TypeScript TV~\footnote[frame]{\url{https://typescript.tv/}} (liste des codes d'erreur)
            \item TS Playground~\footnote[frame]{\url{https://www.typescriptlang.org/play/}} (environnement d'exécution en ligne)
        \end{itemize}
     \end{itemize}
\end{frame}

\subsection{Typage statique et dynamique}

\begin{frame}{TypeScript : typage du code JavaScript}
    Types de base disponibles dans TypeScript~\footnote{\url{https://www.typescriptlang.org/docs/handbook/2/everyday-types.html}} :
    \begin{itemize}
        \item \texttt{boolean}
        \item \texttt{number}
        \item \texttt{string}
        \item Tableaux (dynamiques) -- exemple : \texttt{string[]} ou \texttt{Array<string>}
        \item Tuples (taille fixe) -- exemple : \texttt{let x: [string, number]}
        \item \texttt{enum}
        \item \texttt{unknown} (type à préciser en le vérifiant à l'exécution)
        \item \texttt{any} (à éviter : toute valeur autorisée)
        \item \texttt{void} (absence de valeur)
        \item \texttt{null} (valeur vide) et \texttt{undefined} (valeur non définie)
    \end{itemize}
\end{frame}

\begin{frame}[fragile]{Exercice 1 : les pièges du typage dynamique}
    \begin{block}{Fonctions et paramètres}
        \begin{itemize}
            \item Écrire une fonction \texttt{addition(a, b)} qui additionne deux nombres.
            \item Tester la fonction avec les entrées suivantes :
        \end{itemize}
    \end{block}

    \begin{minted}{js}
addition(2, 3);      // attendu : 5
addition("2", 3);    // attendu : ?
addition(true, 3);   // attendu : ?
    \end{minted}

    \begin{alertblock}{Questions}
        \begin{enumerate}
            \item Que se passe-t-il pour les deux derniers cas ?
            \item Quels problèmes cela pose-t-il poser dans une application réelle ?
            \item Proposer une version TypeScript pour éviter ces erreurs \textit{à la compilation}.
        \end{enumerate}
    \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Exercice 1 : les pièges du typage dynamique}
    \begin{minted}{ts}
function addition2(a: number, b: number): number {
  return a + b;
}

console.log(addition2(2, 3));
// L'argument de type 'string' n'est pas attribuable au paramètre
// de type 'number'.ts(2345)
console.log(addition2("2", 3));
// L'argument de type 'boolean' n'est pas attribuable au paramètre
// de type 'number'.ts(2345)
console.log(addition2(true, 3));
    \end{minted}
\end{frame}

\begin{frame}[fragile]{JavaScript : POJO (\textit{Plain Old Java Object})}
    \begin{minted}{js}
const o = {
    "foo": "bar",
    "value": 42,
    other: true,
}

console.log(o.foo);
console.log(o["value"]);
console.log(o.other);
    \end{minted}
\end{frame}

\begin{frame}[fragile]{POJO et listes : \textit{Spread operator}}
    \begin{minted}{ts}
const o1 = { "abc": 123 };
// Ajout d'une nouvelle valeur dans `o1`
o1["def"] = 456;
// Nouvel objet avec copie des valeurs de `o1`
const o2 = { ...o1, "ghi": 789 };
    \end{minted}

    \vspace{.5cm}

    \begin{minted}{ts}
const l1 = [123];
// Ajout d'une nouvelle valeur à la fin de `l1`
l1.append(456);
// Nouvelle liste avec copies des valeurs de `l1`
const l2 = [...l1, 789];
    \end{minted}
\end{frame}

\begin{frame}[fragile]{TypeScript : typer les objets avec \texttt{Record}}
    \begin{minted}{js}
const o: Record<string, string | number | boolean> = {
    "foo": "bar",
    "value": 42,
    other: true,
}

console.log(o.foo);
console.log(o["value"]);
console.log(o.other);
console.log(o.blabla); // undefined
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Typage, interfaces et classes}
    \begin{columns}
        \column{.5\textwidth}
        \begin{minted}{ts}
// Définition
interface Bidule {
    truc: string;
    machin: number;
    toto?: boolean;
}

// Instanciation
const b: Bidule = {
    truc: "bidule",
    machin: 42,
};
        \end{minted}

        \column{.5\textwidth}
        \begin{minted}{ts}
// Définition
class Bidule {
    constructor(
        public truc: string,
        public machin: number,
        public toto?: boolean,
    ) {}
}

// Instanciation
const b: Bidule = new Bidule(
    "bidule", 42
);
        \end{minted}
    \end{columns}
\end{frame}

\begin{frame}[fragile]{Exercice 2 : interfaces et contrats}
    \begin{block}{Typage des objets}
        \begin{itemize}
            \item Écrire une fonction \texttt{afficherUtilisateur(u)} qui prend un objet représentant un utilisateur et affiche son nom et son âge.
            \item Tester la fonction avec les entrées suivantes :
        \end{itemize}
    \end{block}

    \begin{minted}{js}
afficherUtilisateur({ nom: "Alice", age: 25 });
afficherUtilisateur({ nom: "Bob" });
    \end{minted}

    \begin{alertblock}{Questions}
        \begin{enumerate}
            \item Que se passe-t-il pour le second cas ?
            \item Comment TypeScript peut-il garantir la présence des propriétés attendues ?
            \item Proposer une solution avec TypeScript.
        \end{enumerate}
    \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Exercice 2 : interfaces et contrats}
    \begin{minted}{ts}
interface Utilisateur {
    nom: string;
    age: number;
}

function afficherUtilisateur(u: Utilisateur): void {
    console.log(`${u.nom} a ${u.age} ans`);
}

afficherUtilisateur({ nom: "Alice", age: 25 });
// L'argument de type '{ nom: string; }' n'est pas attribuable
// au paramètre de type 'Utilisateur'.
//  La propriété 'age' est absente du type '{ nom: string; }'
//  mais obligatoire dans le type 'Utilisateur'.ts(2345)
afficherUtilisateur({ nom: "Bob" });
    \end{minted}
\end{frame}

\begin{frame}{Typage, interfaces et classes}
    \begin{itemize}
        \item Types \textbf{effacés} à la compilation
        \begin{itemize}
            \item Pas d'impact sur les performances (compromis : temps de compilation vs temps d'exécution)
            \item Une erreur de typage n'empêche pas la compilation vers JavaScript
        \end{itemize}
        \item Corollaire : il n'est pas possible de vérifier les types TypeScript \textbf{lors de l'exécution} du programme...
        \item ... sauf pour les types primitifs de JavaScript !
    \end{itemize}
\end{frame}

\begin{frame}[fragile]{Typage, interfaces et classes}
    \begin{minted}{ts}
// type union : soit number, soit string
const fn = (x: number | string) => {
    // typeof type guard
    if (typeof x === 'number') { 
        return x + 1;
    }
    
    return -1;
};
    \end{minted}

    \begin{minted}{ts}
// type union : soit string, soit null
const toUpperCase = (name: string | null) => {
    // truthiness narrowing
    if (name) {
        return name.toUpperCase();
    } else {
        return null; 
    }
};
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 3 : types au \textit{runtime}}
    \begin{minted}[fontsize=\footnotesize]{ts}
interface Animal {
  name: string;
}
interface Dog extends Animal {
  bark: () => void;
}
interface Cat extends Animal {
  meow: () => void;
}
const makeNoise = (animal: Animal) => {
  if (animal instanceof Dog) {
    // 'Dog' fait référence à un type mais s'utilise en tant que valeur ici.ts(2693)
    animal.bark();
  } else {
    animal.meow();
  }
};
    \end{minted}

    \begin{alertblock}{Questions}
        \begin{enumerate}
            \item Que signifie l'erreur levée par le compilateur ?
            \item Comment peut-on vérifier la nature de l'objet \texttt{animal} au \textit{runtime} ?
        \end{enumerate}
    \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Exercice 3 : types au \textit{runtime}}
    \begin{minted}{ts}
interface Dog {
  kind: "dog"; // Tagged union
  bark: () => void;
}

interface Cat {
  kind: "cat"; // Tagged union
  meow: () => void;
}

type Animal = Dog | Cat; // Union type

const makeNoise = (animal: Animal) => {
  if (animal.kind === "dog") animal.bark();
  else animal.meow();
};
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 3 : types au \textit{runtime}}
    \begin{minted}{ts}
class Dog {
  constructor(public name: string, public bark: () => void) {}
}

class Cat {
  constructor(public name: string, public meow: () => void) {}
}

type Animal = Dog | Cat; // Union type

const makeNoise = (animal: Animal) => {
  if (animal instanceof Dog) animal.bark();
  else animal.meow();
};
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 3 : types au \textit{runtime}}
    \begin{minted}[fontsize=\footnotesize]{ts}
interface Dog {
  kind: "dog"; // Tagged union
  bark: () => void;
}
interface Cat {
  kind: "cat"; // Tagged union
  meow: () => void;
}
type Animal = Dog | Cat;
const makeNoise = (animal: Animal) => {
  if (animal.kind === "dog") animal.bark();
  else animal.meow();
};
const dog: Dog = { 
  kind: "dog",
  bark: () => console.log("bark")
};
makeNoise(dog);
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Type Guards : \textit{compile time} et \textit{run time}}
    \begin{itemize}
        \item \textit{Type narrowing} : \textit{compile time}
        \item \textit{Type assertion} : \textit{run time}
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
interface Something { id: string };

export function isSomething(obj: unknown): obj is Something {
  return !!obj
    && typeof obj === "object"
    && "id" in obj && typeof obj.id === "string";
}

const bla = { id: "blabla" };

    \end{minted}
\end{frame}

\subsection{Généricité}

\begin{frame}[fragile]{Généricité}
    \begin{itemize}
        \item \texttt{SomeContainer<T extends SomeData>}
        \begin{itemize}
            \item \texttt{T} est un type paramètre contraint à hériter ou implémenter \texttt{SomeData}
            \item Permet de réutiliser le même conteneur pour différents types de données
        \end{itemize}
        \item Objectifs :
        \begin{itemize}
            \item Définir des structures et fonctions abstraites sur un type variable
            \item Maintenir les contraintes de type
        \end{itemize}
    \end{itemize}

    \begin{columns}
        \column{.6\textwidth}
        \begin{minted}[fontsize=\footnotesize]{ts}
interface SomeData {
  id: string;
}

interface SpecializedData extends SomeData {
  name: string;
  value: number;
}

interface SomeContainer<T extends SomeData> {
  data: T;
}
        \end{minted}

        \column{.4\textwidth}
        \begin{minted}[fontsize=\footnotesize]{ts}
const c: SomeContainer<
  SpecializedData
> = {
  data: {
    id: "foo",
    name: "Foo Bar",
    value: 42,
  },
};
        \end{minted}
    \end{columns}
\end{frame}

\subsection{Gestion des erreurs}

\begin{frame}[fragile]{Gestion des erreurs : exceptions}
    \begin{minted}{ts}
const randInt = Math.floor(Math.random() * 3) + 1; // [1, 3]
const error = 
  randInt === 1 ? new TypeError() :
  randInt === 2 ? new RangeError() :
  new EvalError();

try {
  throw error;
} catch {
  // handle error
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Gestion des erreurs : exceptions}
    \begin{minted}{ts}
const randInt = Math.floor(Math.random() * 3) + 1; // [1, 3]
const error = 
    randInt === 1 ? new TypeError() :
    randInt === 2 ? new RangeError() :
    new EvalError();

try {
  throw error;
} catch (e) {
  if (e instanceof TypeError) {
    // handle TypeError
  } else if (e instanceof RangeError) {
    // handle RangeError
  } else if (e instanceof EvalError) {
    // handle EvalError
  }
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Gestion des erreurs : exceptions}
    \begin{minted}{ts}
try {
  const file = await Deno.open("example.txt", { read: true });

  for await (const chunk of Deno.iter(file)) {
      console.log(new TextDecoder().decode(chunk));
  }
} catch (e) {
  console.error("Error reading file:", e);
} finally {
  // always close the file handle
  if (file) {
    file.close();
  }
}
    \end{minted}
\end{frame}

\subsection{Asynchronisme et parallélisme}

\begin{frame}{Programmation asynchrone}
    Comment manipuler des données...
    \begin{itemize}
        \item que l'on n'a pas encore ?
        \item que l'on n'aura peut-être jamais ?
        \item qui l'on obtient dans un temps variable ?
    \end{itemize}

    Par exemple...
    \begin{itemize}
        \item le résultat d'une requête à une API ?
        \item le contenu d'un fichier volumineux sur le disque ?
        \item le résultat d'une requête à une base de données ?
    \end{itemize}
\end{frame}

\begin{frame}{Programmation asynchrone}
    \centering

    \includegraphics[width=.9\textwidth]{img/async.png}
\end{frame}

\begin{frame}{Programmation asynchrone}
    \begin{itemize}
        \item API : \textbf{Promises}
        \begin{itemize}
            \item Traiter des opérations \textbf{asynchrones}
            \item Une Promise \textit{encapsule un résultat futur}
            \item Elle est associée à des \textit{callbacks} qui seront exécutés à l'obtention de ce résultat
            \item Elle peut être \textit{résolue} (réussite) ou \textit{rejetée} (échec)
        \end{itemize}
    \end{itemize}

    \centering
    \includegraphics[width=.8\textwidth]{img/promises.png}

    \addtocounter{footnote}{1}
    \footnotetext{\url{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise}}
\end{frame}

\begin{frame}[fragile]{Programmation asynchrone}
    \begin{minted}[fontsize=\footnotesize]{ts}
function repeatMaybe(repeat: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const maybe: number = randomIntegerBetween(0, 1);

    if (!maybe) {
        reject("Nope");
        return;
    }

    setTimeout(() => {
        resolve(repeat);
    }, 1000);
  });
}

const blabla = repeatMaybe("bla").then((result: string) => {
    console.log(result);
}).catch((error: string) => {
    console.log(error)
});
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Programmation asynchrone}
    \begin{columns}
        \column{.5\textwidth}
        \begin{itemize}
            \item API : \texttt{async}/\texttt{await}
            \begin{itemize}
                \item Sucre syntaxique pour "aplatir" du code asynchrone
                \item \texttt{async} définit une fonction asynchrone
                \item \texttt{await} met l'exécution du programme en pause dans l'attente d'un résultat
            \end{itemize}
        \end{itemize}

        \column{.5\textwidth}
        \centering
        \includegraphics[width=.7\columnwidth]{img/async-joke.jpg}
    \end{columns}

    \vspace{1cm}

    \begin{columns}
        \column{.5\textwidth}
        \begin{minted}[fontsize=\footnotesize]{ts}
asyncFunction().then((res) => {
    console.log(res);
}).catch((err) => {
    console.log(err);
});
        \end{minted}

        \column{.5\textwidth}
        \begin{minted}[fontsize=\footnotesize]{ts}
try {
    const res = await asyncFunction();
    console.log(res); // "bla"
} catch (err) {
    console.log(err); // "Nope"
}
        \end{minted}
    \end{columns}
\end{frame}

\begin{frame}[fragile]{Programmation asynchrone}
    \begin{minted}[fontsize=\footnotesize]{ts}
function repeatMaybe(repeat: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const maybe: number = randomIntegerBetween(0, 1);

    if (!maybe) {
        reject("Nope");
        return;
    }

    setTimeout(() => {
        resolve(repeat);
    }, 1000);
  });
}

try {
    const blabla = await repeatMaybe("bla");
    console.log(blabla); // "bla"
} catch (error) {
    console.log(error); // "Nope"
}
    \end{minted}
\end{frame}

\begin{frame}{Programmation parallèle}
    \begin{itemize}
        \item \texttt{Promise.all}
        \begin{itemize}
            \item exécute toutes les Promises en \textbf{parallèle}
            \item résout quand toutes les Promises ont \textbf{réussi}
            \item rejette immédiatement si \textbf{une seule échoue}
            \item retourne un tableau des résultats dans l'ordre initial des Promises
        \end{itemize}
        
        \item \texttt{Promise.allSettled}
        \item \begin{itemize}
            \item exécute toutes les Promises en \textbf{parallèle}
            \item résout quand toutes les Promises sont terminées, \textbf{succès ou échec}
            \item ne rejette \textbf{jamais}
            \item retourne un tableau d'objets de type :
            \begin{itemize}
                \item \texttt{{status: 'fulfilled' | 'rejected', value | reason}}
            \end{itemize}
        \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}[fragile]{Exercice 4 : programmation asynchrone}
    \begin{block}{Manipuler l'API Promise}
        \begin{itemize}
            \item Écrire une fonction \texttt{readTextFileIfExists(path)} qui lit un fichier s'il existe et retourne son contenu si le fichier n'est pas vide :
        \end{itemize}
    \end{block}

    \begin{minted}{js}
readTextFileIfExists("data.txt")
  .then(text => console.log("File contents:", text))
  .catch(err => console.error("I/O error:", err.message));
    \end{minted}

    \begin{alertblock}{Questions}
        \begin{enumerate}
            \item Quelle est la signature de cette fonction en TypeScript ?
            \item Comment utiliser cette fonction avec \texttt{await} ?
            \item Comment utiliser cette fonction sur une liste de fichiers ?
            \item Comment paralléliser la lecture des fichiers de la liste ?
        \end{enumerate}
    \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Exercice 4 : programmation asynchrone}
    \begin{minted}[fontsize=\footnotesize]{js}
function readTextFileIfExists(path) {
  return new Promise((resolve, reject) => {
    if (!path) {
      reject(new Error("No file path provided"));
      return;
    }

    readFile(path, "utf8")
      .then(data => {
        if (data.length === 0) {
          reject(new Error("File is empty")); // explicit failure
        } else {
          resolve(data); // successful read
        }
      })
      .catch(err => reject(err)); // I/O error
  });
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 4 : programmation asynchrone}
    \begin{minted}{js}
try {
  const text = await readTextFileIfExists("data.txt");
  console.log("File contents:", text);
} catch (err) {
  console.error("I/O error:", err.message);
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 4 : programmation asynchrone}
    \begin{minted}{js}
const files = ["file1.txt", "file2.txt", "file3.txt"];

for (const file of files) {
  try {
    const text = await readTextFileIfExists(file);
    console.log("File contents:", text);
  } catch (err) {
    console.error("I/O error:", err.message);
    continue;
  }
}
    \end{minted}

    \vspace{.5cm}

    \begin{block}{\emoji{thinking}}
        Temps d'exécution total = ?
    \end{block}
\end{frame}

\begin{frame}[fragile]{Exercice 4 : programmation asynchrone}
    \begin{minted}{js}
const files = ["does_not_exist.txt", "file2.txt", "file3.txt"];

const contents = await Promise.all(
  files.map(readTextFileIfExists)
);
try {
    contents.forEach((text, i) => {
      console.log("File contents:", text);
    });
} catch (err) {
    console.error("I/O error:", err.message);
}
    \end{minted}

    \vspace{.5cm}

    \begin{block}{\emoji{thinking}}
        Temps d'exécution total = ?
    \end{block}
\end{frame}

\begin{frame}[fragile]{Exercice 4 : programmation asynchrone}
    \begin{minted}{js}
const files = ["does_not_exist.txt", "file2.txt", "file3.txt"];

const contents = await Promise.allSettled(
  files.map(readTextFileIfExists)
);
contents.forEach((result, i) => {
  if (result.status === "fulfilled") {
      console.log("File contents:", result.value);
  } else if (result.status === "rejected") {
      console.error("I/O error:", result.reason);
  }
});
    \end{minted}

    \vspace{.5cm}

    \begin{block}{\emoji{thinking}}
        Temps d'exécution total = ?
    \end{block}
\end{frame}

\subsection{Environnement d'exécution}

\begin{frame}{Exécution : machine virtuelle}
    \begin{itemize}
        \item JavaScript : langage interprété dans une VM
        \item Langage permet d'exprimer des instructions \textbf{asynchrones}
        \item Runtime \textbf{synchrone} : boucle d'événements (pas de coroutines, pas de threads~\footnote{Sauf \textit{workers}, voir~\url{https://developer.mozilla.org/en-US/docs/Glossary/Thread}})
    \end{itemize}

    \centering
    \includegraphics[width=\textwidth]{img/js-event-loop.png}
\end{frame}

\begin{frame}{Runtime : Deno}
    \begin{columns}
        \column{.8\textwidth}
        \begin{itemize}
            \item Runtime pour exécuter du code JavaScript en-dehors du navigateur
            \item Basé sur le moteur V8 (comme Node.js)
            \item Créé en 2018 par Ryan Dahl, développeur de Node.js~\footnote[frame]{\url{https://www.youtube.com/watch?v=M3BM9TB-8yA}}
            \item Points forts :
            \begin{itemize}
                \item \textit{Sandbox} : permissions explicites (lecture/écriture, accès au réseau, etc.)
                \item Exécute du code TypeScript sans outillage supplémentaire
                \item Inclut un formateur, un \textit{linter}, une plateforme de test, un profileur
            \end{itemize}
        \end{itemize}

        \column{.2\textwidth}
        \includegraphics[width=\columnwidth]{img/deno.png}
    \end{columns}
\end{frame}

\begin{frame}{Sécurité, permissions}
    \begin{itemize}
        \item \textit{Supply-chain attack} : introduction de vulnérabilités dans un logiciel \textit{via} compromission d'une ou plusieurs de ses dépendances
        \item Exemple : \textit{Shai Hulud}, novembre 2025~\footnote[frame]{\url{https://www.cert.ssi.gouv.fr/actualite/CERTFR-2025-ACT-051/}}, 700 paquets compromis sur NPM
        \begin{itemize}
            \item récupération de différents secrets présents sur la machine compromise [...] ;
            \item exfiltration des secrets ;
            \item réplication par l'infection de paquets NPM ;
            \item suppression de données utilisateurs ;
            \item mise en place de persistance.
        \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}{Gestion des dépendances}
    \begin{columns}
        \column{.8\textwidth}
        Outils et registres :
        \begin{itemize}
            \item \texttt{npmjs.org} : registre historique des paquets JavaScript
            \begin{itemize}
                \item Gestionnaires de paquets : \textbf{npm / yarn}
            \end{itemize}
            \item \texttt{jsr.org} : "nouveau" registre, orienté TypeScript
            \begin{itemize}
                \item Gestionnaire de paquets : \textbf{jsr}, intégré dans Deno
            \end{itemize}
        \end{itemize}

        \vspace{.5cm}

        Modules et imports :
        \begin{itemize}
            \item \textbf{CommonJS (CJS)} : compatibilité historique
                \begin{itemize}
                    \item Import : \texttt{const fs = require('fs');}
                    \item Export : \texttt{module.exports = \{ readFile \};}
                    \item Chargement synchrone
                \end{itemize}
            \item \textbf{ECMAScript Modules (ESM)} : standard moderne
                \begin{itemize}
                    \item Import : \texttt{import \{ readFile \} from 'fs/promises';}
                    \item Export : \texttt{export const myFunc = () => \{...\};}
                    \item Chargement statique ou dynamique (asynchrone)
                \end{itemize}
        \end{itemize}

        \column{.2\textwidth}
        \includegraphics[width=\columnwidth]{img/npm.png}
        \includegraphics[width=\columnwidth]{img/jsr.png}
    \end{columns}
\end{frame}

\section{Serveur web}

\begin{frame}{\textit{It's a series of tubes...}}
    \centering
    \includegraphics[width=.6\textwidth]{img/series-of-tubes.png}
\end{frame}

\begin{frame}{Résumé de la méthode en TP}
    \begin{enumerate}
        \item La base de données retourne des \textbf{enregistrements} : ce sont des données arbitraires
        \begin{itemize}
            \item Élément unique : \texttt{Record<string, SQLOutputValue> | undefined}
            \begin{itemize}
                \item Peut être \texttt{undefined} si introuvable !
            \end{itemize}
            \item Liste : \texttt{Record<string, SQLOutputValue>[]}
            \begin{itemize}
                \item Peut être vide !
            \end{itemize}
        \end{itemize}
        \item On doit \textit{vérifier le typage des données} pour que l'objet se conforme à son \textit{interface base de données} (\texttt{PollRow}, ...)
        \item On peut alors \textit{convertir l'enregistrement} en objet de notre \textit{API} (\texttt{Poll}, ...)
        \item L'objet peut être retourné au client de manière \textit{sûre}
        \begin{itemize}
            \item \textit{Compile time} : typage statique des données dans l'application client
            \item \textit{Run time} : pas d'erreur à l'exécution pour l'utilisateur
        \end{itemize}
    \end{enumerate}
\end{frame}

\begin{frame}
    \centering
    \includegraphics[width=\textwidth]{img/type-guard-1.png}
\end{frame}

\begin{frame}[noframenumbering]
    \centering
    \includegraphics[width=\textwidth]{img/type-guard-2.png}
\end{frame}

\begin{frame}[noframenumbering]
    \centering
    \includegraphics[width=\textwidth]{img/type-guard-3.png}
\end{frame}

\begin{frame}[noframenumbering]
    \centering
    \includegraphics[width=\textwidth]{img/type-guard-4.png}
\end{frame}

\begin{frame}[noframenumbering]
    \centering
    \includegraphics[width=\textwidth]{img/type-guard-5.png}
\end{frame}

\begin{frame}[fragile]{Résumé de la méthode en TP}
    \begin{columns}
        \column{.5\textwidth}
        \begin{minted}{ts}
export interface PollRow {
  id: string;
  title: string;
  description: string | null;
  user_id: string | null;
  created_at: string;
  expires_at: string | null;
  is_active: number;
  [key: string]: SQLOutputValue;
}
        \end{minted}

        \column{.5\textwidth}
        \begin{minted}{ts}
export interface Poll {
  id: string;
  title: string;
  description?: string;
  options: PollOption[];
  userId?: string;
  createdAt: string;
  expiresAt?: string;
  isActive: boolean;
}
        \end{minted}
    \end{columns}
\end{frame}

\begin{frame}[fragile]{Résumé de la méthode en TP}
    \begin{minted}[fontsize=\small]{ts}
export function isPollRow(
  obj: Record<string, SQLOutputValue>
): obj is PollRow {
  return !!obj &&
    typeof obj === "object" &&
    "id" in obj && typeof obj.id === "string" &&
    "title" in obj && typeof obj.title === "string" &&
    "description" in obj &&
    (typeof obj.description === "string" || obj.description === null) &&
    "user_id" in obj &&
    (typeof obj.user_id === "string" || obj.user_id === null) &&
    "created_at" in obj && typeof obj.created_at === "string" &&
    "expires_at" in obj &&
    (typeof obj.expires_at === "string" || obj.expires_at === null) &&
    "is_active" in obj && typeof obj.is_active === "number";
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Résumé de la méthode en TP}
    \begin{minted}{ts}
export function pollRowToApi(
  row: PollRow,
  optionRows: PollOptionRow[],
): Poll {
  return {
    id: row.id,
    title: row.title,
    description: row.description ?? undefined,
    createdAt: row.created_at,
    expiresAt: row.expires_at ?? undefined,
    isActive: row.is_active === 1,
    options: optionRows.map(pollOptionRowToApi),
  };
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Résumé de la méthode en TP}
    \begin{minted}{ts}
export function pollApiToRow(
  poll: Poll
): [PollRow, PollOptionRow[]] {
  return [
    {
      id: poll.id,
      title: poll.title,
      description: poll.description ?? null,
      user_id: poll.userId ?? null,
      created_at: poll.createdAt,
      expires_at: poll.expiresAt ?? null,
      is_active: Number(poll.isActive),
    },
    poll.options.map((pollOption) => pollOptionApiToRow(
      poll.id, pollOption
    )),
  ];
}
    \end{minted}
\end{frame}

\subsection{Protocole HTTP}

\begin{frame}{HTTP}
    \begin{columns}
        \column{.6\textwidth}
        \begin{itemize}
            \item \textit{Hypertext Transfer Protocol} : à l'origine, sert à partager des pages web reliées entre elles par des liens
            \item Inventé au CERN~\footnote[frame]{Initialement \textit{Conseil européen pour la recherche nucléaire}, plus grand centre de recherche au monde en physique des particules} par un chercheur britannique, Tim Berners-Lee, entre 1989 et 1991
            \item 1997 : standardisation de HTTP/1.1 :
            \begin{itemize}
                \item Apparition de l'en-tête \texttt{Host}, permettant d'héberger plusieurs domaines sur la même adresse IP, donc la colocation de serveurs web
            \end{itemize}
        \end{itemize}
        
        \begin{center}
            \includegraphics[width=.4\columnwidth]{img/tbl.jpg}
        \end{center}

        \column{.4\textwidth}
        \includegraphics[width=\columnwidth]{img/osi-model.png}
    \end{columns}
\end{frame}

\begin{frame}{HTTP : requêtes et réponses}
    \centering
    \includegraphics[width=\textwidth]{img/http-message.png}
\end{frame}

\begin{frame}{HTTP : méthodes}
    Méthodes principales pour les requêtes HTTP~\footnote[frame]{\url{https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods}}, aussi appelées \textit{verbes} :

    \begin{itemize}
        \item \texttt{GET} : demande d'une ressource
        \item \texttt{POST} : envoi de données du \textit{corps} de la requête vers une ressource
        \item \texttt{PUT} : remplacement d'une ressource par le \textit{corps} de la requête
        \item \texttt{DELETE} : suppression d'une ressource
    \end{itemize}
\end{frame}

\begin{frame}{HTTP : codes de réponse}
    \begin{itemize}
        \item \texttt{100} à \texttt{199} : réponses informatives
        \begin{itemize}
            \item \texttt{101 Switching Protocols}
        \end{itemize}
        \item \texttt{200} à \texttt{299} : réponses de succès
        \begin{itemize}
            \item \texttt{200 OK}
        \end{itemize}
        \item \texttt{300} à \texttt{399} : réponses de redirection
        \begin{itemize}
            \item \texttt{301 Moved Permanently}
        \end{itemize}
        \item \texttt{400} à \texttt{499} : erreurs du client
        \begin{itemize}
            \item \texttt{401 Unauthorized}
        \end{itemize}
        \item \texttt{500} à \texttt{599} : erreurs du serveur
        \begin{itemize}
            \item \texttt{500 Internal Server Error}
        \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}{HTTP : architecture REST}
    \begin{columns}
        \column{.7\textwidth}
        \begin{itemize}
            \item \textit{REpresentational State Transfer}~\cite{fielding2000architectural} : défini par Roy Fielding en 2000, conçu pendant son doctorat (1996 - 1999)
            \item Modèle d'architecture logicielle pour applications réseau
            \item Manipuler des ressources distantes via des représentations textuelles
            \item Opérations uniformes, prédéfinies, et \textbf{sans état}
        \end{itemize}

        \column{.3\textwidth}
        \includegraphics[width=\columnwidth]{img/roy_fielding_OSCON_2008.jpg}
    \end{columns}
\end{frame}

\begin{frame}
    \begin{center}
        \includegraphics[width=.8\textwidth]{img/rest-wikipedia.png}
    \end{center}
\end{frame}

\begin{frame}[fragile]{Exercice 5 : un serveur HTTP minimal avec TypeScript}
    \begin{block}{Lire et écrire sur un socket TCP}
        Ci-dessous, la boucle principale pour ouvrir et écouter sur un socket TCP avec Deno. Dès la connexion d'un \textbf{client}, on passe le socket à la fonction \texttt{handleConn}.
    \end{block}

    \begin{minted}{ts}
// TCP socket
const listener = Deno.listen({ port: 8080 });
// Strings <-> Bytes
const decoder = new TextDecoder();
const encoder = new TextEncoder();
// Listen loop
for await (const conn of listener) {
  handleConn(conn);
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 5 : un serveur HTTP minimal avec TypeScript}
    \begin{block}{Lire et écrire sur un socket TCP}
        Ci-dessous, la fonction \texttt{handleConn} par laquelle chaque \textbf{requête} en provenance d'un \textbf{client} est traitée. Le serveur reçoit un \textbf{tableau d'octets} ; on le convertit en une chaîne de caractères dans \texttt{rawRequest}.
    \end{block}

    \begin{minted}{ts}
async function handleConn(conn: Deno.Conn) {
  const buf = new Uint8Array(1024);
  const bytes = await conn.read(buf);
  if (bytes === null) {
    conn.close();
    return;
  }

  const rawRequest = decoder.decode(buf.subarray(0, bytes));
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 5 : un serveur HTTP minimal avec TypeScript}
    \begin{minted}{sh}
curl -X POST http://localhost:8080 \
     -H "Content-Type: text/plain" \
     -d "hello world"
    \end{minted}

    \vspace{1cm}

    \begin{columns}
        \column{.4\textwidth}
        \begin{minted}{text}
POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/8.14.1
Accept: */*
Content-Type: text/plain
Content-Length: 11

hello world
        \end{minted}

        \column{.6\textwidth}
        \begin{alertblock}{Questions}
            \begin{enumerate}
                \item Quels sont les champs à inclure dans la réponse que l'on va retourner au client ?
                \item Compléter la fonction \texttt{handleConn} pour signifier une réponse OK comportant du texte au format JSON.
                \item Comment va-t-on gérer l'horodatage ?
            \end{enumerate}
        \end{alertblock}
    \end{columns}
\end{frame}

\subsection{Mise en œuvre}

\begin{frame}{Framework pour serveur HTTP : Oak}
    \begin{columns}
        \column{.8\textwidth}
        \begin{itemize}
            \item Inspiré par Express.js, initialement développé pour Deno
            \item Framework \textit{middleware} : un logiciel qui s'intercale entre la requête d'un client et la réponse d'un serveur
            \item \textbf{Contexte} $=$ \textbf{Requête} $+$ \textbf{Réponse}
            \item Mécanisme principal : le \textbf{routage}
            \begin{itemize}
                \item Pour un point d'entrée donné, appliquer telle fonction, retourner telle valeur
                \item Requête : \texttt{GET http://blabla.com/item/123}
                \item Méthode : \texttt{GET}
                \item Route : \texttt{/item/:itemId}
                \item Fonction : \texttt{getItem(id)}
                \item Réponse : \texttt{\{ id: 123, value: "..." \}}
            \end{itemize}
        \end{itemize}

        \column{.2\textwidth}
        \includegraphics[width=\columnwidth]{img/oak.png}
    \end{columns}
\end{frame}

\begin{frame}[fragile]{Framework pour serveur HTTP : Oak}
    \begin{minted}[fontsize=\footnotesize]{ts}
// Configuration
const BASE_URL = "http://localhost:8000";
// Initialisation
const app = new Application();
const router = new Router();
// Middlewares
app.use(router.routes()); // Encore faut-il définir des routes ! ...
app.use(router.allowedMethods());
// Événements
app.addEventListener(
  "listen", () => console.log(`Server listening on ${BASE_URL}`),
);
app.addEventListener(
  "error", (e) => console.log(`Uncaught error: ${e.message}`),
);
// Boucle principale
if (import.meta.main) {
  await app.listen({ hostname: "localhost", port: 8000 });
}
// Export
export { app };
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : paramètres de la requête}
    \begin{itemize}
        \item L'utilisateur envoie une requête \texttt{GET}
        \item Adresse : \texttt{http://localhost:8000/polls/abcd}
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
router.get("/:pollId", (ctx) => {
  const pollId = ctx.params.pollId; // abcd
});
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : paramètres de la requête}
    \begin{itemize}
        \item L'utilisateur envoie une requête \texttt{POST}
        \item Corps de la requête : un objet JSON
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{json}
{ "foo": "bar" }
    \end{minted}

    \begin{itemize}
        \item Adresse : \texttt{http://localhost:8000/polls}
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
router.post("/polls", async (ctx) => {
  const createPollRequest = await ctx.request.body.json();
  // { "foo": "bar" }
});
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : réponse à la requête}
    \begin{minted}{ts}
export interface APISuccess<T> {
  success: true;
  data: T;
  error?: never;
}

export interface APIFailure {
  success: false;
  data?: never;
  error: APIError;
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : réponse à la requête}
    \begin{minted}{ts}
export enum APIErrorCode {
  NOT_FOUND = "NOT_FOUND",
  SERVER_ERROR = "SERVER_ERROR",
  TIMEOUT = "TIMEOUT",
  UNAUTHORIZED = "UNAUTHORIZED",
  VALIDATION_ERROR = "VALIDATION_ERROR",
}

export interface APIError {
  code: APIErrorCode;
  message: string;
}
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : réponse à la requête}
    \begin{itemize}
        \item Et finalement, le type de \textbf{toute} réponse de l'API...
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
export type APIResponse<T> = APISuccess<T> | APIFailure;
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : réponse à la requête}
    \begin{itemize}
        \item Si l'entité demandée est trouvée :
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
const responseBody: APIResponse<Poll> = {
  success: true,
  data: poll,
};

// Oak donne passe implicitement le code HTTP OK
ctx.response.body = responseBody;
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : réponse à la requête}
    \begin{itemize}
        \item Si l'entité demandée est introuvable :
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
const responseBody: APIResponse<Poll> = {
  success: false,
  error: {
    code: APIErrorCode.NOT_FOUND,
    message: "Poll not found",
  },
};

ctx.response.status = 404;
ctx.response.body = responseBody;
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Routage avec Oak : réponse à la requête}
    \begin{itemize}
        \item Le serveur rencontre une erreur :
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
const responseBody: APIResponse<Poll> = {
  success: false,
  error: {
    code: APIErrorCode.SERVER_ERROR,
    message: "Failed to fetch poll",
  },
};

ctx.response.status = 500;
ctx.response.body = responseBody;
    \end{minted}
\end{frame}

\begin{frame}{Middleware}
    \begin{itemize}
        \item Code applicatif qui se positionne \textbf{entre la requête et la réponse}
        \item \textbf{Intercepte} les données pour leur appliquer des modifications ou effectuer des effets de bord
        \item En pratique :
        \begin{itemize}
            \item Une \textbf{fonction} qui prend en paramètre le \textbf{contexte} (\texttt{ctx}) et la \textbf{prochaine fonction} (\texttt{next})
            \item Invoquée dans une \textbf{chaîne} de traitement, ordonnée, pour chaque requête
            \item Capable d'observer, modifier, court-circuiter ou ignorer le cycle de vie requête-réponse
            \item Appelée par le framework (Oak) lors de la réception d'une requête
        \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}[fragile]{Middleware}
    \begin{minted}[fontsize=\small]{ts}
interface HelloWorldState {
  hello?: string;
  world?: string;
}
async function hello(ctx: Context<HelloWorldState>, next: Next) {
  ctx.state.hello = "Hello";
  await next();
}
async function world(ctx: Context<HelloWorldState>, next: Next) {
  ctx.state.world = "world";
  await next();
}
const router = new Router<HelloWorldState>();
router.get("/hello", hello, world, (ctx) => {
  ctx.response.body = `${ctx.state.hello}, ${ctx.state.world}!`;
});
const app = new Application<HelloWorldState>();
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice 6 : gestion des erreurs du serveur}
    \begin{block}{Un unique point de sortie pour les réponses d'erreur}
        On veut éviter de dupliquer du code pour retourner des erreurs au client dans les fonctions de nos routes. On va donc utiliser un \textbf{middleware} qui sera chargé de remplir la réponse en cas d'erreur.
    \end{block}

    \begin{minted}{ts}
export async function errorMiddleware(ctx: Context, next: Next) { }
    \end{minted}

    \begin{alertblock}{Questions}
        \begin{enumerate}
            \item Sur quel mécanisme s'appuyer pour intercepter les erreurs levées dans les routes de l'application ?
            \item Comment différencier une erreur \textit{prévue} d'une erreur \textit{inattendue} ?
        \end{enumerate}
    \end{alertblock}
\end{frame}

\subsection{Gestion de l'état}

\begin{frame}{Base de données}
    \begin{columns}
        \column{.8\textwidth}
        \begin{itemize}
            \item SQLite
            \item Interactions avec SQLite : bibliothèque
            \item Conversion des \textbf{enregistrements} vers des \textbf{objets}
        \end{itemize}

        \column{.2\textwidth}
        \includegraphics[width=\columnwidth]{img/sqlite.png}
    \end{columns}
\end{frame}

\begin{frame}[fragile]{Base de données : rappels sur SQL}
    \begin{minted}{sql}
CREATE TABLE things (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    maybe TEXT,
    active INTEGER NOT NULL
);

CREATE TABLE thing_options (
    id TEXT PRIMARY KEY,
    thing_id TEXT NOT NULL,
    value TEXT NOT NULL,
    FOREIGN KEY (thing_id) REFERENCES things(id) ON DELETE CASCADE
);
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Base de données : transactions}
    \begin{itemize}
        \item \textbf{Interdépendance} (sémantique et/ou fonctionnelle) entre deux requêtes \textbf{distinctes}
        \item Les deux doivent réussir ou échouer \textbf{ensemble} pour éviter une \textbf{incohérence dans l'état} de l'application
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}[fontsize=\footnotesize]{ts}
// Enregistrer le vote
const voteId = crypto.randomUUID();
const now = new Date().toISOString();
db.prepare(
  "INSERT INTO votes " +
  "(id, poll_id, option_id, user_id, created_at) " +
  "VALUES (?, ?, ?, ?, ?);",
).run(voteId, pollId, optionId, userId || null, now);

// Incrémenter le compteur
db.prepare(
  "UPDATE poll_options SET vote_count = vote_count + 1 WHERE id = ?;",
).run(optionId);
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Base de données : transactions}
    \begin{itemize}
        \item Mécanisme : \textbf{transactions}
        \item Unités de travail qui garantissent l'\textbf{atomicité} des opérations
    \end{itemize}

    \vspace{.5cm}

    \begin{minted}{ts}
try {
  db.prepare("BEGIN").run();    // Début de transaction

  db.prepare("...").run();      // Requête 1
  db.prepare("...").run();      // Requête 2

  db.prepare("COMMIT").run();   // Transaction validée
} catch {
  db.prepare("ROLLBACK").run(); // Transaction annulée
}
    \end{minted}
\end{frame}

\begin{frame}{Exercice 7 : gestion des erreurs du serveur}
    \begin{alertblock}{Besoin d'atomicité}
        \begin{enumerate}
            \item Quelles opérations doivent être \textbf{atomiques} dans notre application de sondage ?
            \item Pourquoi ? C'est-à-dire : quels problèmes peuvent survenir si les sous-opérations, disjointes, échouent ?
        \end{enumerate}
    \end{alertblock}
\end{frame}

\subsection{Architecture}

\begin{frame}{Organisation du dépôt}
    % TODO: pas de paradigme précis, responsabilité côté developpeur

    % TODO: reprendre la terminologie du framework (routes, middleware, etc.)

    \begin{center}
        \includegraphics[width=.5\textwidth]{img/point.png}
    \end{center}
\end{frame}

\begin{frame}[fragile]{Exercice : ...}
    TODO: proposer une organisation

    TODO: montrer les directives export / import associées
\end{frame}

\subsection{Fiabilité et tests}

\begin{frame}[fragile]{Tests}
    \begin{minted}{ts}
import { assertEquals, assert } from "@std/assert";

const BASE_URL = `http://localhost:8000`;

Deno.test({
  name: "polls management API",
  async fn() {
    const listRes = await fetch(`${BASE_URL}/polls`);
    assertEquals(listRes.status, 200);

    const listBody = await listRes.json();
    assert(listBody.success);
    assert(listBody.data.length >= 1);
    },
});
    \end{minted}
\end{frame}

\begin{frame}[fragile]{Exercice ...}
    TODO: écrire des tests pour une ou deux routes
\end{frame}

\section{Client web}

\begin{frame}{HTTP, encore}
    \begin{itemize}
        \item API \texttt{fetch}
    \end{itemize}
\end{frame}

\begin{frame}[fragile]{Un client web minimal avec TypeScript}
    \begin{minted}{js}
        const foo = "bar";
    \end{minted}
\end{frame}

\begin{frame}{Framework : React}
    \begin{itemize}
        \item Hooks
        \begin{itemize}
            \item \texttt{useParams}
            \item \texttt{useState}
            \item \texttt{useRef}
            \item \texttt{useEffect}
        \end{itemize}
        \item Functional Components
        \item React Router
    \end{itemize}
\end{frame}

\begin{frame}{Bundling}
    \begin{itemize}
        \item Bundler
        \item Vite
    \end{itemize}
\end{frame}

\begin{frame}{React : architecture}
    \begin{itemize}
        \item Service Layer Pattern
    \end{itemize}
\end{frame}

\begin{frame}{Bundler}
    
\end{frame}

\section{Authentification}

\begin{frame}{Concepts généraux}
    
\end{frame}

\begin{frame}{\textit{Stateful} : Sessions}
    
\end{frame}

\begin{frame}{\textit{Stateless} : JWT}
    
\end{frame}

\section{Interactions}

\begin{frame}{Data Transfer Objects}
    
\end{frame}

\begin{frame}{WebSockets}
    
\end{frame}

\section{Déploiement de l'application}

\begin{frame}{Nom d'hôte, port, adresse}
    \begin{center}
        \texttt{%
            {\color{BrickRed}https}://%
            {\color{MidnightBlue}foo.bar}.%
            {\color{Orchid}com}%
            [:{\color{LimeGreen}443}]/%
            {\color{YellowOrange}baz.html}%
        }
    \end{center}

    \begin{center}
        \includegraphics[width=.5\textwidth]{img/brace.png}
    \end{center}

    \begin{itemize}
        \item \texttt{{\color{BrickRed}https}} : protocole
        \item \texttt{{\color{MidnightBlue}foo.bar}} : nom d'hôte (\textit{hostname})
        \item \texttt{{\color{Orchid}com}} : \textit{TLD} (\textit{Top-Level Domain})
        \item \texttt{{\color{LimeGreen}443}} : port (HTTP : 80, HTTPS : 443)
        \item \texttt{{\color{YellowOrange}baz.html}} : nom de fichier
    \end{itemize}
\end{frame}

\begin{frame}{Nom d'hôte, port, adresse}
    \begin{center}
        \texttt{%
            {\color{BrickRed}https}://%
            {\color{MidnightBlue}foo.bar}.%
            {\color{Orchid}com}%
            [:{\color{LimeGreen}443}]/%
            {\color{YellowOrange}baz.html}%
        }
    \end{center}
\end{frame}

\begin{frame}[fragile]{Reverse proxy}
    \begin{minted}[fontsize=\footnotesize]{text}
http {
    server {
        listen 80;
        server_name coucou.localhost;

        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}
    \end{minted}
\end{frame}

\begin{frame}{Certificats SSL}
    \begin{itemize}
        \item Protocole (TLSv1.2, TLSv1.3)
        \item Algorithme de chiffrement : AES 128/256, etc.
    \end{itemize}
\end{frame}

\begin{frame}{CORS}
    TODO: 
\end{frame}

\section{Débuggage et profilage}

\begin{frame}{\textit{What could go wrong...}}
    \begin{itemize}
        \item Niveau client
        \item Niveau serveur
        \item Niveau base de données
        \item Interactions API / BDD
        \item Infrastructure
        \item Sécurité
        \item Déploiement
        \item Gestion de l'état
    \end{itemize}
\end{frame}

\subsection{Outillage}

\begin{frame}{\textit{Logging}}
    TODO: 
\end{frame}

\subsection{Profilage des performances}

\begin{frame}{Côté serveur}
    \begin{columns}
        \column{.5\textwidth}
        \begin{itemize}
            \item \texttt{deno run --v8-flags="--prof" main.ts}
            \begin{itemize}
                \item Crée un fichier .log dans le répertoire courant
                \item \textit{"V8 has built-in sample-based profiling. Profiling is turned off by default, but can be enabled via the \texttt{--prof} command-line option. The sampler records stacks of both JavaScript and C/C++ code."}
            \end{itemize}
            \item Lecture du fichier avec cpupro~\footnote[frame]{\url{https://discoveryjs.github.io/cpupro/}}
            \begin{itemize}
                \item Visualisation : \textit{flame graph}~\footnote[frame]{\fullcite{greggFlameGraph2016}}
            \end{itemize}
        \end{itemize}

        \column{.5\textwidth}
        \includegraphics[width=\columnwidth]{img/flamegraph.png}
    \end{columns}
\end{frame}

\begin{frame}{Côté client}
    
\end{frame}

\appendix

\section{Bibliographie}

\begin{frame}[allowframebreaks]{Références}
    \nocite{*}
    \printbibliography[heading=none]
\end{frame}

% \appendix

% \section{Annexes}

% \begin{frame}{Annexe 1 -- ...}
% \end{frame}

\end{document}
