Interroger le contenu

Sur cette page

EmDash fournit des fonctions de requête pour récupérer du contenu dans vos pages et composants Astro. Elles suivent le modèle des live content collections d’Astro et renvoient des résultats structurés avec gestion des erreurs.

Fonctions de requête

EmDash exporte deux fonctions principales :

FonctionRôleRetour
getEmDashCollectionToutes les entrées d’un type de contenu{ entries, error }
getEmDashEntryUne entrée par ID ou slug{ entry, error, isPreview }

Import depuis emdash :

import { getEmDashCollection, getEmDashEntry } from "emdash";

Récupérer toutes les entrées

Utilisez getEmDashCollection pour charger toutes les entrées d’un type de contenu :

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

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

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

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

Filtrer par locale

Lorsque l’i18n est activée, filtrez par locale pour obtenir la langue souhaitée :

// Articles en français
const { entries: frenchPosts } = await getEmDashCollection("posts", {
	locale: "fr",
	status: "published",
});

// Locale de la requête courante
const { entries: localizedPosts } = await getEmDashCollection("posts", {
	locale: Astro.currentLocale,
	status: "published",
});

Pour une entrée unique, passez locale en troisième argument :

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

Sans locale, la locale de la requête s’applique. S’il manque une traduction, la chaîne de repli est utilisée.

Filtrer par statut

Uniquement publié ou uniquement brouillon :

// Articles publiés
const { entries: published } = await getEmDashCollection("posts", {
	status: "published",
});

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

Limiter les résultats

// Les 5 articles les plus récents
const { entries: recentPosts } = await getEmDashCollection("posts", {
	status: "published",
	limit: 5,
});

Filtrer par taxonomie

Par catégorie, tag ou terme personnalisé :

// Articles dans la catégorie "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

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

// Plusieurs valeurs (OU)
const { entries: featuredNews } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: ["news", "featured"] },
});

Le filtre where applique une logique OU lorsque plusieurs valeurs sont fournies pour une même taxonomie.

Gestion des erreurs

Vérifiez les erreurs lorsque la fiabilité compte :

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

if (error) {
	console.error("Failed to load posts:", error);
	return new Response("Server error", { status: 500 });
}

Récupérer une entrée

getEmDashEntry charge une entrée par 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("Server error", { status: 500 });
}

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

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

Type de retour

getEmDashEntry renvoie un objet résultat :

interface EntryResult<T> {
	entry: ContentEntry<T> | null; // null si introuvable
	error?: Error; // Erreurs réelles uniquement (pas « introuvable »)
	isPreview: boolean; // true si aperçu / brouillon
}

interface ContentEntry<T> {
	id: string;
	data: T;
	edit: EditProxy; // Annotations pour l’édition visuelle
}

L’objet data contient tous les champs du type. Le proxy edit fournit les annotations d’édition visuelle (voir ci-dessous).

Mode aperçu

EmDash gère l’aperçu via le middleware. Si l’URL contient un _preview valide, le contexte est configuré ; les fonctions de requête servent le brouillon sans paramètres spéciaux :

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

const { slug } = Astro.params;

// Pas de logique d’aperçu spéciale — le middleware s’en charge
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);

if (error) {
  return new Response("Server error", { status: 500 });
}

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

{isPreview && (
  <div class="preview-banner">
    Aperçu. Ce contenu n’est pas publié.
  </div>
)}

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

Édition visuelle

Chaque entrée inclut un proxy edit pour annoter vos modèles. Étalez-le sur les éléments pour l’édition inline des éditeurs authentifiés :

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

En mode édition, {...entry.edit.title} produit un attribut data-emdash-ref pour la barre d’outils. En production, les spreads ne produisent rien — coût d’exécution nul.

Tri

getEmDashCollection ne garantit pas l’ordre. Triez dans le modèle :

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

// Par date de publication, plus récent d’abord
const sorted = posts.sort(
	(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);

Tris courants

// Alphabétique par titre
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));

// Champ order personnalisé
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));

// Aléatoire
posts.sort(() => Math.random() - 0.5);

Types TypeScript

Générez les types pour vos collections :

npx emdash types

Cela crée .emdash/types.ts avec une interface par collection :

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

const { entries: posts } = await getEmDashCollection<Post>("posts");

const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");

Statique vs rendu serveur

Le contenu EmDash fonctionne en statique et en SSR.

Statique (prérendu)

Avec getStaticPaths pour générer les routes au 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);
---

Rendu serveur

Pour le SSR, interrogez directement :

---
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("Server error", { status: 500 });
}

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

Performances

Mise en cache

EmDash s’appuie sur les live content collections d’Astro avec cache automatique. En SSR, ajoutez des en-têtes HTTP si besoin :

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

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

Éviter les requêtes redondantes

Interrogez une fois et passez les données aux composants :

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

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} />

Étapes suivantes