Referência da API JavaScript

Nesta página

EmDash exporta funções para consultar conteúdo e trabalhar com pré-visualização, configurações, menus, taxonomias, áreas de widgets, seções e busca.

Consultas de conteúdo

As funções de consulta do EmDash seguem o padrão de coleções de conteúdo ao vivo do Astro, retornando { entries, error } ou { entry, error } para tratamento elegante de erros.

getEmDashCollection()

Buscar todas as entradas de uma coleção. O exemplo a seguir carrega todos os posts e verifica erros:

import { getEmDashCollection } from "emdash";

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

if (error) {
	console.error("Falha ao carregar posts:", error);
}

Parâmetros

ParâmetroTipoDescrição
collectionstringSlug da coleção
optionsCollectionFilterOpções de filtro opcionais

Opções

O parâmetro options aceita o seguinte filtro:

interface CollectionFilter {
	status?: "draft" | "published" | "archived";
	limit?: number;
	cursor?: string; // Paginação keyset — passe um `nextCursor` anterior
	offset?: number; // Paginação offset — pular N entradas (usar com `limit`)
	where?: Record<string, string | string[]>; // Filtrar por campo ou taxonomia
}

Retorna

A função resolve para um CollectionResult:

interface CollectionResult<T> {
	entries: ContentEntry<T>[]; // Array vazio em caso de erro ou nenhum encontrado
	error?: Error; // Definido se a consulta falhou
	nextCursor?: string; // Cursor para a próxima página keyset, se houver
	hasMore?: boolean; // Se existem mais entradas além desta página (quando `limit` é definido)
}

Exemplos

Os exemplos a seguir filtram por status e taxonomia, limitam resultados e tratam erros:

// Obter todos os posts publicados
const { entries: posts } = await getEmDashCollection("posts", {
	status: "published",
});

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

// Filtrar por taxonomia
const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

// Página de arquivo numerada (ex. /page/3) com paginação 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" },
});

// Tratar erros
const { entries, error } = await getEmDashCollection("posts");
if (error) {
	return new Response("Erro do servidor", { status: 500 });
}

getEmDashEntry()

Buscar uma entrada individual por slug ou ID. O exemplo a seguir carrega um post e redireciona quando não existe:

import { getEmDashEntry } from "emdash";

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

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

Parâmetros

ParâmetroTipoDescrição
collectionstringSlug da coleção
slugOrIdstringSlug ou ID da entrada
options{ locale?: string }Opcional. Locale para resolução de slug

O modo de pré-visualização é tratado automaticamente — o middleware detecta tokens _preview e serve conteúdo rascunho via AsyncLocalStorage. O parâmetro opcional options aceita apenas um locale para resolução de slug; o estado de pré-visualização não requer parâmetro.

Retorna

A função resolve para um EntryResult:

interface EntryResult<T> {
	entry: ContentEntry<T> | null; // null se não encontrado
	error?: Error; // Definido apenas para erros reais, não para "não encontrado"
	isPreview: boolean; // true se conteúdo rascunho está sendo servido
}

Exemplos

Os exemplos a seguir buscam por slug e ID, leem o estado de pré-visualização e distinguem erros de não-encontrado:

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

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

// Pré-visualização é automática — isPreview é true quando um token _preview válido está presente
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);

// Tratar erros vs não-encontrado
if (error) {
	return new Response("Erro do servidor", { status: 500 });
}
if (!entry) {
	return Astro.redirect("/404");
}

Tipos de conteúdo

ContentEntry

Funções de consulta retornam entradas na seguinte forma:

interface ContentEntry<T = Record<string, unknown>> {
	id: string;
	data: T;
	edit: EditProxy; // Anotações de edição visual
}

O proxy edit fornece anotações de edição visual. Espalhe-o nos elementos para habilitar edição inline: {...entry.edit.title}. Em produção, não produz saída.

O objeto data contém todos os campos de conteúdo mais campos do sistema:

  • id - Identificador único
  • slug - Identificador amigável para URL
  • status - “draft” | “published” | “archived”
  • createdAt - Timestamp ISO
  • updatedAt - Timestamp ISO
  • publishedAt - Timestamp ISO ou null
  • Mais todos os campos personalizados definidos no esquema da coleção

