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ámetro | Tipo | Descripción |
|---|---|---|
collection | string | Slug de la colección |
options | CollectionFilter | Opciones 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ámetro | Tipo | Descripción |
|---|---|---|
collection | string | Slug de la colección |
slugOrId | string | Slug 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 únicoslug- Identificador amigable para URLstatus- “draft” | “published” | “archived”createdAt- Marca de tiempo ISOupdatedAt- Marca de tiempo ISOpublishedAt- 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);
}
}