Referencia de la API de JavaScript

En esta página

EmDash exporta funciones para consultar contenido y trabajar con vista previa, configuración, menús, taxonomías, áreas de widgets, secciones y búsqueda.

Consultas de contenido

Las funciones de consulta de EmDash siguen el patrón de colecciones de contenido en vivo de Astro, devolviendo { entries, error } o { entry, error } para un manejo elegante de errores.

getEmDashCollection()

Obtiene todas las entradas de una colección. El siguiente ejemplo carga todas las publicaciones y verifica si hay errores:

import { getEmDashCollection } from "emdash";

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

if (error) {
	console.error("Failed to load posts:", error);
}

Parámetros

ParámetroTipoDescripción
collectionstringSlug de la colección
optionsCollectionFilterOpciones de filtro opcionales

Opciones

El parámetro options acepta el siguiente filtro:

interface CollectionFilter {
	status?: "draft" | "published" | "archived";
	limit?: number;
	where?: Record<string, string | string[]>; // Filter by field or taxonomy
}

Valor de retorno

La función se resuelve en un CollectionResult:

interface CollectionResult<T> {
	entries: ContentEntry<T>[]; // Empty array if error or none found
	error?: Error; // Set if query failed
}

Ejemplos

Los siguientes ejemplos filtran por estado y taxonomía, limitan resultados y manejan errores:

// Get all published posts
const { entries: posts } = await getEmDashCollection("posts", {
	status: "published",
});

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

// Filter by taxonomy
const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

// Handle errors
const { entries, error } = await getEmDashCollection("posts");
if (error) {
	return new Response("Server error", { status: 500 });
}

getEmDashEntry()

Obtiene una entrada individual por slug o ID. El siguiente ejemplo carga una publicación y redirige cuando falta:

import { getEmDashEntry } from "emdash";

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

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

Parámetros

ParámetroTipoDescripción
collectionstringSlug de la colección
slugOrIdstringSlug o ID de la entrada
options{ locale?: string }Opcional. Locale para resolución de slug

El modo de vista previa se maneja automáticamente: el middleware detecta tokens _preview y sirve contenido borrador a través de AsyncLocalStorage. El parámetro opcional options solo acepta un locale para la resolución de slug; el estado de vista previa no requiere parámetro.

Valor de retorno

La función se resuelve en un EntryResult:

interface EntryResult<T> {
	entry: ContentEntry<T> | null; // null if not found
	error?: Error; // Set only for actual errors, not "not found"
	isPreview: boolean; // true if draft content is being served
}

Ejemplos

Los siguientes ejemplos obtienen por slug e ID, leen el estado de vista previa y distinguen errores de “no encontrado”:

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

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

// Preview is automatic — isPreview is true when a valid _preview token is present
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);

// Handle errors vs not-found
if (error) {
	return new Response("Server error", { status: 500 });
}
if (!entry) {
	return Astro.redirect("/404");
}

Tipos de contenido

ContentEntry

Las funciones de consulta devuelven entradas con la siguiente forma:

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

El proxy edit proporciona anotaciones de edición visual. Distribúyalo en elementos para habilitar la edición en línea: {...entry.edit.title}. En producción, esto no produce salida.

El objeto data contiene todos los campos de contenido más campos del sistema:

  • id - Identificador único
  • slug - Identificador amigable para URL
  • status - “draft” | “published” | “archived”
  • createdAt - Marca de tiempo ISO
  • updatedAt - Marca de tiempo ISO
  • publishedAt - Marca de tiempo ISO o null
  • Más todos los campos personalizados definidos en su esquema de colección

Sistema de vista previa

generatePreviewToken()

Genera un token de vista previa para contenido borrador. El siguiente ejemplo crea un token que expira en una hora:

import { generatePreviewToken } from "emdash";

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

verifyPreviewToken()

Verifica un token de vista previa y lee su carga útil:

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 is "collection:id" format, e.g. "posts:my-draft-post"
}

isPreviewRequest()

Verifica si una solicitud incluye un token de vista previa y luego lo lee:

import { isPreviewRequest, getPreviewToken } from "emdash";

if (isPreviewRequest(Astro.url)) {
	const token = getPreviewToken(Astro.url);
	// Verify and show preview content
}

Convertidores de contenido

Convertir entre formatos Portable Text y ProseMirror:

import { prosemirrorToPortableText, portableTextToProsemirror } from "emdash";

// From ProseMirror (editor) to Portable Text (storage)
const portableText = prosemirrorToPortableText(prosemirrorDoc);

// From Portable Text to ProseMirror
const prosemirrorDoc = portableTextToProsemirror(portableText);

Configuración del sitio

Leer configuración de todo el sitio con getSiteSettings y getSiteSetting:

import { getSiteSettings, getSiteSetting } from "emdash";

// Get all settings
const settings = await getSiteSettings();

// Get single setting
const title = await getSiteSetting("title");

La configuración es de solo lectura desde la API de tiempo de ejecución. Use la API de administración para actualizarla.

Menús

Obtener menús de navegación e iterar sobre sus elementos, incluidos los hijos anidados:

import { getMenu, getMenus } from "emdash";

// Get all menus
const menus = await getMenus();

// Get specific menu with items
const primaryMenu = await getMenu("primary");

if (primaryMenu) {
	primaryMenu.items.forEach(item => {
		console.log(item.label, item.url);
		// Nested items for dropdowns
		item.children.forEach(child => console.log("  -", child.label));
	});
}

Taxonomías

Obtener términos de taxonomía, un término individual, los términos de una entrada o entradas por término:

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

// Get all terms for a taxonomy (tree structure for hierarchical)
const categories = await getTaxonomyTerms("category");

// Get single term
const news = await getTerm("category", "news");

// Get terms assigned to a content entry
const postCategories = await getEntryTerms("posts", "post-123", "category");

// Get entries with a specific term
const newsPosts = await getEntriesByTerm("posts", "category", "news");

Áreas de widgets

Obtener áreas de widgets y los widgets que contienen:

import { getWidgetArea, getWidgetAreas } from "emdash";

// Get all widget areas
const areas = await getWidgetAreas();

// Get specific widget area with widgets
const sidebar = await getWidgetArea("sidebar");

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

Secciones

Obtener secciones y filtrarlas:

import { getSection, getSections } from "emdash";

// Get all sections (paginated)
const { items, nextCursor } = await getSections();

// Filter sections
const { items: themeSections } = await getSections({ source: "theme" });
const { items: results } = await getSections({ search: "newsletter" });

// Get a single section by slug
const cta = await getSection("newsletter-cta");

getSections(options?) devuelve { items: Section[]; nextCursor?: string }. Las opciones son source ("theme" | "user" | "import"), search, limit (predeterminado 50, máximo 100) y cursor.

Búsqueda

Ejecutar una búsqueda global en colecciones. Los resultados incluyen fragmentos resaltados:

import { search } from "emdash";

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

// search() resolves to { items, nextCursor? }
results.items.forEach(result => {
	console.log(result.title);
	console.log(result.snippet); // Contains <mark> tags
	console.log(result.score);
});

Manejo de errores

EmDash exporta clases de error para manejar fallos específicos. El siguiente ejemplo captura errores de validación y esquema:

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);
  }
}