Consultar conteúdo

Nesta página

EmDash fornece funções de consulta para recuperar conteúdo em suas páginas e componentes Astro. Essas funções seguem o padrão de coleções de conteúdo ao vivo do Astro, retornando resultados estruturados com tratamento de erros.

Funções de consulta

EmDash exporta duas funções de consulta principais:

FunçãoPropósitoRetorna
getEmDashCollectionRecuperar todas as entradas de um tipo de conteúdo{ entries, error }
getEmDashEntryRecuperar uma única entrada por ID ou slug{ entry, error, isPreview }

Importe-as de emdash:

import { getEmDashCollection, getEmDashEntry } from "emdash";

Obter todas as entradas

Use getEmDashCollection para recuperar todas as entradas de um tipo de conteúdo:

---
import { getEmDashCollection } from "emdash";

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

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

<ul>
  {posts.map((post) => (
    <li>{post.data.title}</li>
  ))}
</ul>

Filtrar por localidade

Quando i18n está habilitado, filtre por localidade para recuperar conteúdo em um idioma específico:

// Posts em francês
const { entries: frenchPosts } = await getEmDashCollection("posts", {
	locale: "fr",
	status: "published",
});

// Usar a localidade da solicitação atual
const { entries: localizedPosts } = await getEmDashCollection("posts", {
	locale: Astro.currentLocale,
	status: "published",
});

Para entradas individuais, passe locale como terceiro argumento:

const { entry: post } = await getEmDashEntry("posts", "my-post", {
	locale: Astro.currentLocale,
});

Quando locale é omitido, usa por padrão a localidade atual da solicitação. Se não existir tradução para a localidade solicitada, a cadeia de fallback é seguida.

Filtrar por status

Recuperar apenas conteúdo publicado ou rascunho:

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

// Apenas rascunhos
const { entries: drafts } = await getEmDashCollection("posts", {
	status: "draft",
});

Limitar resultados

Restringir o número de entradas retornadas:

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

Filtrar por taxonomia

Filtrar entradas por categoria, tag ou termos de taxonomia personalizados:

// Posts na categoria "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

// Posts com a tag "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { tag: "javascript" },
});

// Posts que correspondem a qualquer um de vários termos
const { entries: featuredNews } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: ["news", "featured"] },
});

O filtro where usa lógica OU quando vários valores são fornecidos para uma única taxonomia.

Tratamento de erros

Sempre verifique erros quando a confiabilidade é importante:

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

if (error) {
	// Registrar e tratar elegantemente
	console.error("Falha ao carregar posts:", error);
	return new Response("Erro do servidor", { status: 500 });
}

Obter uma única entrada

Use getEmDashEntry para recuperar uma entrada por seu ID ou slug:

---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";

const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);

if (error) {
  return new Response("Erro do servidor", { status: 500 });
}

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

<article>
  <h1>{post.data.title}</h1>
  <PortableText value={post.data.content} />
</article>

Tipo de retorno de entrada

getEmDashEntry retorna um objeto de resultado:

interface EntryResult<T> {
	entry: ContentEntry<T> | null; // null se não encontrado
	error?: Error; // Definido apenas para erros reais (não "não encontrado")
	isPreview: boolean; // true se visualizando conteúdo de visualização/rascunho
}

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

O objeto data dentro de entry contém todos os campos definidos para o tipo de conteúdo. O proxy edit fornece anotações de edição visual (veja abaixo).

Modo de visualização

EmDash trata a visualização automaticamente via middleware. Quando uma URL contém um token _preview válido, o middleware o verifica e configura o contexto da solicitação. Suas funções de consulta então servem conteúdo rascunho sem parâmetros especiais:

---
import { getEmDashEntry } from "emdash";

const { slug } = Astro.params;

// Não é necessário tratamento especial de visualização — o middleware faz isso automaticamente
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);

if (error) {
  return new Response("Erro do servidor", { status: 500 });
}

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

{isPreview && (
  <div class="preview-banner">
    Visualizando pré-visualização. Este conteúdo não está publicado.
  </div>
)}

<article>
  <h1>{entry.data.title}</h1>
  <PortableText value={entry.data.content} />
</article>

Edição visual

Cada entrada retornada pelas funções de consulta inclui um proxy edit para anotar seus templates. Expanda-o em elementos para habilitar edição inline para editores autenticados:

<article {...entry.edit}>
  <h1 {...entry.edit.title}>{entry.data.title}</h1>
  <div {...entry.edit.content}>
    <PortableText value={entry.data.content} />
  </div>
</article>

No modo de edição, {...entry.edit.title} produz um atributo data-emdash-ref que a barra de ferramentas de edição visual usa para habilitar a edição inline. Em produção, as expansões do proxy não produzem saída.

Ordenar resultados

getEmDashCollection não garante ordem de classificação. Ordene os resultados em seu template:

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

// Ordenar por data de publicação, mais recente primeiro
const sorted = posts.sort(
	(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);

Padrões comuns de ordenação

// Alfabeticamente por título
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));

// Por campo de ordem personalizado
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));

// Ordem aleatória
posts.sort(() => Math.random() - 0.5);

Tipos TypeScript

Gerar tipos TypeScript para suas coleções:

npx emdash types

Isso cria .emdash/types.ts com interfaces para cada coleção. Use-as para segurança de tipos:

import { getEmDashCollection, getEmDashEntry } from "emdash";
import type { Post } from "../.emdash/types";

// Consulta de coleção com segurança de tipos
const { entries: posts } = await getEmDashCollection<Post>("posts");
// posts é ContentEntry<Post>[]

// Consulta de entrada com segurança de tipos
const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");
// post é ContentEntry<Post> | null

Renderização estática vs. servidor

Conteúdo EmDash funciona com páginas estáticas e renderizadas no servidor.

Estático (Pré-renderizado)

Para páginas estáticas, use getStaticPaths para gerar rotas no momento da build:

---
import { getEmDashCollection, getEmDashEntry } from "emdash";

export async function getStaticPaths() {
  const { entries: posts } = await getEmDashCollection("posts", {
    status: "published",
  });

  return posts.map((post) => ({
    params: { slug: post.data.slug },
  }));
}

const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
---

Renderizado no servidor

Para páginas renderizadas no servidor, consulte o conteúdo diretamente:

---
export const prerender = false;

import { getEmDashEntry } from "emdash";

const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);

if (error) {
  return new Response("Erro do servidor", { status: 500 });
}

if (!post) {
  return new Response(null, { status: 404 });
}
---

Considerações de desempenho

Cache

EmDash usa coleções de conteúdo ao vivo do Astro, que tratam o cache automaticamente. Para páginas renderizadas no servidor, considere adicionar cabeçalhos de cache HTTP:

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

// Cache por 5 minutos
Astro.response.headers.set("Cache-Control", "public, max-age=300");
---

Evitar consultas redundantes

Consulte uma vez e passe dados para componentes:

---
import { getEmDashCollection } from "emdash";
import PostList from "../components/PostList.astro";
import Sidebar from "../components/Sidebar.astro";

// Consultar uma vez
const { entries: posts } = await getEmDashCollection("posts", {
  status: "published",
});

const featured = posts.filter((p) => p.data.featured);
const recent = posts.slice(0, 5);
---

<PostList posts={featured} />
<Sidebar posts={recent} />

Próximos passos