JavaScript API 레퍼런스

이 페이지

EmDash는 콘텐츠 쿼리 및 미리보기, 설정, 메뉴, 분류체계, 위젯 영역, 섹션, 검색 작업을 위한 함수를 내보냅니다.

콘텐츠 쿼리

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 CollectionFilter {
	status?: "draft" | "published" | "archived";
	limit?: number;
	where?: Record<string, string | string[]>; // Filter by field or taxonomy
}

반환 값

함수는 CollectionResult로 해결됩니다:

interface CollectionResult<T> {
	entries: ContentEntry<T>[]; // Empty array if error or none found
	error?: Error; // Set if query failed
}

예제

다음 예제는 상태 및 분류체계로 필터링하고, 결과를 제한하며, 오류를 처리합니다:

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

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

getEmDashEntry()

슬러그 또는 ID로 단일 항목을 가져옵니다. 다음 예제는 게시물을 로드하고 누락된 경우 리디렉션합니다:

import { getEmDashEntry } from "emdash";

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

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

매개변수

매개변수타입설명
collectionstring컬렉션 슬러그
slugOrIdstring항목 슬러그 또는 ID
options{ locale?: string }선택사항. 슬러그 해석을 위한 로케일

미리보기 모드는 자동으로 처리됩니다. 미들웨어가 _preview 토큰을 감지하고 AsyncLocalStorage를 통해 초안 콘텐츠를 제공합니다. 선택적 options 매개변수는 슬러그 해석을 위한 locale만 허용합니다. 미리보기 상태는 매개변수가 필요하지 않습니다.

반환 값

함수는 EntryResult로 해결됩니다:

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
}

예제

다음 예제는 슬러그와 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.redirect("/404");
}

콘텐츠 타입

ContentEntry

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

interface ContentEntry<T = Record<string, unknown>> {
	id: string;
	data: T;
	edit: EditProxy; // Visual editing annotations
}

edit 프록시는 시각적 편집 주석을 제공합니다. 인라인 편집을 활성화하려면 요소에 펼쳐 넣으세요: {...entry.edit.title}. 프로덕션에서는 출력이 생성되지 않습니다.

data 객체에는 모든 콘텐츠 필드와 시스템 필드가 포함되어 있습니다:

  • id - 고유 식별자
  • slug - URL 친화적 식별자
  • status - “draft” | “published” | “archived”
  • createdAt - ISO 타임스탬프
  • updatedAt - ISO 타임스탬프
  • publishedAt - ISO 타임스탬프 또는 null
  • 컬렉션 스키마에 정의된 모든 사용자 정의 필드

미리보기 시스템

generatePreviewToken()

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

import { generatePreviewToken } from "emdash";

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

verifyPreviewToken()

미리보기 토큰을 확인하고 페이로드를 읽습니다:

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 is "collection:id" format, e.g. "posts:my-draft-post"
}

isPreviewRequest()

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

import { isPreviewRequest, getPreviewToken } from "emdash";

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

콘텐츠 변환기

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

사이트 설정

getSiteSettingsgetSiteSetting으로 사이트 전체 설정을 읽습니다:

import { getSiteSettings, getSiteSetting } from "emdash";

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

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

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

메뉴

탐색 메뉴를 가져오고 중첩된 자식을 포함하여 항목을 반복합니다:

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

분류체계

분류체계 용어, 단일 용어, 항목의 용어 또는 용어별 항목을 가져옵니다:

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

위젯 영역

위젯 영역과 포함된 위젯을 가져옵니다:

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

섹션

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

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입니다.

검색

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

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

오류 처리

EmDash는 특정 오류를 처리하기 위한 오류 클래스를 내보냅니다. 다음 예제는 유효성 검사 및 스키마 오류를 포착합니다:

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