JavaScript API 참조

이 페이지

이 페이지는 Astro 페이지, 레이아웃, 컴포넌트가 EmDash 사이트를 읽고 표시하는 데 사용하는 공개 API를 다룹니다. emdash 패키지 루트에서 내보내는 모든 항목을 나열하지는 않습니다. 데이터베이스 리포지토리, API 핸들러, 마이그레이션 유틸리티, 플러그인 작성 API 및 기타 서버 내부 구현은 각각 별도의 참조 문서가 있거나 프레임워크 통합 코드용입니다.

이 참조의 사이트 템플릿 API 계약은 EmDash가 유지 관리하는 공식 사이트 템플릿이 emdash에서 가져오는 모든 함수를 나열합니다. MediaValue 같은 타입 전용 import는 해당 데이터 모델 문서에서 다룹니다. 사이트 작성자에게 도움이 되는 관련 함수는 같은 섹션에서 설명하지만, 관련 없는 루트 export는 이 페이지에서 다루지 않습니다.

사이트 템플릿 API 계약

유지 관리되는 템플릿은 다음 런타임 헬퍼를 호출합니다.

함수용도
decodeSlug조회 전에 동적 라우트 매개변수를 디코딩
getEmDashCollection컬렉션의 항목을 읽고 필터링
getEmDashEntryID 또는 슬러그로 항목 하나를 읽기
getMenuWithCacheHint캐시 무효화 힌트와 함께 내비게이션 메뉴를 렌더링
getSeoMeta항목의 SEO 패널 값과 템플릿 폴백을 확인
getSiteSettings공개 사이트 정보와 기타 전역 설정을 읽기
getSiteSettingsWithCacheHint캐시 무효화 힌트와 함께 전역 설정을 읽기
getTaxonomyTermsWithCacheHint캐시 무효화 힌트와 함께 택소노미 필터를 렌더링
getTermsForEntries항목 목록에 대해 택소노미 하나를 일괄 로드
sanitizeHref저장된 링크를 렌더링하기 전에 안전하지 않은 URL 스킴을 거부
search컬렉션 전체에서 게시된 콘텐츠를 검색

콘텐츠 쿼리

EmDash의 쿼리 함수는 Astro의 라이브 콘텐츠 컬렉션 패턴을 따르며, 오류를 우아하게 처리할 수 있도록 { entries, error } 또는 { entry, error }를 반환합니다.

getEmDashCollection()

컬렉션의 모든 항목을 가져옵니다. 다음 예제는 모든 게시물을 로드하고 오류를 확인합니다.

import { getEmDashCollection } from "emdash";

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

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

매개변수

매개변수타입설명
collectionstring컬렉션 슬러그
optionsCollectionFilter선택적 필터 옵션

옵션

options 매개변수는 다음 필터를 받습니다.

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와 offset은 함께 사용할 수 없습니다. where의 키에는 콘텐츠 필드, 택소노미, byline을 지정할 수 있으며, 순서가 있는 비교에는 범위 객체를 사용할 수 있습니다.

반환값

이 함수는 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)
}

예제

다음 예제는 상태와 택소노미로 필터링하고, 결과를 제한하며, 오류를 처리합니다.

// 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()

슬러그 또는 ID로 항목 하나를 가져옵니다. 다음 예제는 게시물을 로드하고, 게시물이 없으면 사이트의 404 페이지를 렌더링합니다.

import { getEmDashEntry } from "emdash";

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

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

매개변수

매개변수타입설명
collectionstring컬렉션 슬러그
slugOrIdstring항목 슬러그 또는 ID
options{ locale?: string; references?: ReferenceSelection }선택 사항. 슬러그 확인에 쓸 로케일과 로드할 참조 필드

미리보기 모드는 자동으로 처리됩니다. 요청에 유효한 _preview 토큰이 있으면 쿼리가 초안 콘텐츠를 반환합니다. 미리보기 상태에는 매개변수가 필요 없습니다.

references는 로드할 참조 필드를 필드 슬러그를 키로 지정합니다. true는 기본 한도인 50개 항목으로 첫 페이지를 요청합니다. 객체 형태에서는 limit(최대 100)와 이전 페이지에서 받은 cursor를 지정할 수 있습니다. 생략한 필드는 읽지 않으며, 이 옵션을 생략한 호출은 참조 쿼리를 전혀 실행하지 않습니다.

반환값

이 함수는 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
}

예제

다음 예제는 슬러그와 ID로 가져오고, 미리보기 상태를 읽고, 오류와 찾을 수 없음을 구분합니다.

