JavaScript-API-Referenz
EmDash exportiert Funktionen zum Abfragen von Inhalten, Verwalten von Medien und Arbeiten mit der Datenbank.
Inhaltsabfragen
Abschnitt betitelt „Inhaltsabfragen“Die Abfragefunktionen von EmDash folgen Astros Live-Content-Sammlungen-Muster und geben { entries, error } oder { entry, error } für eine elegante Fehlerbehandlung zurück.
getEmDashCollection()
Abschnitt betitelt „getEmDashCollection()“Gibt alle Einträge einer Sammlung zurück.
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) { console.error("Beiträge konnten nicht geladen werden:", error);}Parameter
Abschnitt betitelt „Parameter“| Parameter | Typ | Beschreibung |
|---|---|---|
collection | string | Sammlungs-Slug |
options | CollectionFilter | Optionale Filteroptionen |
Optionen
Abschnitt betitelt „Optionen“interface CollectionFilter { status?: "draft" | "published" | "archived"; limit?: number; where?: Record<string, string | string[]>; // Filtert nach Feld oder Taxonomie}Rückgabewerte
Abschnitt betitelt „Rückgabewerte“interface CollectionResult<T> { entries: ContentEntry<T>[]; // Leeres Array bei Fehler oder wenn nichts gefunden wird error?: Error; // Wird gesetzt, wenn die Abfrage fehlschlägt}Beispiele
Abschnitt betitelt „Beispiele“// Alle veröffentlichten Beiträge ladenconst { entries: posts } = await getEmDashCollection("posts", { status: "published",});
// Hole die neuesten 5 Beiträgeconst { entries: latest } = await getEmDashCollection("posts", { limit: 5, status: "published",});
// Filtere nach Taxonomieconst { entries: newsPosts } = await getEmDashCollection("posts", { status: "published", where: { category: "news" },});
// Behandle Fehlerconst { entries, error } = await getEmDashCollection("posts");if (error) { return new Response("Serverfehler", { status: 500 });}getEmDashEntry()
Abschnitt betitelt „getEmDashEntry()“Hole einen einzelnen Eintrag anhand von Slug oder ID.
import { getEmDashEntry } from "emdash";
const { entry: post, error } = await getEmDashEntry("posts", "my-post-slug");
if (!post) { return Astro.redirect("/404");}Parameter
Abschnitt betitelt „Parameter“| Parameter | Typ | Beschreibung |
|---|---|---|
collection | string | Sammlungs-Slug |
slugOrId | string | Eintrags-Slug oder ID |
Der Vorschaumodus wird automatisch behandelt – die Middleware erkennt _preview-Tokens und stellt Entwurfsinhalte über AsyncLocalStorage bereit. Ein Options-Parameter ist nicht erforderlich.
Rückgabewerte
Abschnitt betitelt „Rückgabewerte“interface EntryResult<T> { entry: ContentEntry<T> | null; // null, wenn nichts gefunden wurde error?: Error; // Nur bei echten Fehlern gesetzt, nicht bei "nicht gefunden" isPreview: boolean; // true, wenn Entwurfsinhalt ausgeliefert wird}Beispiele
Abschnitt betitelt „Beispiele“// Per Slug ladenconst { entry: post } = await getEmDashEntry("posts", "hello-world");
// Hole per IDconst { entry: post } = await getEmDashEntry("posts", "01HXK5MZSN0FVXT2Q3KPRT9M7D");
// Vorschau ist automatisch – isPreview ist true, wenn ein gültiges _preview-Token vorhanden istconst { entry, isPreview, error } = await getEmDashEntry("posts", slug);
// Behandle Fehler vs. nicht gefundenif (error) { return new Response("Serverfehler", { status: 500 });}if (!entry) { return Astro.redirect("/404");}Inhaltstypen
Abschnitt betitelt „Inhaltstypen“ContentEntry
Abschnitt betitelt „ContentEntry“Der von Abfragefunktionen zurückgegebene Eintrag:
interface ContentEntry<T = Record<string, unknown>> { id: string; data: T; edit: EditProxy; // Annotationen für die visuelle Bearbeitung}Der edit-Proxy stellt Anmerkungen für die visuelle Bearbeitung bereit. Verteile ihn auf Elemente, um Inline-Bearbeitung zu ermöglichen: {...entry.edit.title}. In der Produktion erzeugt dies keine Ausgabe.
Das data-Objekt enthält alle Inhaltsfelder plus Systemfelder:
id- Eindeutiger Bezeichnerslug- URL-freundlicher Bezeichnerstatus- “draft” | “published” | “archived”createdAt- ISO-ZeitstempelupdatedAt- ISO-ZeitstempelpublishedAt- ISO-Zeitstempel oder null- Plus alle benutzerdefinierten Felder, die in Ihrem Sammlungsschema definiert sind
Datenbankfunktionen
Abschnitt betitelt „Datenbankfunktionen“createDatabase()
Abschnitt betitelt „createDatabase()“Erstelle eine Datenbankverbindung.
import { createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });runMigrations()
Abschnitt betitelt „runMigrations()“Führe ausstehende Datenbankmigrationen aus.
import { createDatabase, runMigrations } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const { applied } = await runMigrations(db);console.log(`${applied.length} Migrationen angewendet`);getMigrationStatus()
Abschnitt betitelt „getMigrationStatus()“Überprüfe den Migrationsstatus.
import { createDatabase, getMigrationStatus } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const status = await getMigrationStatus(db);// { applied: ["0001_core", ...], pending: [] }Repositories
Abschnitt betitelt „Repositories“Niedrigstufiger Datenzugriff über Repositories.
ContentRepository
Abschnitt betitelt „ContentRepository“import { ContentRepository, createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const repo = new ContentRepository(db);
// Mehrere ladenconst { items, nextCursor } = await repo.findMany("posts", { limit: 10, where: { status: "published" },});
// Per ID ladenconst post = await repo.findById("posts", "01HXK5MZSN...");
// Erstelleconst newPost = await repo.create({ type: "posts", slug: "new-post", data: { title: "Neuer Beitrag", content: [] }, status: "draft",});
// Aktualisiereconst updated = await repo.update("posts", "01HXK5MZSN...", { data: { title: "Aktualisierter Titel" },});
// Löscheawait repo.delete("posts", "01HXK5MZSN...");MediaRepository
Abschnitt betitelt „MediaRepository“import { MediaRepository, createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const repo = new MediaRepository(db);
// Medien auflistenconst { items } = await repo.findMany({ limit: 20 });
// Hole per IDconst media = await repo.findById("01HXK5MZSN...");
// Erstelle (nach Upload)const newMedia = await repo.create({ filename: "photo.jpg", mimeType: "image/jpeg", size: 12345, storageKey: "uploads/photo.jpg",});Schema-Registry
Abschnitt betitelt „Schema-Registry“Programmatische Schemaverwaltung.
import { SchemaRegistry, createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const registry = new SchemaRegistry(db);
// Liste Sammlungen aufconst collections = await registry.listCollections();
// Hole Sammlung mit Feldernconst postsSchema = await registry.getCollectionWithFields("posts");
// Erstelle Sammlungawait registry.createCollection({ slug: "products", label: "Produkte", labelSingular: "Produkt", supports: ["drafts", "revisions"],});
// Füge Feld hinzuawait registry.createField("products", { slug: "price", label: "Preis", type: "number", required: true,});Vorschausystem
Abschnitt betitelt „Vorschausystem“generatePreviewToken()
Abschnitt betitelt „generatePreviewToken()“Generiere ein Vorschau-Token für Entwurfsinhalte.
import { generatePreviewToken } from "emdash";
const token = await generatePreviewToken({ contentId: "posts:01HXK5MZSN...", secret: process.env.EMDASH_ADMIN_SECRET, expiresIn: 3600, // 1 Stunde});verifyPreviewToken()
Abschnitt betitelt „verifyPreviewToken()“Überprüfe ein Vorschau-Token.
import { verifyPreviewToken } from "emdash";
const result = await verifyPreviewToken({ token, secret: process.env.EMDASH_ADMIN_SECRET,});
if (result.valid) { const { cid, exp, iat } = result.payload; // cid hat das Format "collection:id", z.B. "posts:my-draft-post"}isPreviewRequest()
Abschnitt betitelt „isPreviewRequest()“Prüfe, ob eine Anfrage ein Vorschau-Token enthält.
import { isPreviewRequest, getPreviewToken } from "emdash";
if (isPreviewRequest(Astro.request)) { const token = getPreviewToken(Astro.request); // Vorschau-Inhalt validieren und anzeigen}Inhaltskonverter
Abschnitt betitelt „Inhaltskonverter“Konvertiere zwischen Portable Text- und ProseMirror-Formaten.
import { prosemirrorToPortableText, portableTextToProsemirror } from "emdash";
// Von ProseMirror (Editor) zu Portable Text (Speicher)const portableText = prosemirrorToPortableText(prosemirrorDoc);
// Von Portable Text zu ProseMirrorconst prosemirrorDoc = portableTextToProsemirror(portableText);Website-Einstellungen
Abschnitt betitelt „Website-Einstellungen“import { getSiteSettings, getSiteSetting } from "emdash";
// Hole alle Einstellungenconst settings = await getSiteSettings();
// Hole einzelne Einstellungconst title = await getSiteSetting("siteTitle");Einstellungen sind über die Laufzeit-API schreibgeschützt. Verwenden Sie die Admin-API, um sie zu aktualisieren.
import { getMenu, getMenus } from "emdash";
// Hole alle Menüsconst menus = await getMenus();
// Hole spezifisches Menü mit Elementenconst primaryMenu = await getMenu("primary");
if (primaryMenu) { primaryMenu.items.forEach(item => { console.log(item.label, item.url); // Verschachtelte Elemente für Dropdown-Menüs item.children.forEach(child => console.log(" -", child.label)); });}Taxonomien
Abschnitt betitelt „Taxonomien“import { getTaxonomyTerms, getTerm, getEntryTerms, getEntriesByTerm } from "emdash";
// Hole alle Begriffe für eine Taxonomie (Baumstruktur für hierarchische)const categories = await getTaxonomyTerms("category");
// Einzelnen Begriff abrufenconst news = await getTerm("category", "news");
// Begriffe abrufen, die einem Inhalteintrag zugewiesen sindconst postCategories = await getEntryTerms("posts", "post-123", "category");
// Einträge mit einem bestimmten Begriff abrufenconst newsPosts = await getEntriesByTerm("posts", "category", "news");Widget-Bereiche
Abschnitt betitelt „Widget-Bereiche“import { getWidgetArea, getWidgetAreas } from "emdash";
// Alle Widget-Bereiche abrufenconst areas = await getWidgetAreas();
// Bestimmten Widget-Bereich mit Widgets abrufenconst sidebar = await getWidgetArea("sidebar");
if (sidebar) { sidebar.widgets.forEach(widget => { console.log(widget.type, widget.title); });}Abschnitte
Abschnitt betitelt „Abschnitte“import { getSection, getSections, getSectionCategories } from "emdash";
// Alle Abschnitte abrufenconst sections = await getSections();
// Abschnitte filternconst heroes = await getSections({ category: "hero" });const themeSections = await getSections({ source: "theme" });const results = await getSections({ search: "newsletter" });
// Einzelnen Abschnitt abrufenconst cta = await getSection("newsletter-cta");
// Kategorien abrufenconst categories = await getSectionCategories();import { search, searchCollection } from "emdash";
// Globale Suche über Sammlungen hinwegconst results = await search("hello world", { collections: ["posts", "pages"], status: "published", limit: 20,});
// Ergebnisse enthalten Ausschnitte mit Hervorhebungenresults.forEach(result => { console.log(result.title); console.log(result.snippet); // Contains <mark> tags console.log(result.score);});
// Sammlungsspezifische Sucheconst posts = await searchCollection("posts", "typescript", { limit: 10,});Fehlerbehandlung
Abschnitt betitelt „Fehlerbehandlung“EmDash exportiert Fehlerklassen zur Behandlung spezifischer Fehler:
import { EmDashDatabaseError, EmDashValidationError, EmDashStorageError, SchemaError,} from "emdash";
try { await repo.create({ ... });} catch (error) { if (error instanceof EmDashValidationError) { console.error("Validation failed:", error.message); } if (error instanceof SchemaError) { console.error("Schema error:", error.code, error.details); }}