Référence de l’API JavaScript

Sur cette page

Cette page présente l’API publique que les pages, les layouts et les composants Astro utilisent pour lire et présenter un site EmDash. Elle ne répertorie pas tous les exports de la racine du paquet emdash : les dépôts de base de données, les gestionnaires d’API, les utilitaires de migration, les API de création de plugins et les autres éléments internes du serveur disposent de références distinctes ou sont destinés au code d’intégration du framework.

Le contrat d’API des modèles de site de cette référence répertorie chaque fonction que les modèles de site maintenus par EmDash importent depuis emdash. Les imports de type seul, comme MediaValue, relèvent de la documentation du modèle de données concerné. Les fonctions connexes sont documentées dans les mêmes sections lorsqu’elles aident l’auteur d’un site, mais la page ne couvre pas les exports de la racine qui n’ont aucun rapport.

Contrat d’API des modèles de site

Les modèles maintenus appellent ces helpers d’exécution :

FonctionUtilisée pour
decodeSlugDécoder un paramètre de route dynamique avant la recherche
getEmDashCollectionLire et filtrer les entrées d’une collection
getEmDashEntryLire une entrée par ID ou par slug
getMenuWithCacheHintAfficher un menu de navigation avec invalidation du cache
getSeoMetaRésoudre les valeurs du panneau SEO d’une entrée et les valeurs de repli du modèle
getSiteSettingsLire l’identité publique du site et d’autres paramètres globaux
getSiteSettingsWithCacheHintLire les paramètres globaux avec invalidation du cache
getTaxonomyTermsWithCacheHintAfficher des filtres de taxonomie avec invalidation du cache
getTermsForEntriesCharger par lots une taxonomie pour une liste d’entrées
sanitizeHrefRejeter les schémas d’URL dangereux avant d’afficher des liens stockés
searchRechercher du contenu publié dans plusieurs collections

Requêtes de contenu

Les fonctions de requête d’EmDash suivent le modèle des collections de contenu en direct d’Astro et renvoient { entries, error } ou { entry, error } afin de gérer les erreurs avec souplesse.

getEmDashCollection()

Récupère toutes les entrées d’une collection. L’exemple suivant charge tous les articles et vérifie la présence d’une erreur :

import { getEmDashCollection } from "emdash";

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

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

Paramètres

ParamètreTypeDescription
collectionstringSlug de la collection
optionsCollectionFilterOptions de filtre facultatives

Options

Le paramètre options accepte le filtre suivant :

interface WhereRange {
	gt?: string;
	gte?: string;
	lt?: string;
	lte?: string;
}

interface CollectionFilter {
	status?: "draft" | "published" | "archived";
	limit?: number;
	cursor?: string; // Keyset pagination — pass a previous `nextCursor`
	offset?: number; // Offset pagination — skip N entries (use with `limit`)
	where?: Record<string, string | string[] | WhereRange>;
	orderBy?: Record<string, "asc" | "desc">;
	locale?: string;
}

cursor et offset s’excluent mutuellement. Les clés de where peuvent désigner des champs de contenu, des taxonomies ou byline ; des objets de plage permettent les comparaisons ordonnées.

Valeur de retour

La fonction se résout en un CollectionResult :

interface CollectionResult<T> {
	entries: ContentEntry<T>[]; // Empty array if error or none found
	error?: Error; // Set if query failed
	cacheHint: CacheHint; // Tags and last-modified time for Astro route caching
	nextCursor?: string; // Cursor for the next keyset page, if any
	hasMore?: boolean; // Whether more entries exist beyond this page (when `limit` is set)
}

Exemples

Les exemples suivants filtrent par statut et par taxonomie, limitent les résultats et gèrent les erreurs :

// 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" },
});

// Numbered archive page (e.g. /page/3) with offset pagination
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" },
});

// Handle errors
const { entries, error } = await getEmDashCollection("posts");
if (error) {
	return new Response("Server error", { status: 500 });
}

getEmDashEntry()

Récupère une seule entrée par slug ou par ID. L’exemple suivant charge un article et affiche la page 404 du site lorsqu’il est introuvable :

import { getEmDashEntry } from "emdash";

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

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

Paramètres

