Riferimento API JavaScript

In questa pagina

EmDash esporta funzioni per interrogare i contenuti e lavorare con anteprima, impostazioni, menu, tassonomie, aree widget, sezioni e ricerca.

Query sui contenuti

Le funzioni di query di EmDash seguono il pattern delle collezioni di contenuto live di Astro, restituendo { entries, error } o { entry, error } per una gestione elegante degli errori.

getEmDashCollection()

Recuperare tutte le voci di una collezione. L’esempio seguente carica tutti i post e verifica gli errori:

import { getEmDashCollection } from "emdash";

const { entries: posts, error } = await getEmDashCollection("posts");

if (error) {
	console.error("Impossibile caricare i post:", error);
}

Parametri

ParametroTipoDescrizione
collectionstringSlug della collezione
optionsCollectionFilterOpzioni di filtro opzionali

Opzioni

Il parametro options accetta il seguente filtro:

interface CollectionFilter {
	status?: "draft" | "published" | "archived";
	limit?: number;
	cursor?: string; // Paginazione keyset — passa un `nextCursor` precedente
	offset?: number; // Paginazione offset — salta N voci (usare con `limit`)
	where?: Record<string, string | string[]>; // Filtrare per campo o tassonomia
}

Restituisce

La funzione risolve in un CollectionResult:

interface CollectionResult<T> {
	entries: ContentEntry<T>[]; // Array vuoto in caso di errore o nessun risultato
	error?: Error; // Impostato se la query è fallita
	nextCursor?: string; // Cursore per la prossima pagina keyset, se presente
	hasMore?: boolean; // Se esistono più voci oltre questa pagina (quando `limit` è impostato)
}

Esempi

I seguenti esempi filtrano per stato e tassonomia, limitano i risultati e gestiscono gli errori:

// Ottenere tutti i post pubblicati
const { entries: posts } = await getEmDashCollection("posts", {
	status: "published",
});

// Ottenere gli ultimi 5 post
const { entries: latest } = await getEmDashCollection("posts", {
	limit: 5,
	status: "published",
});

// Filtrare per tassonomia
const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

// Pagina di archivio numerata (es. /page/3) con paginazione offset
const perPage = 20;
const page = Number(Astro.params.page ?? 1);
const { entries: pagePosts, hasMore } = await getEmDashCollection("posts", {
	status: "published",
	limit: perPage,
	offset: (page - 1) * perPage,
	orderBy: { published_at: "desc" },
});

// Gestire gli errori
const { entries, error } = await getEmDashCollection("posts");
if (error) {
	return new Response("Errore del server", { status: 500 });
}

getEmDashEntry()

Recuperare una singola voce per slug o ID. L’esempio seguente carica un post e reindirizza quando manca:

import { getEmDashEntry } from "emdash";

const { entry: post, error } = await getEmDashEntry("posts", "my-post-slug");

if (!post) {
	return Astro.redirect("/404");
}

Parametri

ParametroTipoDescrizione
collectionstringSlug della collezione
slugOrIdstringSlug o ID della voce
options{ locale?: string }Opzionale. Locale per la risoluzione dello slug

La modalità anteprima è gestita automaticamente — il middleware rileva i token _preview e serve contenuto bozza tramite AsyncLocalStorage. Il parametro opzionale options accetta solo un locale per la risoluzione dello slug; lo stato di anteprima non richiede parametri.

Restituisce

La funzione risolve in un EntryResult:

interface EntryResult<T> {
	entry: ContentEntry<T> | null; // null se non trovato
	error?: Error; // Impostato solo per errori reali, non per "non trovato"
	isPreview: boolean; // true se viene servito contenuto bozza
}

Esempi

I seguenti esempi recuperano per slug e ID, leggono lo stato di anteprima e distinguono errori da non-trovato:

// Ottenere per slug
const { entry: post } = await getEmDashEntry("posts", "hello-world");

// Ottenere per ID
const { entry: post } = await getEmDashEntry("posts", "01HXK5MZSN0FVXT2Q3KPRT9M7D");

// L'anteprima è automatica — isPreview è true quando è presente un token _preview valido
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);

// Gestire errori vs non-trovato
if (error) {
	return new Response("Errore del server", { status: 500 });
}
if (!entry) {
	return Astro.redirect("/404");
}

Tipi di contenuto

ContentEntry

Le funzioni di query restituiscono voci nella seguente forma:

interface ContentEntry<T = Record<string, unknown>> {
	id: string;
	data: T;
	edit: EditProxy; // Annotazioni di editing visuale
}

Il proxy edit fornisce annotazioni di editing visuale. Distribuiscilo sugli elementi per abilitare l’editing inline: {...entry.edit.title}. In produzione, questo non produce output.

L’oggetto data contiene tutti i campi di contenuto più i campi di sistema:

  • id - Identificatore univoco
  • slug - Identificatore URL-friendly
  • status - “draft” | “published” | “archived”
  • createdAt - Timestamp ISO
  • updatedAt - Timestamp ISO
  • publishedAt - Timestamp ISO o null
  • Più tutti i campi personalizzati definiti nel tuo schema di collezione

Sistema di anteprima

generatePreviewToken()

