Nest.JS Tutorial

Dieses Tutorial zeigt in kompakter Form, wie du NestJS und RxJS für die Implementierung von Server-Sent Events (SSE) einrichtest und nutzt. Es setzt voraus,dass Du mit den Konzepten von Node und Typescript sowie mit der Linux Shell vertraut bist.

Das Besipielprojekt findest Du auch in einem Github Repo.

NodeJS installieren

Installiere Node.js (LTS) entweder von nodejs.org oder nutze deinen Paketmanager:

1
2
3
4
5
# Fedora
sudo dnf install nodejs

# Arch Linux
sudo pacman -S nodejs npm

Installation überprüfen:

1
2
node -v
npm -v

Nest CLI installieren

Installiere das NestJS Command Line Interface global:

1
npm install -g @nestjs/cli

Neues Projekt erstellen

Erstelle dein NestJS-Projekt:

1
2
3
4
nest new my-app
cd my-app
npm install
npm run start:dev

Neues Modul hinzufügen

Generiere ein Modul und einen dazugehörigen Service:

1
2
nest generate module tweet
nest generate service tweet

Tests schreiben

NestJS erstellt automatisch Testdateien. Hier ein Beispieltest (tweet.gateway.spec.ts):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { Test, TestingModule } from '@nestjs/testing';
import { TweetGateway } from './tweet.gateway';

describe('TweetGateway', () => {
  let gateway: TweetGateway;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [TweetGateway],
    }).compile();

    gateway = module.get<TweetGateway>(TweetGateway);
  });

  it('should be defined', () => {
    expect(gateway).toBeDefined();
  });
});

Tests ausführen:

1
npm run test

Hurl für Fixtures einrichten

Installiere Hurl:

1
cargo install --locked hurl

Erstelle fixtures.hurl:

1
2
GET http://localhost:3000/tweets
HTTP/1.1 200

Fixture ausführen:

1
hurl fixtures.hurl

SSE Gateway implementieren (tweet.gateway.ts)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import { Injectable } from '@nestjs/common';
import { Response } from 'express';

@Injectable()
export class TweetGateway {
  private clients: Response[] = [];

  addClient(res: Response) {
    this.clients.push(res);
    res.on('close', () => {
      this.clients = this.clients.filter(c => c !== res);
    });
  }

  broadcast(html: string) {
    const payload = `data: ${JSON.stringify({ html })}\n\n`;
    this.clients.forEach(res => res.write(payload));
  }
}

HTML-Client integrieren

Erstelle eine index.html mit Pico.css, RxJS und nativen SSE:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SSE Client</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css">
  <script src="https://cdn.jsdelivr.net/npm/rxjs@latest/dist/bundles/rxjs.umd.min.js"></script>
</head>
<body>
  <main class="container">
    <h1>Server-Sent Events (SSE)</h1>
    <section id="events"></section>
  </main>

  <script>
    const { fromEvent } = rxjs;
    const eventSource = new EventSource('/tweets');

    const sse$ = fromEvent(eventSource, 'message');

    sse$.subscribe(event => {
      const data = JSON.parse(event.data);
      const eventDiv = document.getElementById('events');
      const messageEl = document.createElement('div');
      messageEl.innerHTML = data.html;
      eventDiv.prepend(messageEl);
    });
  </script>
</body>
</html>

Öffne die index.html im Browser, um kontinuierlich Server-Sent Events zu empfangen und anzuzeigen.

CRUD-Generator

NestJS bietet tatsächlich Möglichkeiten, CRUD-Services effizient aufzusetzen. Ein populärer Ansatz ist das Paket @nestjsx/crud, welches automatisch CRUD-Endpunkte generiert.

1
npm install @nestjsx/crud @nestjsx/crud-typeorm typeorm

Beispiel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { Controller } from '@nestjs/common';
import { Crud } from '@nestjsx/crud';
import { Tweet } from './tweet.entity';
import { TweetsService } from './tweets.service';

@Crud({
  model: { type: Tweet },
})
@Controller('tweets')
export class TweetsController {
  constructor(public service: TweetsService) {}
}

Die Nest CLI generiert Boilerplate-Code:

1
nest g resource tweets

Dies erstellt Module, Controller, Services und DTOs mit Basis-CRUD-Operationen. Nutze TypeORM-Entities und Repositories für effiziente Datenbankoperationen, insbesondere in Kombination mit NestJS generierten CRUD-Controllern und -Services.