ParamètreTypeDescription
collectionstringSlug de la collection
slugOrIdstringSlug ou ID de l’entrée
options{ locale?: string; references?: ReferenceSelection }Facultatif. Locale pour la résolution du slug, et champs de référence à charger

Le mode aperçu est géré automatiquement : lorsque la requête porte un jeton _preview valide, la requête renvoie le contenu en brouillon. L’état d’aperçu ne nécessite aucun paramètre.

references nomme les champs de référence à charger, indexés par slug de champ. true demande la première page avec la limite par défaut de 50 entrées ; la forme objet accepte un limit (100 au plus) et le cursor d’une page précédente. Les champs omis ne sont pas lus, et un appel qui omet l’option n’exécute aucune requête de référence.

Valeur de retour

La fonction se résout en un EntryResult :

interface EntryResult<T, R> {
	entry: ContentEntry<T, R> | null; // null if not found
	error?: Error; // Set only for actual errors, not "not found"
	isPreview: boolean; // true if draft content is being served
	fallbackLocale?: string; // Set when locale fallback returned another locale
	cacheHint: CacheHint; // Tags and last-modified time for Astro route caching
}

Exemples

Les exemples suivants récupèrent des entrées par slug et par ID, lisent l’état d’aperçu et distinguent les erreurs de l’absence de résultat :

// 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.rewrite("/404");
}

getTranslations()

Récupère les traductions disponibles d’une entrée à partir du slug de la collection et de l’ID en base de données :

import { getTranslations } from "emdash";

const { translations, error } = await getTranslations("posts", post.data.id);

Le résultat contient le translationGroup partagé, un tableau translations et un error facultatif. Chaque résumé de traduction comprend id, locale, slug et status.

resolveEmDashPath()

Résout un chemin public à partir des modèles d’URL configurés pour les collections routables :

import { resolveEmDashPath } from "emdash";

const result = await resolveEmDashPath("/blog/hello-world");

if (result) {
	console.log(result.collection, result.entry.data.title);
}

Le résultat contient la collection correspondante, l’entry et les params de la route. La fonction renvoie null lorsqu’aucun modèle d’URL configuré ne correspond.

getEditMeta()

Lit les métadonnées d’édition visuelle non énumérables attachées à une valeur Portable Text :

import { getEditMeta } from "emdash";

const meta = getEditMeta(post.data.content);

Elle renvoie { collection, id, field } pour une valeur annotée, ou undefined lorsque la valeur n’a pas d’annotation.

Types de contenu

ContentEntry

Les fonctions de requête renvoient les entrées sous la forme suivante :

interface ContentEntry<T = Record<string, unknown>, R = ReferencePages> {
	id: string;
	data: T;
	references?: R; // One page per reference field requested; absent otherwise
	edit: EditProxy; // Visual editing annotations
}

Le proxy edit fournit des annotations d’édition visuelle. Étalez-le sur des éléments pour activer l’édition en ligne : {...entry.edit.title}. En dehors du mode édition, il ne produit aucune sortie.

L’objet data contient tous les champs de contenu ainsi que les champs système :

  • id - Identifiant unique
  • slug - Identifiant adapté aux URL
  • status - “draft” | “published” | “archived”
  • createdAt - Date de création, sous forme de Date
  • updatedAt - Date de dernière mise à jour, sous forme de Date
  • publishedAt - Date de publication, sous forme de Date ou null ; conservée lorsque le contenu est dépublié
  • Ainsi que tous les champs personnalisés définis dans le schéma de votre collection

ReferencePage

entry.references contient une page par champ de référence demandé à getEmDashEntry, indexée par slug de champ :

interface ReferencePage<T = Record<string, unknown>> {
	entries: ContentEntry<T>[];
	nextCursor?: string; // Set when the field holds more entries than the limit
}

Chaque entrée est mappée comme une entrée chargée directement, à une exception près : les bylines et les termes de taxonomie ne sont pas hydratés, de sorte que data.bylines et data.terms sont absents.

getEmDashReferences()

Récupère une page d’un seul champ de référence, sans relire l’entrée à laquelle il est rattaché. Utilisez-la pour dépasser la première page avec le nextCursor renvoyé par cette page.