// 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()

컬렉션 슬러그와 데이터베이스 ID로 항목 하나에서 사용할 수 있는 번역을 가져옵니다.

import { getTranslations } from "emdash";

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

결과에는 공유되는 translationGroup, translations 배열, 선택적 error가 들어 있습니다. 각 번역 요약에는 id, locale, slug, status가 포함됩니다.

resolveEmDashPath()

라우팅 가능한 컬렉션에 구성된 URL 패턴을 기준으로 공개 경로명을 확인합니다.

import { resolveEmDashPath } from "emdash";

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

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

결과에는 일치한 collection, entry, 라우트 params가 들어 있습니다. 구성된 URL 패턴과 일치하는 것이 없으면 이 함수는 null을 반환합니다.

getEditMeta()

Portable Text 값에 붙은 열거할 수 없는 시각적 편집 메타데이터를 읽습니다.

import { getEditMeta } from "emdash";

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

주석이 달린 값에는 { collection, id, field }를 반환하고, 주석이 없는 값에는 undefined를 반환합니다.

콘텐츠 타입

ContentEntry

쿼리 함수는 다음 형태로 항목을 반환합니다.

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
}

edit 프록시는 시각적 편집 주석을 제공합니다. 요소에 전개하면 인라인 편집이 활성화됩니다: {...entry.edit.title}. 편집 모드가 아닐 때는 아무것도 출력하지 않습니다.

data 객체에는 모든 콘텐츠 필드와 시스템 필드가 들어 있습니다.

  • id - 고유 식별자
  • slug - URL에 쓰기 좋은 식별자
  • status - “draft” | “published” | “archived”
  • createdAt - 생성 시각(Date)
  • updatedAt - 마지막 업데이트 시각(Date)
  • publishedAt - 게시 시각(Date 또는 null). 콘텐츠를 게시 취소해도 유지됩니다
  • 그리고 컬렉션 스키마에 정의한 모든 사용자 정의 필드

ReferencePage

entry.references에는 getEmDashEntry에 요청된 참조 필드마다 한 페이지씩, 필드 슬러그를 키로 하여 담깁니다.

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

각 항목은 직접 로드한 항목과 같은 방식으로 매핑되지만 한 가지 예외가 있습니다. 바이라인과 택소노미 용어는 채워지지 않으므로 data.bylines와 data.terms는 존재하지 않습니다.

getEmDashReferences()

필드가 속한 항목을 다시 읽지 않고 참조 필드 하나의 한 페이지를 가져옵니다. 첫 페이지를 넘어가려면 그 페이지가 반환한 nextCursor를 사용합니다.

매개변수타입설명
collectionstring필드를 가진 항목의 컬렉션 슬러그
slugOrIdstring항목 슬러그 또는 ID
fieldstring참조 필드 슬러그
options{ limit?: number; cursor?: string; locale?: string }선택 사항. 기본 50개, 최대 100개

다음 예제는 연결된 항목을 다음 20개 로드합니다.

import { getEmDashReferences } from "emdash";

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

error는 실제 오류일 때만 설정됩니다. 알 수 없는 필드, 존재하지 않는 항목, 요청에서 볼 수 없는 항목은 모두 빈 entries 배열로 확정됩니다.

결과에는 해당 페이지가 읽은 행을 가리키는 cacheHint도 들어 있습니다. 렌더링한 결과를 캐시하는 라우트는 getEmDashEntry({ references })가 첫 페이지의 힌트를 합치는 것과 같은 방식으로 이를 자신의 힌트에 병합해야 합니다. 그래야 해당 항목 중 하나에 쓰기가 발생할 때 페이지가 만료됩니다.

URL 헬퍼

decodeSlug() 및 slugify()

동적 라우트 매개변수를 콘텐츠 쿼리에 전달하기 전에 decodeSlug()를 사용하세요. 매개변수가 없으면 undefined를 반환하고, 그렇지 않으면 decodeURIComponent()를 적용합니다. 퍼센트 인코딩이 잘못된 경우 decodeURIComponent()는 예외를 던집니다.

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)는 텍스트를 소문자에 하이픈으로 구분된 슬러그로 변환합니다. 템플릿에서 레이블로 슬러그를 만들어야 할 때 사용하세요. 저장된 항목 슬러그는 이미 EmDash가 생성한 것입니다.

sanitizeHref() 및 isSafeHref()

