Server-Bibliothek
vor 18 Std. 1f44739ba685cd77dc804adcc58fbf584b21e52b
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
32
33
34
35
36
37
38
39
40
import {
  abgleichMisserfolg,
  alsIsoDatum,
  dateinameAusUrl,
  dateiVorhanden,
  ersetzeDateiSicher,
  inhaltBeanstanden,
  type Abgleichauftrag,
  type Bezugsquelle,
  type QuellenAbgleich,
} from './basis';
 
/** Direkter Download-Link: lädt die Datei, erkennt Änderungen über ETag/Last-Modified. */
export class DirektLinkQuelle implements Bezugsquelle {
  async gleicheAb(auftrag: Abgleichauftrag): Promise<QuellenAbgleich> {
    try {
      const antwort = await fetch(auftrag.wert, { redirect: 'follow' });
      if (!antwort.ok) {
        return abgleichMisserfolg(auftrag.aktuelleVersion, `Server nicht erreichbar (HTTP ${antwort.status}).`);
      }
      const kennung = antwort.headers.get('etag') ?? antwort.headers.get('last-modified') ?? '';
      const veroeffentlichtAm = alsIsoDatum(antwort.headers.get('last-modified'));
      const dateiname = dateinameAusUrl(auftrag.wert);
      if (kennung && kennung === auftrag.aktuelleVersion && dateiVorhanden(auftrag.zielordner, dateiname)) {
        return { erfolg: true, geaendert: false, version: kennung, dateiname, meldung: 'Bereits aktuell.', veroeffentlichtAm };
      }
 
      const inhalt = Buffer.from(await antwort.arrayBuffer());
      const beanstandung = inhaltBeanstanden(inhalt, dateiname, antwort.headers.get('content-type'), auftrag.vorherigeGroesse);
      if (beanstandung) {
        return abgleichMisserfolg(auftrag.aktuelleVersion, beanstandung);
      }
 
      ersetzeDateiSicher(auftrag.zielordner, dateiname, inhalt);
      return { erfolg: true, geaendert: true, version: kennung || new Date().toISOString(), dateiname, meldung: 'Aktualisiert.', veroeffentlichtAm };
    } catch (fehler) {
      return abgleichMisserfolg(auftrag.aktuelleVersion, `Download fehlgeschlagen: ${fehler instanceof Error ? fehler.message : String(fehler)}`);
    }
  }
}