ParamètreTypeDescription
collectionstringSlug de la collection de l’entrée qui contient le champ
slugOrIdstringSlug ou ID de l’entrée
fieldstringSlug du champ de référence
options{ limit?: number; cursor?: string; locale?: string }Facultatif. 50 entrées par défaut, 100 au plus

L’exemple suivant charge les 20 entrées liées suivantes :

import { getEmDashReferences } from "emdash";

const { entries, nextCursor, error } = await getEmDashReferences(
	"posts",
	post.id,
	"related_posts",
	{ cursor, limit: 20 },
);

error n’est défini que pour de véritables erreurs. Un champ inconnu, une entrée manquante ou une entrée que la requête n’a pas le droit de voir se résolvent tous en un tableau entries vide.

Le résultat comporte aussi un cacheHint qui nomme les lignes lues par la page. Une route qui met en cache ce qu’elle affiche doit le fusionner dans son propre indice, comme getEmDashEntry({ references }) intègre celui de la première page, afin que l’écriture dans l’une de ces entrées fasse expirer la page.

Helpers d’URL

decodeSlug() et slugify()

Utilisez decodeSlug() sur un paramètre de route dynamique avant de le transmettre à une requête de contenu. Elle renvoie undefined pour un paramètre absent ou une chaîne mal encodée en pourcentage, et renvoie sinon le slug décodé :

function decodeSlug(raw: string | undefined): string | undefined;
import { decodeSlug, getEmDashEntry } from "emdash";

const slug = decodeSlug(Astro.params.slug);
const { entry } = slug ? await getEmDashEntry("posts", slug) : { entry: null };

slugify(value) convertit un texte en slug en minuscules, séparé par des traits d’union. Utilisez-la lorsqu’un modèle doit construire un slug à partir d’un libellé ; les slugs d’entrées stockés proviennent déjà d’EmDash.

sanitizeHref() et isSafeHref()

Ces helpers acceptent http:, https:, mailto:, tel:, les chemins relatifs au site et les fragments. Ils rejettent les schémas capables d’exécuter des scripts, les URL relatives au protocole, les formes préfixées par une barre oblique inverse que les navigateurs résolvent vers un autre site, ainsi que les caractères de contrôle. isSafeHref(value) renvoie un booléen. sanitizeHref(value) renvoie l’URL sûre d’origine, ou "#" lorsque la valeur est vide ou dangereuse.

import { sanitizeHref } from "emdash";

const href = sanitizeHref(menuItem.url);

Système de preview

generatePreviewToken()

Génère un jeton d’aperçu pour du contenu en brouillon. L’exemple suivant crée un jeton qui expire dans une heure :

import { generatePreviewToken } from "emdash";

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

contentId doit utiliser le format collection:id. expiresIn accepte des secondes ou une durée se terminant par s, m, h, d ou w, et vaut "1h" par défaut. Gardez le secret de signature côté serveur.

verifyPreviewToken()

Vérifie un jeton d’aperçu et lit sa charge utile :

import { verifyPreviewToken } from "emdash";

const result = await verifyPreviewToken({
	token,
	secret: process.env.EMDASH_PREVIEW_SECRET!,
});

if (result.valid) {
	const { cid, exp, iat } = result.payload;
	// cid is "collection:id" format, e.g. "posts:my-draft-post"
}

Transmettez soit token, soit url, avec le secret de signature. Un jeton invalide renvoie { valid: false, error }, où error vaut "none", "malformed", "invalid" ou "expired".

parseContentId()

Sépare en deux parties la valeur collection:id de la charge utile d’un aperçu :

import { parseContentId } from "emdash";

const parsed = parseContentId(result.payload.cid);

Elle renvoie { collection, id } et lève une exception lorsque la valeur ne contient pas de séparateur deux-points.

getPreviewUrl() et buildPreviewUrl()

getPreviewUrl() crée et signe une URL d’aperçu. Elle accepte collection, id et secret, ainsi que les valeurs facultatives expiresIn, baseUrl, pathPattern et locale :

import { getPreviewUrl } from "emdash";

const previewUrl = await getPreviewUrl({
	collection: "posts",
	id: post.id,
	secret: process.env.EMDASH_PREVIEW_SECRET!,
	pathPattern: "/blog/{id}",
});