이 헬퍼들은 http:, https:, mailto:, tel:, 사이트 상대 경로, 프래그먼트를 허용합니다. 스크립트를 실행할 수 있는 스킴, 프로토콜 상대 URL, 브라우저가 다른 사이트로 해석하는 백슬래시로 시작하는 형태, 제어 문자는 거부합니다. isSafeHref(value)는 불리언을 반환합니다. sanitizeHref(value)는 원래의 안전한 URL을 반환하며, 값이 비어 있거나 안전하지 않으면 "#"을 반환합니다.

import { sanitizeHref } from "emdash";

const href = sanitizeHref(menuItem.url);

미리보기 시스템

generatePreviewToken()

초안 콘텐츠용 미리보기 토큰을 생성합니다. 다음 예제는 한 시간 뒤에 만료되는 토큰을 만듭니다.

import { generatePreviewToken } from "emdash";

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

contentId는 collection:id 형식이어야 합니다. expiresIn에는 초 단위 숫자 또는 s, m, h, d, w로 끝나는 기간을 지정할 수 있으며, 기본값은 "1h"입니다. 서명 시크릿은 서버에만 보관하세요.

verifyPreviewToken()

미리보기 토큰을 검증하고 페이로드를 읽습니다.

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

서명용 secret과 함께 token 또는 url 중 하나를 전달하세요. 유효하지 않은 토큰은 { valid: false, error }를 반환하며, error는 "none", "malformed", "invalid", "expired" 중 하나입니다.

parseContentId()

미리보기 페이로드의 collection:id 값을 두 부분으로 나눕니다.

import { parseContentId } from "emdash";

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

{ collection, id }를 반환하며, 값에 콜론 구분자가 없으면 예외를 던집니다.

getPreviewUrl() 및 buildPreviewUrl()

getPreviewUrl()은 미리보기 URL을 만들고 서명합니다. collection, id, secret을 받으며, 선택적으로 expiresIn, baseUrl, pathPattern, locale 값도 받습니다.

import { getPreviewUrl } from "emdash";

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

baseUrl이 없으면 사이트 상대 URL을 반환합니다. 이미 토큰이 있다면 buildPreviewUrl({ path, token, baseUrl? })를 사용하세요.

isPreviewRequest()

요청에 미리보기 토큰이 포함되어 있는지 확인한 다음 읽습니다.

import { isPreviewRequest, getPreviewToken } from "emdash";

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

getPreviewToken()은 _preview 쿼리 매개변수를 반환하며, 없으면 null을 반환합니다. EmDash 미들웨어는 일반 미리보기 요청을 검증하고 미리보기 상태를 getEmDashEntry()에 자동으로 전달합니다. 이 헬퍼들은 사용자 정의 미리보기 라우트와 도구를 위한 것입니다.

콘텐츠 변환기

Portable Text와 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);

사이트 설정

getSiteSettings와 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");

설정은 런타임 API에서 읽기 전용입니다. 업데이트하려면 관리자 API를 사용하세요.

getSiteSettings()는 설정되지 않은 키가 생략되므로 부분 객체를 반환합니다. 사이트 로고와 파비콘 같은 미디어 설정은 함수가 반환되기 전에 미디어 참조 객체로 확인됩니다.

getSiteSettingsWithCacheHint()는 { data, cacheHint }를 반환합니다. 사이트 설정이 바뀐 뒤 Astro 라우트 캐시를 무효화해야 한다면 이 힌트를 Astro.cache.set()에 전달하세요.

SEO

getSeoMeta()로 페이지의 SEO 패널 값과 콘텐츠 폴백을 확인합니다.

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

확인된 제목, 설명, Open Graph 값, 정규 URL, robots 값을 반환합니다. getContentSeo(content)는 템플릿 폴백을 적용하지 않은 원본 SEO 객체를 반환합니다.

번역된 콘텐츠의 경우 getHreflangAlternates(collection, entryId, { siteUrl? })가 게시되었고 라우팅 가능한 로케일별 변형을 { hreflang, href } 객체로 반환하고 x-default 항목을 추가합니다. 국제화가 비활성화되어 있거나, 현재 항목이 noindex로 표시되어 있거나, 절대 사이트 URL이 없으면 빈 배열을 반환합니다.

댓글

항목의 승인된 댓글과 그 개수를 가져옵니다.

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는 답글을 부모 댓글 아래에 중첩합니다. 기본 sort는 "oldest"이며, "best"는 최상위 댓글을 반응 수로 순위를 매기고 반응 집계를 자동으로 활성화합니다. 서버 렌더링 댓글 쿼리는 승인된 댓글을 최대 500개까지 반환합니다. 클라이언트에서 페이지네이션이 필요하면 REST API를 사용하세요.

