From b2ac13e1282ea87cf9f9b6583575c34187c5ac1e Mon Sep 17 00:00:00 2001 From: Florian Wilde Date: Sat, 22 Aug 2026 10:41:33 +0200 Subject: [PATCH] feat: Versionierung mit Changelog, Version 1.0.0 Bis jetzt stand nirgends, welcher Stand laeuft. Beim Aktualisieren auf einem Server ist das die erste Frage. CHANGELOG.md nach Keep a Changelog, Versionsnummern nach SemVer. Der Changelog sagt, was sich beim Arbeiten aendert - nicht, welche Datei angefasst wurde. Dazu eine Tabelle, was Major, Minor und Patch fuer den Betreiber praktisch bedeuten, und der Hinweis, dass sich eine Datenbank-Migration nicht zurueckrollen laesst. Die Version steht bewusst an zwei Stellen: package.json und src/lib/version.ts. Ein Import der package.json waere im Standalone-Build eine andere Datei als die des Projekts - die Zahl haenge dann an der Laufzeit. Ein Test haelt beide zusammen, und "npm run version" setzt sie gemeinsam samt Changelog-Abschnitt. Committet und getaggt wird nicht automatisch. Ein Changelog-Eintrag, den niemand gegengelesen hat, ist keinen Deut besser als keiner. Sichtbar wird die Version unten in der Seitenleiste und unter /api/gesundheit - dort mit Git-Stand, den der Docker-Build hineinreicht. Auf der Anmeldeseite steht sie nicht: wer nicht angemeldet ist, muss nicht wissen, welche Fassung hier laeuft. Etappe: 8 Phase: Haertung --- CHANGELOG.md | 192 ++++++++++++++++++++++++++++++++ Dockerfile | 10 ++ docker-compose.yml | 5 + package.json | 5 +- scripts/version.mjs | 137 +++++++++++++++++++++++ src/app/(app)/layout.tsx | 2 + src/app/api/gesundheit/route.ts | 18 ++- src/components/app-huelle.tsx | 12 +- src/lib/version.ts | 38 +++++++ tests/version.test.ts | 31 ++++++ 10 files changed, 442 insertions(+), 8 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 scripts/version.mjs create mode 100644 src/lib/version.ts create mode 100644 tests/version.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8f8e6a8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,192 @@ +# Änderungen + +Alle nennenswerten Änderungen an dieser Anwendung, in umgekehrter +Reihenfolge. Aufbau nach [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), +Versionsnummern nach [Semantic Versioning](https://semver.org/lang/de/). + +**Was hier steht:** was sich für dich beim Arbeiten ändert — nicht, welche +Datei angefasst wurde. Wer den technischen Verlauf braucht, findet ihn im +Git-Log; jeder Commit trägt seine Etappe. + +**Was die Zahlen bedeuten:** + +| Stelle | Wann sie steigt | Was du tun musst | +|---|---|---| +| **Major** (1.x.x → 2.0.0) | Etwas verhält sich anders als vorher, oder eine Migration lässt sich nicht zurücknehmen | Changelog lesen, **vorher sichern**, Zeit einplanen | +| **Minor** (1.0.x → 1.1.0) | Neue Funktionen, alles Bisherige bleibt wie es war | Changelog überfliegen, normal aktualisieren | +| **Patch** (1.0.0 → 1.0.1) | Fehler behoben, sonst nichts | Einfach aktualisieren | + +Eine Datenbank-Migration lässt sich **nicht** zurückrollen. Vor jedem +Update ein Backup anstoßen — siehe README, Abschnitt *Sicherung und +Wiederherstellung*. + +--- + +## [Unveröffentlicht] + +_Noch nichts._ + +## [1.0.0] – 2026-08-22 + +Erste vollständige Fassung. Alle acht Etappen umgesetzt, alle +Abnahmekriterien als Test hinterlegt. + +### Hinzugefügt + +**Der Alltag** + +- **Dashboard „Heute"** — beantwortet morgens, was ansteht: Fristen-Ampel + (überfällig / diese Woche / diesen Monat), wer gerade am Zug ist, + offene Nachforderungen des Bezirks, ungeprüfter Posteingang, + unverbuchte Belege, Kennzahlen zu Vermögen und Heimkosten. +- **Fristen** — die gesetzlichen Pflichtfristen entstehen von selbst aus + dem Bestellungsdatum: Vermögensverzeichnis und Anfangsbericht nach drei + Monaten, Jahresbericht und Vermögensübersicht zum Ende jedes + Betreuungsjahres, Aufwandspauschale, Landespflegegeld, + Zuzahlungsbefreiung, Rückkaufswerte. Liste, Monatskalender und ein + ICS-Feed zum Abonnieren im eigenen Kalender. +- **Vorgänge** als Fallakte mit Zeitstrahl über Dokumente, Protokolle, + Fristen und Buchungen. Neun Vorlagen mit vorbefüllter Aufgabenliste, + darunter Heimeinzug, Antrag Hilfe zur Pflege, Wohnungsauflösung, + Hausverkauf, Darlehen nach § 91 SGB XII und Widerspruch gegen einen + Bescheid. +- **Kontakte und Kontaktprotokoll** — Verzeichnis aller Stellen mit + Aktenzeichen, dazu eine Schnellerfassung, die am Handy in unter zwanzig + Sekunden zu bedienen ist. + +**Papier** + +- **Dokumentenablage** mit Drag & Drop, Sammel-Upload und Handy-Foto. + Texterkennung auf Deutsch, Volltextsuche über alle Schreiben, + Posteingangsbuch mit den Stufen neu → gesichtet → zugeordnet → + beantwortet, Feld für den Ablageort des Papieroriginals. +- Beim Import werden **Absender, Datum, Aktenzeichen, Dokumentart und + eine im Text genannte Frist vorgeschlagen** — mit der Textstelle + daneben, damit man prüfen kann. Übernommen wird nur auf Klick. +- **Belegmappe**: alle Dokumente eines Vorgangs oder Zeitraums als eine + chronologisch sortierte, paginierte PDF mit Deckblatt und + Inhaltsverzeichnis. + +**Geld** + +- **Kassenbuch** mit Belegzwang, Kategorien, CSV- und CAMT.053-Import. + Harte Trennung zwischen dem Vermögen der betreuten Person und eigenen + Auslagen, mit Warnung bei Buchungen auf ein als privat markiertes Konto. +- **Konten** mit verschlüsselter IBAN und Saldoständen je Stichtag, + **Vermögensposten** mit vollständiger Wert-Historie und Pflichtangabe + zur Wertquelle. Werte werden nie überschrieben. +- **Vermögensverzeichnis (§ 1835 BGB)** und **Vermögensübersicht bzw. + Rechnungslegung (§§ 1859, 1865 BGB)** als druckfertige PDF, in zwei + Ausgabevarianten für befreite und nicht befreite Betreuer. + +**Behörde** + +- **Sozialhilfe-Modul** für das Verfahren beim Bezirk: Antragsakte, + Nachforderungs-Tracker mit Fortschrittsbalken, vorbefüllte Checkliste + der Standardunterlagen mit Begründung, warum der Träger sie will. +- **Bescheid-Prüfung** mit Berechnung der Rechtsbehelfsfrist ab dem + Zugangsdatum, einschließlich Wochenende, bayerischer Feiertage und dem + Sonderfall fehlender Rechtsbehelfsbelehrung. Der Rechenweg wird + ausgegeben. +- **Heimkosten-Gegenüberstellung** Monat für Monat: Kosten gegen + Pflegekasse, Leistungszuschlag nach § 43c SGB XI, Rente und + Sozialhilfeanteil — die Deckungslücke wird sichtbar. +- **Schonvermögens-Bewertung** je Posten (verwertbar / geschützt / + strittig) mit Begründungsfeld und Textbausteinen zu § 90 SGB XII. +- **Katalog weiterer Leistungen**: Landespflegegeld, Zuzahlungsbefreiung, + Rundfunkbeitragsbefreiung, Schwerbehindertenausweis, Grundsicherung. + +**Substanz** + +- **Immobilie** mit Grundbuchdaten, Belastungen nach Abteilung II und + III, Wert-Historie, Status im Sozialhilfeverfahren und einer + Pflichten-Checkliste bei Leerstand — zehn Punkte, jeder mit Begründung. +- **Versicherungen und Verträge** mit Kündigungsfristen-Rechner, der den + spätesten Absendetag nennt, Anschreiben zur Rückkaufswert-Anfrage mit + automatischer Wiedervorlage und einem Kündigungs-Assistenten. +- **Heim und Pflege** mit Heimvertrag, Leistungszuschlag-Staffel, + Pflegegrad-Historie, Abwesenheitstagen und einem Gesundheitsverlauf mit + COPD-Bezug: Exazerbationen, Sauerstoff, Stürze, Krankenhaus, + Hilfsmittel, Impfungen nach STIKO-Plan. + +**Ausgabe** + +- **Jahresbericht (§ 1863 BGB)** als Entwurf zum Überarbeiten, gespeist + aus Kontaktprotokollen, Gesundheitsereignissen und Vorgangsstatus. + Ausgabe als PDF und als DOCX. +- **Unterlagenpaket für den Bezirk**: die im Tracker markierten + Dokumente als eine PDF mit Anschreiben und Inhaltsverzeichnis. +- **Vollexport** als ZIP mit allen Originaldateien, allen Daten als + entschlüsseltes JSON, den erzeugten Berichten, einer LIESMICH und + SHA-256-Prüfsummen. +- **Wissensbasis** mit 37 Hinweiskarten, pflegbar als JSON-Datei ohne + Neustart. Jede mit Rechtsgrundlage, Link und dem stehenden Vermerk, + dass sie keine Rechtsberatung ersetzt. + +**Verwaltung** + +- **Mitleser-Rolle** mit modulweiser Freigabe und ausdrücklicher Warnung + bei Gesundheit, Finanzen und Sozialhilfe. +- **Papierkorb** mit 30 Tagen Aufbewahrung. +- **Wartungslauf** über `/api/wartung`: Fristerinnerungen per E-Mail, + Papierkorb leeren, alte Anmeldeversuche entfernen. + +### Sicherheit + +- **Pflicht-Zweitfaktor** (TOTP nach RFC 6238). Lässt sich nicht + abschalten. Acht Wiederherstellungscodes, einzeln Argon2id-gehasht. +- **Anwendungsseitige Feldverschlüsselung** mit AES-256-GCM für + Diagnosen, den ermittelten Willen, IBANs, Versicherungs-, Renten- und + Steuernummern sowie alle Freitext-Notizen. Der Feldname wird + mitauthentifiziert — ein Geheimtext lässt sich nicht von einem Feld in + ein anderes umhängen. Schlüsselrotation ohne Datenverlust vorgesehen. +- **Argon2id** nach OWASP-Empfehlung, mit automatischem Nachziehen bei + späterer Parametererhöhung. +- **Rate-Limiting** am Login nach E-Mail und Anschluss. Die Sperre wird + geprüft, bevor überhaupt gerechnet wird, und die Antwortzeit ist + gestreckt — sie verrät nicht, welche Adressen existieren. +- **Unveränderliches Audit-Log**: ein Datenbank-Trigger weist UPDATE und + DELETE ab, auch bei direktem Zugriff mit `psql`. +- **Strenge Content-Security-Policy** mit Nonce pro Anfrage. Keine + externen Schriften, kein CDN, keine Tracker — nachgewiesen durch einen + Test, der jede Anfrage an einen fremden Host als Fehler wertet. +- **Uploads** werden an den Magic Bytes geprüft, nicht an Endung oder + gemeldetem MIME-Typ. Ausgeliefert wird nur über kurzlebige signierte + URLs, immer als Anhang mit `nosniff`. +- **Erneute Anmeldung** vor Export, endgültigem Löschen und + Rollenänderungen. Ein Passwortwechsel beendet alle offenen Sitzungen. + +### Betrieb + +- Docker Compose mit Anwendung, PostgreSQL, MinIO und Sicherungsdienst. + **Ohne Reverse Proxy** — der ist auf dem Zielserver vorhanden. Die + Datenbank hat keine Portfreigabe. +- **Tägliche verschlüsselte Sicherung** um 03:15 Uhr mit Selbstprüfung: + lässt sich die Datei nicht wieder entschlüsseln, endet der Lauf mit + Fehler statt mit einem stillen Scheinerfolg. +- Verarbeitungsverzeichnis und Datenschutzhinweise als ausfüllbare + Textbausteine. +- Bauprotokoll aus den Commit-Trailern. + +### Bekannte Einschränkungen + +- Die Texterkennung ist gegen ein echtes Tesseract **nicht** end-to-end + geprüft. Der Weg „nicht verfügbar, Upload funktioniert trotzdem" ist + getestet. +- Der CAMT.053-Import ist nur gegen selbst gebaute Beispiele geprüft, nicht + gegen einen echten Bankauszug. +- Das Kostenkonto der Immobilie wertet über Buchungskategorien aus und + wäre bei einem **zweiten** Grundstück falsch. Die Oberfläche sagt das + an der Auswertung dazu. +- Eine Aufgabe aus einer Vorgangs-Vorlage lässt sich nicht entfernen — + passt sie im Einzelfall nicht, bleibt sie offen stehen. +- `@react-pdf/renderer` braucht in diesem Abhängigkeitsbaum eine Krücke + (`src/lib/pdf/standardschrift.ts`), weil seine Unterabhängigkeiten für + Standardschriften kein Schriftobjekt mehr liefern. + +Was davon wann angegangen wird, steht in [`docs/ROADMAP.md`](docs/ROADMAP.md). + +--- + +[Unveröffentlicht]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.0.0...HEAD +[1.0.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/releases/tag/v1.0.0 diff --git a/Dockerfile b/Dockerfile index 4eb22bf..0cf5ab2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,6 +43,16 @@ COPY . . ENV NEXT_TELEMETRY_DISABLED=1 ENV SKIP_ENV_VALIDATION=1 +# Git-Stand und Bauzeitpunkt landen in der Oberflaeche und im +# Gesundheitsendpunkt. Beim Aktualisieren sieht man damit auf einen Blick, +# ob wirklich der neue Stand laeuft: +# +# docker build --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) . +ARG GIT_COMMIT="" +ARG BUILD_ZEIT="" +ENV NEXT_PUBLIC_GIT_COMMIT=$GIT_COMMIT +ENV NEXT_PUBLIC_BUILD_ZEIT=$BUILD_ZEIT + RUN npm run build # --- Stufe 3: Laufzeit ------------------------------------------------------- diff --git a/docker-compose.yml b/docker-compose.yml index 95dbc6c..6345766 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -70,6 +70,11 @@ services: build: context: . dockerfile: Dockerfile + args: + # In der Oberflaeche und unter /api/gesundheit sichtbar. Setzen mit: + # GIT_COMMIT=$(git rev-parse --short HEAD) docker compose up -d --build + GIT_COMMIT: ${GIT_COMMIT:-} + BUILD_ZEIT: ${BUILD_ZEIT:-} restart: unless-stopped depends_on: db: diff --git a/package.json b/package.json index 48d4488..d5cd39b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "betreuungs-cockpit", - "version": "0.1.0", + "version": "1.0.0", "private": true, "description": "Arbeits- und Dokumentationswerkzeug fuer die ehrenamtliche rechtliche Betreuung", "engines": { @@ -28,7 +28,8 @@ "protokoll": "node scripts/bauprotokoll.mjs", "test:e2e": "playwright test", "protokoll:md": "node scripts/bauprotokoll.mjs --md", - "wartungsschluessel": "node --env-file=.env scripts/wartungsschluessel.mjs" + "wartungsschluessel": "node --env-file=.env scripts/wartungsschluessel.mjs", + "version": "node scripts/version.mjs" }, "prisma": { "seed": "tsx prisma/seed.ts" diff --git a/scripts/version.mjs b/scripts/version.mjs new file mode 100644 index 0000000..a662f69 --- /dev/null +++ b/scripts/version.mjs @@ -0,0 +1,137 @@ +#!/usr/bin/env node +/** + * Version anheben. + * + * npm run version -- patch 1.0.0 -> 1.0.1 + * npm run version -- minor 1.0.0 -> 1.1.0 + * npm run version -- major 1.0.0 -> 2.0.0 + * npm run version -- 1.2.3 genau diese Version + * + * Was passiert: + * 1. package.json und src/lib/version.ts werden gesetzt - beide, damit + * sie nicht auseinanderlaufen. + * 2. Im CHANGELOG wird aus "## [Unveroeffentlicht]" ein Abschnitt mit + * Versionsnummer und heutigem Datum, darueber ein neuer leerer + * Abschnitt. + * 3. Der Vergleichslink am Dateiende wird nachgezogen. + * + * Was NICHT passiert: committen und taggen. Das machst du selbst, nachdem + * du den Changelog-Eintrag gegengelesen hast. Ein automatisch erzeugter + * Changelog, den niemand liest, ist keinen Deut besser als keiner. + * + * Danach: + * git add -A && git commit -m "chore: Version 1.0.1" + * git tag -a v1.0.1 -m "..." && git push --follow-tags + */ +import { readFileSync, writeFileSync } from 'node:fs' + +const WURZEL = new URL('..', import.meta.url) +const pfad = (name) => new URL(name, WURZEL) + +function lesen(name) { + return readFileSync(pfad(name), 'utf8') +} + +function schreiben(name, inhalt) { + writeFileSync(pfad(name), inhalt, 'utf8') + console.log(` ${name}`) +} + +// --- Ziel bestimmen --------------------------------------------------------- + +const argument = process.argv[2] +if (!argument) { + console.error('Aufruf: npm run version -- ') + process.exit(1) +} + +const paket = JSON.parse(lesen('package.json')) +const alt = paket.version + +function naechste(aktuell, art) { + const treffer = aktuell.match(/^(\d+)\.(\d+)\.(\d+)$/) + if (!treffer) throw new Error(`Version "${aktuell}" ist kein x.y.z`) + const [haupt, neben, fehler] = treffer.slice(1).map(Number) + + switch (art) { + case 'major': + return `${haupt + 1}.0.0` + case 'minor': + return `${haupt}.${neben + 1}.0` + case 'patch': + return `${haupt}.${neben}.${fehler + 1}` + default: + if (!/^\d+\.\d+\.\d+$/.test(art)) { + throw new Error(`"${art}" ist weder patch/minor/major noch x.y.z`) + } + return art + } +} + +const neu = naechste(alt, argument) +if (neu === alt) { + console.error(`Version ist bereits ${alt}.`) + process.exit(1) +} + +console.log(`\n${alt} -> ${neu}\n`) +console.log('Geaendert:') + +// --- 1. package.json -------------------------------------------------------- + +paket.version = neu +schreiben('package.json', `${JSON.stringify(paket, null, 2)}\n`) + +// --- 2. src/lib/version.ts -------------------------------------------------- + +const versionsdatei = lesen('src/lib/version.ts') +const ersetzt = versionsdatei.replace( + /export const VERSION = '[^']+'/, + `export const VERSION = '${neu}'`, +) +if (ersetzt === versionsdatei) { + console.error('FEHLER: VERSION in src/lib/version.ts nicht gefunden.') + process.exit(1) +} +schreiben('src/lib/version.ts', ersetzt) + +// --- 3. CHANGELOG.md -------------------------------------------------------- + +const heute = new Date().toISOString().slice(0, 10) +let changelog = lesen('CHANGELOG.md') + +const UNVEROEFFENTLICHT = '## [Unveröffentlicht]' +if (!changelog.includes(UNVEROEFFENTLICHT)) { + console.error(`FEHLER: "${UNVEROEFFENTLICHT}" steht nicht im CHANGELOG.`) + process.exit(1) +} + +const leererAbschnitt = [ + UNVEROEFFENTLICHT, + '', + '_Noch nichts._', + '', + `## [${neu}] – ${heute}`, +].join('\n') + +changelog = changelog.replace(UNVEROEFFENTLICHT, leererAbschnitt) + +// Vergleichslinks am Dateiende nachziehen. +const basis = 'https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare' +changelog = changelog.replace( + /^\[Unveröffentlicht\]:.*$/m, + `[Unveröffentlicht]: ${basis}/v${neu}...HEAD\n[${neu}]: ${basis}/v${alt}...v${neu}`, +) + +schreiben('CHANGELOG.md', changelog) + +// --- Hinweis ---------------------------------------------------------------- + +console.log(` +Jetzt: + 1. CHANGELOG.md gegenlesen - steht dort, was sich fuer den Nutzer + tatsaechlich aendert? Nicht, welche Datei angefasst wurde. + 2. git add -A && git commit -m "chore: Version ${neu}" + 3. git tag -a v${neu} -m "Version ${neu}" + 4. git push --follow-tags +`) diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx index 5061f86..9563055 100644 --- a/src/app/(app)/layout.tsx +++ b/src/app/(app)/layout.tsx @@ -7,6 +7,7 @@ import { aktiveBetreute, erfordereBenutzer, erfordereZweitenFaktor, meineBetreut import { darf } from '@/lib/auth/rollen' import { ROLLEN_BESCHRIFTUNG } from '@/lib/auth/rollen' import { db, nichtGeloescht } from '@/lib/db' +import { versionstext } from '@/lib/version' /** * Rahmen aller Fachseiten. @@ -64,6 +65,7 @@ export default async function AppLayout({ children }: { children: React.ReactNod return ( -
{benutzerbereich}
+
+ {benutzerbereich} + {version && ( +

+ Version {version} +

+ )} +
{/* --- Kopfzeile am Handy ------------------------------------------- */} diff --git a/src/lib/version.ts b/src/lib/version.ts new file mode 100644 index 0000000..bd5021c --- /dev/null +++ b/src/lib/version.ts @@ -0,0 +1,38 @@ +/** + * Versionsangaben der Anwendung. + * + * VERSION wird vom Skript `npm run version` zusammen mit der package.json + * gesetzt - es gibt also genau eine Quelle, aus der beide gespeist werden. + * Ein Test (tests/version.test.ts) prueft, dass sie nicht auseinanderlaufen. + * + * Warum nicht einfach die package.json importieren? Im Standalone-Build + * liegt eine andere package.json neben dem Server als die des Projekts. + * Die Zahl waere dann je nach Laufzeit eine andere - genau das, was man + * bei einer Versionsangabe nicht gebrauchen kann. + * + * Die Angabe ist kein Geheimnis, aber auch keine oeffentliche Auskunft: + * sie steht in den Einstellungen und im Gesundheitsendpunkt, nicht auf + * der Anmeldeseite. Wer nicht angemeldet ist, muss nicht wissen, welche + * Fassung hier laeuft. + */ + +/** Muss zur "version" in der package.json passen. */ +export const VERSION = '1.0.0' + +/** + * Kurzer Git-Stand, beim Bauen hineingereicht: + * + * docker build --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) . + * + * Fehlt die Angabe (etwa im Entwicklungsmodus), bleibt sie leer. Dann + * zeigt die Oberflaeche nur die Version. + */ +export const COMMIT = process.env.NEXT_PUBLIC_GIT_COMMIT ?? '' + +/** Zeitpunkt des Bauens, ebenfalls beim Bauen hineingereicht. */ +export const GEBAUT_AM = process.env.NEXT_PUBLIC_BUILD_ZEIT ?? '' + +/** "1.0.0" oder "1.0.0 · 4b953e7" - fuer die Anzeige. */ +export function versionstext(): string { + return COMMIT ? `${VERSION} · ${COMMIT}` : VERSION +} diff --git a/tests/version.test.ts b/tests/version.test.ts new file mode 100644 index 0000000..a99a49f --- /dev/null +++ b/tests/version.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from 'vitest' +import { readFileSync } from 'node:fs' +import { VERSION, versionstext } from '@/lib/version' + +/** + * Die Version steht an zwei Stellen: in der package.json und in + * src/lib/version.ts. Das ist Absicht - im Standalone-Build liegt eine + * andere package.json neben dem Server als die des Projekts, ein Import + * waere also je nach Laufzeit eine andere Zahl. + * + * Damit die beiden nicht auseinanderlaufen, gibt es dieses Netz. Wer die + * Version von Hand aendert statt mit "npm run version", merkt es hier. + */ +describe('Version', () => { + const paket = JSON.parse(readFileSync('package.json', 'utf8')) as { version: string } + + it('stimmt mit der package.json ueberein', () => { + expect( + VERSION, + 'src/lib/version.ts und package.json weichen ab - benutze "npm run version"', + ).toBe(paket.version) + }) + + it('ist eine gueltige Versionsnummer nach SemVer', () => { + expect(VERSION).toMatch(/^\d+\.\d+\.\d+$/) + }) + + it('haengt den Git-Stand an, wenn er bekannt ist', () => { + expect(versionstext().startsWith(VERSION)).toBe(true) + }) +})