Sans baseUrl, elle renvoie une URL relative au site. Utilisez buildPreviewUrl({ path, token, baseUrl? }) lorsqu’un jeton existe déjà.

isPreviewRequest()

Vérifie si une requête comporte un jeton d’aperçu, puis le lit :

import { isPreviewRequest, getPreviewToken } from "emdash";

if (isPreviewRequest(Astro.url)) {
	const token = getPreviewToken(Astro.url);
	// Verify and show preview content
}

getPreviewToken() renvoie le paramètre de requête _preview, ou null lorsqu’il est absent. Le middleware d’EmDash vérifie les requêtes d’aperçu normales et fournit l’état d’aperçu à getEmDashEntry() automatiquement ; ces helpers sont destinés aux routes d’aperçu personnalisées et aux outils.

Convertisseurs de contenu

Convertissez entre les formats Portable Text et 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);

Le document ProseMirror utilise les nœuds propres à EmDash pour les blocs intégrés, tels que image, table, iframeBlock et videoBlock. Un éditeur TipTap qui le charge a besoin de ces nœuds dans son schéma, faute de quoi il ne peut pas charger les documents qui les utilisent. Un nœud videoBlock possède les attributs src, mediaId, provider, caption, width et height.

Paramètres du site

Lisez les paramètres de l’ensemble du site avec getSiteSettings et getSiteSetting :

function getSiteSettings(): Promise<Partial<SiteSettings>>;
function getSiteSetting<K extends SiteSettingKey>(key: K): Promise<SiteSettings[K] | undefined>;
import { getSiteSettings, getSiteSetting } from "emdash";

// Get all settings
const settings = await getSiteSettings();

// Get single setting
const title = await getSiteSetting("title");

Les paramètres sont en lecture seule depuis l’API d’exécution. Utilisez l’API d’administration pour les mettre à jour.

getSiteSettings() renvoie un objet partiel, car les clés non définies sont omises. Les paramètres de médias, comme le logo et le favicon du site, sont résolus en objets de référence de média avant le retour de la fonction.

getSiteSettingsWithCacheHint() renvoie { data, cacheHint }. Transmettez l’indice à Astro.cache.set() lorsqu’un cache de route Astro doit être invalidé après une modification des paramètres du site.

SEO

Résolvez les valeurs du panneau SEO et les valeurs de repli du contenu pour une page avec getSeoMeta() :

function getSeoMeta<T>(content: SeoContentInput<T>, options?: SeoMetaOptions): SeoMeta;

interface SeoMetaOptions {
	siteTitle?: string;
	siteUrl?: string;
	titleSeparator?: string; // Default: " | "
	path?: string;
	defaultOgImage?: string;
	defaultTitle?: string;
	defaultDescription?: string;
}

interface SeoMeta {
	title: string;
	description: string | null;
	ogTitle: string;
	ogDescription: string | null;
	ogImage: string | null;
	canonical: string | null;
	robots: string | null;
}
import { getSeoMeta } from "emdash";

const meta = getSeoMeta(post, {
	siteTitle: "Example Blog",
	siteUrl: "https://example.com",
	path: `/blog/${post.data.slug}`,
});

Elle renvoie le titre résolu, la description, les valeurs Open Graph, l’URL canonique et la valeur robots. getContentSeo(content) renvoie l’objet SEO brut, sans appliquer les valeurs de repli du modèle.

Pour le contenu traduit, getHreflangAlternates(collection, entryId, { siteUrl? }) renvoie les variantes de locale publiées et routables sous forme d’objets { hreflang, href } et ajoute une entrée x-default. Elle renvoie un tableau vide lorsque l’internationalisation est désactivée, que l’entrée actuelle est marquée noindex ou qu’aucune URL de site absolue n’est disponible.

Commentaires

Récupérez les commentaires approuvés d’une entrée et leur nombre :

import { getCommentCount, getComments } from "emdash";

const { items: comments, total } = await getComments({
	collection: "posts",
	contentId: post.data.id,
	threaded: true,
	reactions: true,
	sort: "best",
});

const count = await getCommentCount("posts", post.data.id);

