Referência da API JavaScript
O EmDash exporta funções para consultar conteúdo, gerenciar mídia e trabalhar com o banco de dados.
Consultas de Conteúdo
Seção intitulada “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 um tratamento de erros elegante.
getEmDashCollection()
Seção intitulada “getEmDashCollection()”Busca todas as entradas de uma coleção.
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) { console.error("Failed to load posts:", error);}Parâmetros
Seção intitulada “Parâmetros”| Parâmetro | Tipo | Descrição |
|---|---|---|
collection | string | Slug da coleção |
options | CollectionFilter | Opções de filtro opcionais |
interface CollectionFilter { status?: "draft" | "published" | "archived"; limit?: number; where?: Record<string, string | string[]>; // Filter by field or taxonomy}Retorna
Seção intitulada “Retorna”interface CollectionResult<T> { entries: ContentEntry<T>[]; // Empty array if error or none found error?: Error; // Set if query failed}Exemplos
Seção intitulada “Exemplos”// Get all published postsconst { entries: posts } = await getEmDashCollection("posts", { status: "published",});
// Obter os 5 posts mais recentesconst { entries: latest } = await getEmDashCollection("posts", { limit: 5, status: "published",});
// Filtrar por taxonomiaconst { entries: newsPosts } = await getEmDashCollection("posts", { status: "published", where: { category: "news" },});
// Lidar com errosconst { entries, error } = await getEmDashCollection("posts");if (error) { return new Response("Server error", { status: 500 });}getEmDashEntry()
Seção intitulada “getEmDashEntry()”Busca uma única entrada por slug ou ID.
import { getEmDashEntry } from "emdash";
const { entry: post, error } = await getEmDashEntry("posts", "my-post-slug");
if (!post) { return Astro.redirect("/404");}Parâmetros
Seção intitulada “Parâmetros”| Parâmetro | Tipo | Descrição |
|---|---|---|
collection | string | Slug da coleção |
slugOrId | string | Slug ou ID da entrada |
O modo de visualização é tratado automaticamente — o middleware detecta tokens _preview e serve conteúdo de rascunho via AsyncLocalStorage. Nenhum parâmetro de opções é necessário.
Retorna
Seção intitulada “Retorna”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}Exemplos
Seção intitulada “Exemplos”// Get by slugconst { entry: post } = await getEmDashEntry("posts", "hello-world");
// Obter por IDconst { entry: post } = await getEmDashEntry("posts", "01HXK5MZSN0FVXT2Q3KPRT9M7D");
// A visualização é automática — isPreview é verdadeiro quando um token _preview válido está presenteconst { entry, isPreview, error } = await getEmDashEntry("posts", slug);
// Lidar com erros vs não encontradoif (error) { return new Response("Server error", { status: 500 });}if (!entry) { return Astro.redirect("/404");}Tipos de Conteúdo
Seção intitulada “Tipos de Conteúdo”ContentEntry
Seção intitulada “ContentEntry”A entrada retornada pelas funções de consulta:
interface ContentEntry<T = Record<string, unknown>> { id: string; data: T; edit: EditProxy; // Visual editing annotations}O proxy edit fornece anotações de edição visual. Espalhe-o em elementos para habilitar a edição inline: {...entry.edit.title}. Em produção, isso não gera saída.
O objeto data contém todos os campos de conteúdo mais os campos do sistema:
id- Identificador únicoslug- Identificador amigável para URLstatus- “draft” | “published” | “archived”createdAt- Timestamp ISOupdatedAt- Timestamp ISOpublishedAt- Timestamp ISO ou null- Mais todos os campos personalizados definidos no esquema da sua coleção
Funções do Banco de Dados
Seção intitulada “Funções do Banco de Dados”createDatabase()
Seção intitulada “createDatabase()”Cria uma conexão com o banco de dados.
import { createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });runMigrations()
Seção intitulada “runMigrations()”Executa migrações pendentes do banco de dados.
import { createDatabase, runMigrations } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const { applied } = await runMigrations(db);console.log(`Aplicadas ${applied.length} migrações`);getMigrationStatus()
Seção intitulada “getMigrationStatus()”Verifica o status da migração.
import { createDatabase, getMigrationStatus } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const status = await getMigrationStatus(db);// { applied: ["0001_core", ...], pending: [] }Repositórios
Seção intitulada “Repositórios”Acesso de baixo nível aos dados através de repositórios.
ContentRepository
Seção intitulada “ContentRepository”import { ContentRepository, createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const repo = new ContentRepository(db);
// Encontrar váriosconst { items, nextCursor } = await repo.findMany("posts", { limit: 10, where: { status: "published" },});
// Encontrar por IDconst post = await repo.findById("posts", "01HXK5MZSN...");
// Criarconst newPost = await repo.create({ type: "posts", slug: "new-post", data: { title: "New Post", content: [] }, status: "draft",});
// Atualizarconst updated = await repo.update("posts", "01HXK5MZSN...", { data: { title: "Updated Title" },});
// Excluirawait repo.delete("posts", "01HXK5MZSN...");MediaRepository
Seção intitulada “MediaRepository”import { MediaRepository, createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const repo = new MediaRepository(db);
// Listar mídiaconst { items } = await repo.findMany({ limit: 20 });
// Obter por IDconst media = await repo.findById("01HXK5MZSN...");
// Criar (após upload)const newMedia = await repo.create({ filename: "photo.jpg", mimeType: "image/jpeg", size: 12345, storageKey: "uploads/photo.jpg",});Registro de Esquema
Seção intitulada “Registro de Esquema”Gerenciamento programático de esquemas.
import { SchemaRegistry, createDatabase } from "emdash";
const db = createDatabase({ url: "file:./data.db" });const registry = new SchemaRegistry(db);
// Listar coleçõesconst collections = await registry.listCollections();
// Obter coleção com camposconst postsSchema = await registry.getCollectionWithFields("posts");
// Criar coleçãoawait registry.createCollection({ slug: "products", label: "Products", labelSingular: "Product", supports: ["drafts", "revisions"],});
// Adicionar campoawait registry.createField("products", { slug: "price", label: "Price", type: "number", required: true,});Sistema de Visualização
Seção intitulada “Sistema de Visualização”generatePreviewToken()
Seção intitulada “generatePreviewToken()”Gera um token de visualização para conteúdo de rascunho.
import { generatePreviewToken } from "emdash";
const token = await generatePreviewToken({ contentId: "posts:01HXK5MZSN...", secret: process.env.EMDASH_ADMIN_SECRET, expiresIn: 3600, // 1 hour});verifyPreviewToken()
Seção intitulada “verifyPreviewToken()”Verifica um token de visualização.
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 "coleção:id", ex: "posts:my-draft-post"}isPreviewRequest()
Seção intitulada “isPreviewRequest()”Verifica se uma requisição inclui um token de visualização.
import { isPreviewRequest, getPreviewToken } from "emdash";
if (isPreviewRequest(Astro.request)) { const token = getPreviewToken(Astro.request); // Verify and show preview content}Conversores de Conteúdo
Seção intitulada “Conversores de Conteúdo”Converte entre os 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 ProseMirrorconst prosemirrorDoc = portableTextToProsemirror(portableText);Configurações do Site
Seção intitulada “Configurações do Site”import { getSiteSettings, getSiteSetting } from "emdash";
// Obter todas as configuraçõesconst settings = await getSiteSettings();
// Obter uma única configuraçãoconst title = await getSiteSetting("siteTitle");As configurações são somente leitura a partir da API de tempo de execução. Use a API de administração para atualizá-las.
import { getMenu, getMenus } from "emdash";
// Obter todos os menusconst menus = await getMenus();
// Obter menu específico com itensconst primaryMenu = await getMenu("primary");
if (primaryMenu) { primaryMenu.items.forEach(item => { console.log(item.label, item.url); // Itens aninhados para menus suspensos item.children.forEach(child => console.log(" -", child.label)); });}Taxonomias
Seção intitulada “Taxonomias”import { getTaxonomyTerms, getTerm, getEntryTerms, getEntriesByTerm } from "emdash";
// Obter todos os termos para uma taxonomia (estrutura de árvore para hierárquicas)const categories = await getTaxonomyTerms("category");
// Obter um único termoconst news = await getTerm("category", "news");
// Obter termos atribuídos a uma entrada de conteúdoconst postCategories = await getEntryTerms("posts", "post-123", "category");
// Obter entradas com um termo específicoconst newsPosts = await getEntriesByTerm("posts", "category", "news");Áreas de Widgets
Seção intitulada “Áreas de Widgets”import { getWidgetArea, getWidgetAreas } from "emdash";
// Obter todas as áreas de widgetsconst areas = await getWidgetAreas();
// Obter área de widget específica com widgetsconst sidebar = await getWidgetArea("sidebar");
if (sidebar) { sidebar.widgets.forEach(widget => { console.log(widget.type, widget.title); });}import { getSection, getSections, getSectionCategories } from "emdash";
// Obter todas as seçõesconst sections = await getSections();
// Filtrar seçõesconst heroes = await getSections({ category: "hero" });const themeSections = await getSections({ source: "theme" });const results = await getSections({ search: "newsletter" });
// Obter uma única seçãoconst cta = await getSection("newsletter-cta");
// Obter categoriasconst categories = await getSectionCategories();import { search, searchCollection } from "emdash";
// Busca global em todas as coleçõesconst results = await search("hello world", { collections: ["posts", "pages"], status: "published", limit: 20,});
// Os resultados incluem trechos com destaquesresults.forEach(result => { console.log(result.title); console.log(result.snippet); // Contains <mark> tags console.log(result.score);});
// Busca específica por coleçãoconst posts = await searchCollection("posts", "typescript", { limit: 10,});Tratamento de Erros
Seção intitulada “Tratamento de Erros”A EmDash exporta classes de erro para lidar com falhas específicas:
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); }}