Sistema de pré-visualização

generatePreviewToken()

Gerar um token de pré-visualização para conteúdo rascunho. O exemplo a seguir cria um token que expira em uma hora:

import { generatePreviewToken } from "emdash";

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

verifyPreviewToken()

Verificar um token de pré-visualização e ler seu payload:

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 está no formato "collection:id", ex. "posts:my-draft-post"
}

isPreviewRequest()

Verificar se uma requisição inclui um token de pré-visualização, depois lê-lo:

import { isPreviewRequest, getPreviewToken } from "emdash";

if (isPreviewRequest(Astro.url)) {
	const token = getPreviewToken(Astro.url);
	// Verificar e mostrar conteúdo de pré-visualização
}

Conversores de conteúdo

Converter entre formatos Portable Text e ProseMirror:

import { prosemirrorToPortableText, portableTextToProsemirror } from "emdash";

// De ProseMirror (editor) para Portable Text (armazenamento)
const portableText = prosemirrorToPortableText(prosemirrorDoc);

// De Portable Text para ProseMirror
const prosemirrorDoc = portableTextToProsemirror(portableText);

Configurações do site

Ler configurações globais do site com getSiteSettings e getSiteSetting:

import { getSiteSettings, getSiteSetting } from "emdash";

// Obter todas as configurações
const settings = await getSiteSettings();

// Obter configuração individual
const title = await getSiteSetting("title");

Configurações são somente leitura pela API de runtime. Use a API de administração para atualizá-las.

Buscar menus de navegação e iterar seus itens, incluindo filhos aninhados:

import { getMenu, getMenus } from "emdash";

// Obter todos os menus
const menus = await getMenus();

// Obter menu específico com itens
const primaryMenu = await getMenu("primary");

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

Taxonomias

Buscar termos de taxonomia, um termo individual, os termos de uma entrada ou entradas por termo:

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

// Obter todos os termos de uma taxonomia (estrutura de árvore para hierárquicas)
const categories = await getTaxonomyTerms("category");

// Obter um termo individual
const news = await getTerm("category", "news");

// Obter termos atribuídos a uma entrada de conteúdo
const postCategories = await getEntryTerms("posts", "post-123", "category");

// Obter entradas com um termo específico
const newsPosts = await getEntriesByTerm("posts", "category", "news");

Áreas de widgets

Buscar áreas de widgets e os widgets que contêm:

import { getWidgetArea, getWidgetAreas } from "emdash";

// Obter todas as áreas de widgets
const areas = await getWidgetAreas();

// Obter área de widgets específica com widgets
const sidebar = await getWidgetArea("sidebar");

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

Seções

Buscar seções e filtrá-las:

import { getSection, getSections } from "emdash";

// Obter todas as seções (paginadas)
const { items, nextCursor } = await getSections();

// Filtrar seções
const { items: themeSections } = await getSections({ source: "theme" });
const { items: results } = await getSections({ search: "newsletter" });

// Obter uma seção individual por slug
const cta = await getSection("newsletter-cta");

getSections(options?) retorna { items: Section[]; nextCursor?: string }. As opções são source ("theme" | "user" | "import"), search, limit (padrão 50, máx. 100) e cursor.

Busca

Executar uma busca global através das coleções. Resultados incluem trechos destacados:

import { search } from "emdash";

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

// search() resolve para { items, nextCursor? }
results.items.forEach(result => {
	console.log(result.title);
	console.log(result.snippet); // Contém tags <mark>
	console.log(result.score);
});

// Paginar: passe o nextCursor anterior como `cursor` para obter a próxima página.
// nextCursor é undefined quando não há mais resultados.
if (results.nextCursor) {
	const next = await search("hello world", {
		collections: ["posts", "pages"],
		limit: 20,
		cursor: results.nextCursor,
	});
}

Tratamento de erros

EmDash exporta classes de erro para tratar falhas específicas. O exemplo a seguir captura erros de validação e schema:

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

try {
  await repo.create({ ... });
} catch (error) {
  if (error instanceof EmDashValidationError) {
    console.error("Validação falhou:", error.message);
  }
  if (error instanceof SchemaError) {
    console.error("Erro de schema:", error.code, error.details);
  }
}