threaded imbrique les réponses sous leur commentaire parent. La valeur par défaut de sort est "oldest" ; "best" classe les commentaires de premier niveau selon les réactions et active automatiquement le décompte des réactions. Les requêtes de commentaires rendues côté serveur renvoient au plus 500 commentaires approuvés ; utilisez l’API REST lorsqu’un client a besoin de pagination.

Traduire les composants de commentaires

Les composants Comments et CommentForm de emdash/ui/comments affichent par défaut du texte en anglais. Transmettez un objet labels pour remplacer n’importe lequel de ces textes. Les clés que vous omettez, ou que vous définissez sur undefined, conservent leur valeur par défaut en anglais :

<Comments
	collection="posts"
	contentId={post.data.id}
	threaded
	labels={{
		heading: (count) => (count === 1 ? "1 Kommentar" : `${count} Kommentare`),
		member: "Mitglied",
		like: "Gefällt mir",
	}}
/>
<CommentForm
	collection="posts"
	contentId={post.data.id}
	labels={{
		name: "Name",
		email: "E-Mail",
		comment: "Kommentar",
		submit: "Kommentar senden",
		submitting: "Wird gesendet …",
		published: "Kommentar veröffentlicht",
		pending: "Kommentar wird vor der Veröffentlichung geprüft",
		error: "Der Kommentar konnte nicht gesendet werden.",
		networkError: "Netzwerkfehler. Bitte versuche es erneut.",
	}}
/>

Comments accepte heading, member et like. heading reçoit le nombre de commentaires approuvés, et peut donc renvoyer un texte distinct lorsqu’il n’y a aucun commentaire.

CommentForm accepte name, email, comment, submit, submitting, published, pending, error et networkError. Le formulaire affiche published lorsque le commentaire est approuvé immédiatement et pending lorsqu’il attend la modération. Sans error, le formulaire affiche le message d’erreur en anglais du serveur.

Comments formate les dates des commentaires selon la locale de la page (Astro.currentLocale) et se rabat sur en-US. Astro ne définit Astro.currentLocale que lorsque la configuration i18n est activée. Sans elle, ou pour utiliser un autre format, transmettez une balise de locale BCP 47 telle que locale="de-CH".

Récupérez les menus de navigation et parcourez leurs éléments, y compris les enfants imbriqués :

function getMenu(name: string, options?: { locale?: string }): Promise<Menu | null>;
function getMenus(options?: { locale?: string }): Promise<MenuSummary[]>;
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));
	});
}

getMenu(name, { locale? }) suit la chaîne de repli de locale configurée. getMenus({ locale? }) liste les résumés de menus pour la locale de la requête résolue ou la locale configurée ; sans internationalisation, elle liste toutes les locales. getMenuWithCacheHint() renvoie { data, cacheHint } pour les routes qui utilisent le cache d’Astro.

Bylines

Récupérez le profil d’un auteur par ID ou par slug, ou listez les entrées créditées à un byline :

import { getByline, getBylineBySlug, getEntriesByByline } from "emdash";

const profile = await getBylineBySlug("jane-doe", { locale: "en" });
const posts = profile
	? await getEntriesByByline("posts", profile.translationGroup ?? profile.id)
	: [];

getByline(id) renvoie un profil ou null. La recherche par slug accepte une locale facultative et suit la chaîne de repli de locale. Les requêtes de contenu hydratent déjà les crédits ordonnés d’une entrée dans entry.data.bylines ; utilisez ces helpers autonomes pour les pages d’auteur et les archives de bylines.

Taxonomies

Récupérez des termes de taxonomie, un terme unique, les termes d’une entrée ou des entrées par terme :

function getTaxonomyTerms(
	taxonomyName: string,
	options?: { locale?: string; includeCounts?: boolean },
): Promise<TaxonomyTerm[]>;

function getTerm(
	taxonomyName: string,
	slug: string,
	options?: { locale?: string; includeCounts?: boolean },
): Promise<TaxonomyTerm | null>;

function getTermsForEntries(
	collection: string,
	entryIds: string[],
	taxonomyName: string,
	options?: { locale?: string },
): Promise<Map<string, TaxonomyTerm[]>>;
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");