Generare un token di anteprima per contenuto bozza. L’esempio seguente crea un token che scade in un’ora:

import { generatePreviewToken } from "emdash";

const token = await generatePreviewToken({
	contentId: "posts:01HXK5MZSN...",
	secret: process.env.EMDASH_ADMIN_SECRET,
	expiresIn: 3600, // 1 ora
});

verifyPreviewToken()

Verificare un token di anteprima e leggere il suo contenuto:

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 è nel formato "collection:id", es. "posts:my-draft-post"
}

isPreviewRequest()

Verificare se una richiesta include un token di anteprima, poi leggerlo:

import { isPreviewRequest, getPreviewToken } from "emdash";

if (isPreviewRequest(Astro.url)) {
	const token = getPreviewToken(Astro.url);
	// Verificare e mostrare il contenuto di anteprima
}

Convertitori di contenuto

Convertire tra i formati Portable Text e ProseMirror:

import { prosemirrorToPortableText, portableTextToProsemirror } from "emdash";

// Da ProseMirror (editor) a Portable Text (archiviazione)
const portableText = prosemirrorToPortableText(prosemirrorDoc);

// Da Portable Text a ProseMirror
const prosemirrorDoc = portableTextToProsemirror(portableText);

Impostazioni del sito

Leggere le impostazioni globali del sito con getSiteSettings e getSiteSetting:

import { getSiteSettings, getSiteSetting } from "emdash";

// Ottenere tutte le impostazioni
const settings = await getSiteSettings();

// Ottenere una singola impostazione
const title = await getSiteSetting("title");

Le impostazioni sono di sola lettura dall’API di runtime. Usa l’API di amministrazione per aggiornarle.

Recuperare i menu di navigazione e iterare i loro elementi, inclusi i figli annidati:

import { getMenu, getMenus } from "emdash";

// Ottenere tutti i menu
const menus = await getMenus();

// Ottenere un menu specifico con i suoi elementi
const primaryMenu = await getMenu("primary");

if (primaryMenu) {
	primaryMenu.items.forEach(item => {
		console.log(item.label, item.url);
		// Elementi annidati per i dropdown
		item.children.forEach(child => console.log("  -", child.label));
	});
}

Tassonomie

Recuperare termini di tassonomia, un singolo termine, i termini di una voce o le voci per termine:

import { getTaxonomyTerms, getTerm, getEntryTerms, getEntriesByTerm } from "emdash";

// Ottenere tutti i termini di una tassonomia (struttura ad albero per le gerarchiche)
const categories = await getTaxonomyTerms("category");

// Ottenere un singolo termine
const news = await getTerm("category", "news");

// Ottenere i termini assegnati a una voce di contenuto
const postCategories = await getEntryTerms("posts", "post-123", "category");

// Ottenere le voci con un termine specifico
const newsPosts = await getEntriesByTerm("posts", "category", "news");

Aree widget

Recuperare le aree widget e i widget che contengono:

import { getWidgetArea, getWidgetAreas } from "emdash";

// Ottenere tutte le aree widget
const areas = await getWidgetAreas();

// Ottenere un'area widget specifica con i suoi widget
const sidebar = await getWidgetArea("sidebar");

if (sidebar) {
	sidebar.widgets.forEach(widget => {
		console.log(widget.type, widget.title);
	});
}

Sezioni

Recuperare le sezioni e filtrarle:

import { getSection, getSections } from "emdash";

// Ottenere tutte le sezioni (paginate)
const { items, nextCursor } = await getSections();

// Filtrare le sezioni
const { items: themeSections } = await getSections({ source: "theme" });
const { items: results } = await getSections({ search: "newsletter" });

// Ottenere una singola sezione per slug
const cta = await getSection("newsletter-cta");

getSections(options?) restituisce { items: Section[]; nextCursor?: string }. Le opzioni sono source ("theme" | "user" | "import"), search, limit (predefinito 50, max 100) e cursor.

Ricerca

Eseguire una ricerca globale attraverso le collezioni. I risultati includono frammenti evidenziati:

import { search } from "emdash";

const results = await search("hello world", {
	collections: ["posts", "pages"],
	status: "published",
	limit: 20,
});

// search() risolve in { items, nextCursor? }
results.items.forEach(result => {
	console.log(result.title);
	console.log(result.snippet); // Contiene tag <mark>
	console.log(result.score);
});

// Paginare: passa il nextCursor precedente come `cursor` per ottenere la pagina successiva.
// nextCursor è undefined quando non ci sono più risultati.
if (results.nextCursor) {
	const next = await search("hello world", {
		collections: ["posts", "pages"],
		limit: 20,
		cursor: results.nextCursor,
	});
}

Gestione degli errori

EmDash esporta classi di errore per gestire fallimenti specifici. L’esempio seguente cattura errori di validazione e schema:

import {
  EmDashDatabaseError,
  EmDashValidationError,
  EmDashStorageError,
  SchemaError,
} from "emdash";

try {
  await repo.create({ ... });
} catch (error) {
  if (error instanceof EmDashValidationError) {
    console.error("Validazione fallita:", error.message);
  }
  if (error instanceof SchemaError) {
    console.error("Errore di schema:", error.code, error.details);
  }
}