Fibel

15 · Fibel einbauen

Bis hierher war Fibel ein Werkzeug für die Kommandozeile: fibel starte, und fertig. Dieses Kapitel ist für den anderen Fall — ein Programm, das schon läuft, soll Fibel-Seiten zeigen.

bash
npm install fibel
js
import { lies, seite, speicher } from 'fibel';
import fs from 'node:fs';

const programm = lies(fs.readFileSync('laden.fibel', 'utf8'));
const store = await speicher(programm, { quellPfad: 'laden.fibel' });

const antwort = await seite(programm, '/katalog', { store });
// -> { status: 200, html: '<!doctype html>…' }

Mehr ist es nicht. Was hier steht, ist alles, was das Paket zusagt.

Der ganze Eingang

lies(quelle, {…})Text einer .fibel-Datei → Programm
pruefe(programm){ fehler, warnungen, text }
seite(programm, pfad, {…}){ status, html }
speicher(programm, {…})öffnet den Datenspeicher
starte(pfad, {…})die ganze App als eigener Server
Storeder Speicher als Klasse, für Daten im Arbeitsspeicher
FibelError, SpeicherFehlerdie beiden Fehlerarten

Wie in der Sprache gilt jeder Name auch auf Englisch: read, check, page, store, serve.

Alles andere ist Innenleben. fibel/src/lang.js lässt sich nicht importieren — die exports in der package.json sperren es zu. Das ist kein Misstrauen, sondern eine Zusage in die andere Richtung: Was du nicht importieren kannst, können wir umbenennen, ohne dein Programm zu brechen.

lies

js
const programm = lies(quelle);
const programm = lies(quelle, { woerter: { card: 'kachel' } });
const programm = lies(quelle, { pruefen: false });

Geprüft wird von sich aus, und ein Fehler wirft einen FibelError mit der Zeilennummer. Das ist die Vorgabe, weil die andere Reihenfolge — erst laufen lassen, dann merken, dass etwas nicht stimmt — den Fehler zuerst dem Besucher zeigt.

Warnungen halten nichts auf und stehen danach in programm.warnungen.

quelle ist der Inhalt der Datei, nicht ihr Pfad. Fibel liest hier nichts selbst; wo deine Dateien herkommen, weißt du besser.

seite

js
const { status, html } = await seite(programm, '/bestellung/42', {
  store,
  me: angemeldeterNutzer,   // oder weglassen: dann ist es ein Gast
  marke,                    // gegen fremde Formulare, siehe unten
});
status
200die Seite
200 mit anmeldung: truedie Anmeldeseite — die Seite verlangt einen Namen
403angemeldet, aber nicht erlaubt
404die Adresse gibt es nicht

html ist immer da, auch bei 403 und 404. Wer eigene Fehlerseiten hat, benutzt sie eben statt der mitgelieferten.

Die Rechte gelten hier genauso. Es ist derselbe Engpass wie im eigenen Server, nicht ein zweiter Weg daran vorbei: sichtbar, nur, die Eigentümer-Regel. Wer me weglässt, ist ein Gast — und sieht, was ein Gast sehen darf, sonst nichts.

speicher

js
const store = await speicher(programm, { quellPfad: 'laden.fibel' });
const store = await speicher(programm, { quellPfad: 'laden.fibel', art: 'sqlite' });
const store = await speicher(programm, { quellPfad: 'laden.fibel', art: 'postgres' });

Dieselben Speicher wie auf der Kommandozeile, dieselben Namen — siehe Daten. Ohne art ist es die JSON-Datei neben der .fibel-Datei.

Daten nur im Arbeitsspeicher, ohne irgendeine Datei:

js
import { Store } from 'fibel';
const store = new Store(programm.models);

Praktisch für Tests und für Vorschauen, die nichts hinterlassen sollen.

Was noch nicht geht

Ehrlicher an dieser Stelle als eine Enttäuschung später:

  • Formulare abschicken geht nicht über den Eingang. seite zeichnet. Wer die Antworten auch entgegennehmen will, braucht starte — die Aktionen (/__do/…), die Anmeldung und die Uploads hängen am Server. Der Eingang wächst dort hin, aber er ist noch nicht so weit.
  • Die Marke musst du selbst verwalten. seite schreibt sie in die Formulare, wenn du sie hereingibst; sie zu setzen, in einem HttpOnly-Keks abzulegen und beim Abschicken zu vergleichen, ist dann deine Sache.
  • daten lokal wird trotzdem serverseitig gezeichnet. fibel starte schickt bei daten lokal nur die Schale und lässt den Browser rechnen; seite gibt fertiges HTML zurück. Zum Anzeigen ist das richtig — die App im Gerät, die daten lokal sonst ergibt, wird daraus aber nicht.
  • Eigene Wörter gelten für den ganzen Prozess. lies(…, { woerter }) setzt sie global. Wer in einem Prozess Programme von mehreren Kunden mit je eigenen Wörterbüchern lesen will, bekommt sie durcheinander. Ein Wort pro Prozess ist heute die Grenze.

Fremde Programme ausführen

Das ist der Fall, für den es diesen Eingang eigentlich gibt: Die Kundschaft bringt ihre .fibel-Datei und ihre Bilder mit, dein Programm zeigt sie an.

Dabei gibt es eine Frage, die sonst nirgends auftaucht: Ein fremdes Programm darf den Wirt nicht anhalten. Eine Liste über einem großen Bestand kann beliebig lange rechnen. Im Werkzeug ist das eine langsame Seite — bei dir bringt es die Nachbarn mit zum Stehen.

Fibel hat dagegen heute nichts. Keine Zeitgrenze, keine Speicherobergrenze, keinen Abbruch. Was du selbst tun kannst:

  • Jedes Programm in einem eigenen Prozess ausführen und den Prozess nach einer Zeitgrenze beenden.
  • Den Speicher, den du hereingibst, klein halten — sichtbar schützt vor fremden Augen, nicht vor Rechenzeit.
  • Nicht darauf verlassen, dass eine geprüfte Datei auch schnell ist. Die Prüfung sagt, ob das Programm gültig ist, nicht, ob es sich lohnt.

Solange das so ist, gehört ein fremdes Fibel-Programm nicht in denselben Prozess wie etwas, das laufen muss.


Zurück zur Übersicht