getTaxonomyDefs({ locale? }) liste une définition par taxonomie, et getTaxonomyDef(name, { locale? }) renvoie une définition, ou null lorsqu’aucune locale ne définit la taxonomie. Les deux résolvent une taxonomie dans toutes les locales ; Traduire les taxonomies et les termes explique quel libellé de locale elles utilisent. Les recherches de termes suivent la chaîne de repli configurée.

getTaxonomyTerms(name, { locale?, includeCounts? }) renvoie un arbre pour les taxonomies hiérarchiques et inclut par défaut le nombre d’entrées visibles. Transmettez includeCounts: false lorsque le modèle n’affiche pas les nombres. Les requêtes de contenu hydratent aussi les termes attribués dans le data.terms de chaque entrée ; utilisez getEntryTerms() lorsque vous n’avez qu’un nom de collection et un ID d’entrée.

Pour les pages d’archive qui affichent des termes à côté de nombreuses entrées, regroupez la recherche par lots au lieu d’appeler getEntryTerms() dans une boucle :

import { getAllTermsForEntries, getTermsForEntries } from "emdash";

const termsByPost = await getTermsForEntries(
	"posts",
	posts.map(post => post.data.id),
	"category",
);

const allTermsByPost = await getAllTermsForEntries(
	"posts",
	posts.map(post => post.data.id),
);

getTermsForEntries() renvoie une map de l’ID d’entrée vers les termes de la taxonomie demandée. getAllTermsForEntries() renvoie une map de l’ID d’entrée vers les termes regroupés par nom de taxonomie. getTaxonomyTermsWithCacheHint() renvoie { data, cacheHint } pour une route mise en cache par Astro.

Zones de widgets

Récupérez les zones de widgets et les widgets qu’elles contiennent :

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);
	});
}

getWidgetAreaWithCacheHint(name) renvoie { data, cacheHint } pour les routes qui utilisent le cache d’Astro. Les zones de widgets et leurs widgets sont ordonnés selon leur ordre de tri configuré.

Sections

Récupérez des sections et filtrez-les :

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?) renvoie { items: Section[]; nextCursor?: string }. Les options sont source ("theme" | "user" | "import"), search, limit (50 par défaut, 100 au maximum) et cursor.

Recherche

Lancez une recherche globale dans les collections. Les résultats comprennent des extraits mis en évidence :

function search(query: string, options?: SearchOptions): Promise<SearchResponse>;

interface SearchOptions {
	collections?: string[]; // Default: every searchable collection
	status?: string; // Default: "published"
	locale?: string; // Default: all locales
	limit?: number; // Default: 20
	cursor?: string;
	scope?: "all" | "title"; // Default: "all"
}

interface SearchResponse {
	items: SearchResult[];
	nextCursor?: string;
}
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);
});

// Paginate: pass the previous nextCursor back as `cursor` to get the next page.
// nextCursor is undefined once there are no more results.
if (results.nextCursor) {
	const next = await search("hello world", {
		collections: ["posts", "pages"],
		limit: 20,
		cursor: results.nextCursor,
	});
}

Avec scope: "title", la requête ne correspond qu’au champ de titre de chaque collection au lieu de l’ensemble du texte indexé — utile pour les sélecteurs et l’autocomplétion, où des correspondances dans le corps du texte surprendraient. Les collections dont le champ de titre n’est pas indexé pour la recherche ne renvoient aucun résultat avec cette portée.

Gestion des erreurs

Les requêtes de contenu renvoient les erreurs opérationnelles dans leur résultat au lieu de les lever. Une entrée manquante n’est pas une erreur opérationnelle : entry vaut null et error reste indéfini.

const { entry, error } = await getEmDashEntry("posts", slug);

if (error) {
	return new Response("Content could not be loaded", { status: 500 });
}

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

Les helpers sans enveloppe de résultat peuvent lever des exceptions lorsque leur entrée est invalide ou qu’une opération de base de données échoue. Gérez ces erreurs à la limite de la route lorsque la page peut proposer un repli utile. Les classes d’erreur des dépôts et des gestionnaires utilisées par les intégrations serveur de plus bas niveau sortent du cadre de cette API de modèles de site.