메뉴

내비게이션 메뉴를 가져와 중첩된 하위 항목을 포함한 항목을 순회합니다.

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? })는 구성된 로케일 폴백 체인을 따릅니다. getMenus({ locale? })는 확인된 요청 로케일 또는 구성된 로케일의 메뉴 요약을 나열하며, 국제화를 사용하지 않으면 모든 로케일을 나열합니다. getMenuWithCacheHint()는 Astro 캐시를 사용하는 라우트를 위해 { data, cacheHint }를 반환합니다.

바이라인

ID 또는 슬러그로 작성자 프로필을 가져오거나, 바이라인에 크레딧된 항목을 나열합니다.

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)는 프로필 하나 또는 null을 반환합니다. 슬러그 조회는 선택적 로케일을 받고 로케일 폴백 체인을 따릅니다. 콘텐츠 쿼리는 이미 항목의 순서가 있는 크레딧을 entry.data.bylines에 채워 줍니다. 작성자 페이지와 바이라인 아카이브에는 이 독립 실행형 헬퍼를 사용하세요.

택소노미

택소노미 용어, 단일 용어, 항목의 용어, 또는 용어별 항목을 가져옵니다.

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? })는 택소노미마다 정의 하나를 나열하고, getTaxonomyDef(name, { locale? })는 정의 하나를 반환하며, 어떤 로케일에서도 해당 택소노미를 정의하지 않았으면 null을 반환합니다. 둘 다 모든 로케일에 걸쳐 택소노미를 확인합니다. 어느 로케일의 레이블을 사용하는지는 택소노미와 용어 번역하기를 참고하세요. 용어 조회는 구성된 폴백 체인을 따릅니다.

getTaxonomyTerms(name, { locale?, includeCounts? })는 계층형 택소노미에는 트리를 반환하며, 기본적으로 표시 가능한 항목 수를 포함합니다. 템플릿이 개수를 렌더링하지 않는다면 includeCounts: false를 전달하세요. 콘텐츠 쿼리도 할당된 용어를 각 항목의 data.terms에 채워 줍니다. 컬렉션 이름과 항목 ID만 있을 때는 getEntryTerms()를 사용하세요.

많은 항목 옆에 용어를 렌더링하는 아카이브 페이지에서는 반복문 안에서 getEntryTerms()를 호출하는 대신 조회를 일괄 처리하세요.

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()는 항목 ID에서 요청한 택소노미의 용어로 가는 맵을 반환합니다. getAllTermsForEntries()는 항목 ID에서 택소노미 이름별로 묶인 용어로 가는 맵을 반환합니다. getTaxonomyTermsWithCacheHint()는 Astro 캐시를 사용하는 라우트를 위해 { data, cacheHint }를 반환합니다.

위젯 영역

위젯 영역과 그 안에 들어 있는 위젯을 가져옵니다.

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)은 Astro 캐시를 사용하는 라우트를 위해 { data, cacheHint }를 반환합니다. 위젯 영역과 그 위젯은 구성된 정렬 순서대로 정렬됩니다.

섹션

섹션을 가져오고 필터링합니다.

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?)는 { items: Section[]; nextCursor?: string }을 반환합니다. 옵션은 source("theme" | "user" | "import"), search, limit(기본 50, 최대 100), cursor입니다.

검색

컬렉션 전체에서 전역 검색을 실행합니다. 결과에는 강조 표시된 스니펫이 포함됩니다.

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

scope: "title"을 사용하면 쿼리가 색인된 전체 텍스트 대신 각 컬렉션의 제목 필드에만 일치합니다. 본문 일치가 뜻밖일 수 있는 선택기나 자동 완성에 유용합니다. 제목 필드가 검색용으로 색인되지 않은 컬렉션은 이 범위에서는 결과를 반환하지 않습니다.

오류 처리

콘텐츠 쿼리는 운영상의 오류를 예외로 던지지 않고 결과에 담아 반환합니다. 항목이 없는 것은 운영상의 오류가 아닙니다. 이 경우 entry는 null이고 error는 정의되지 않은 채로 남습니다.

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

결과 래퍼가 없는 헬퍼는 입력이 유효하지 않거나 데이터베이스 작업이 실패하면 예외를 던질 수 있습니다. 페이지가 유용한 폴백을 제공할 수 있다면 라우트 경계에서 이러한 오류를 처리하세요. 더 낮은 수준의 서버 통합에서 사용하는 리포지토리와 핸들러 오류 클래스는 이 사이트 템플릿 API의 범위 밖입니다.