컬렉션(collection)은 콘텐츠 유형(게시물, 페이지, 제품)입니다. 필드 정의는 각 항목의 데이터 구조를 설정합니다.
컬렉션 생성
관리 패널의 콘텐츠 타입에서 컬렉션을 생성합니다. 각 컬렉션에는 다음 속성이 있습니다:
| 속성 | 설명 |
|---|---|
slug | URL 안전 식별자(예: posts, products) |
label | 표시 이름(예: “블로그 게시물”) |
labelSingular | 단수형(예: “게시물”) |
description | 편집자를 위한 선택적 설명 |
icon | 관리 사이드바용 Lucide 아이콘 이름 |
supports | 초안, 리비전, 미리보기, 예약, 검색, SEO와 같은 기능 |
컬렉션 기능
컬렉션을 생성할 때 필요한 기능을 활성화하세요:
| 기능 | 설명 |
|---|---|
drafts | 초안/게시 워크플로우 활성화 |
revisions | 버전 스냅샷으로 콘텐츠 이력 추적 |
preview | 초안 콘텐츠용 서명된 미리보기 URL 생성 |
scheduling | 미래 날짜에 콘텐츠 게시 예약 |
다음 컬렉션은 네 가지 기능을 모두 활성화합니다:
{
slug: "posts",
label: "Blog Posts",
labelSingular: "Post",
supports: ["drafts", "revisions", "preview", "scheduling"]
}
필드 타입
EmDash는 SQLite 열 타입에 매핑되는 16가지 필드 타입을 지원합니다.
텍스트 필드
string
짧은 텍스트 입력. TEXT 열에 매핑됩니다.
{ slug: "title", type: "string", label: "Title" } text
여러 줄 텍스트 영역. TEXT 열에 매핑됩니다.
{ slug: "excerpt", type: "text", label: "Excerpt" } slug
URL 안전 슬러그 필드. TEXT 열에 매핑됩니다.
{ slug: "handle", type: "slug", label: "URL Handle" } 리치 콘텐츠
portableText
리치 텍스트 에디터(TipTap/ProseMirror). JSON으로 저장됩니다.
{ slug: "content", type: "portableText", label: "Content" }Portable Text는 HTML을 내장하지 않고 구조를 보존하는 블록 기반 형식입니다.
json
임의의 JSON 데이터. JSON으로 저장됩니다.
{ slug: "metadata", type: "json", label: "Custom Metadata" } 숫자
number
소수. REAL 열에 매핑됩니다.
{ slug: "price", type: "number", label: "Price" } integer
정수. INTEGER 열에 매핑됩니다.
{ slug: "quantity", type: "integer", label: "Stock Quantity" } 불리언과 날짜
boolean
참/거짓 토글. INTEGER(0/1)에 매핑됩니다.
{ slug: "featured", type: "boolean", label: "Featured Post" } datetime
날짜 및 시간 선택기. ISO 8601 문자열로 저장됩니다.
{ slug: "eventDate", type: "datetime", label: "Event Date" } 선택
select
목록에서 단일 옵션. TEXT 열에 매핑됩니다.
{
slug: "status",
type: "select",
label: "Product Status",
validation: {
options: ["active", "discontinued", "coming_soon"]
}
} multiSelect
목록에서 여러 옵션. JSON 배열로 저장됩니다.
{
slug: "features",
type: "multiSelect",
label: "Product Features",
validation: {
options: ["wireless", "waterproof", "eco-friendly"]
}
} 미디어 및 참조
image
미디어 라이브러리의 이미지 선택기. 미디어 ID를 TEXT로 저장합니다.
{ slug: "featuredImage", type: "image", label: "Featured Image" } file
미디어 라이브러리의 파일 선택기. 미디어 ID를 TEXT로 저장합니다.
{ slug: "attachment", type: "file", label: "PDF Attachment" } reference
다른 컬렉션의 항목 참조. 항목 ID를 TEXT로 저장합니다.
{
slug: "author",
type: "reference",
label: "Author",
options: {
collection: "authors"
}
} 필드 속성
모든 필드는 다음 속성을 지원합니다:
| 속성 | 타입 | 설명 |
|---|---|---|
slug | string | 데이터베이스의 열 이름 |
label | string | 관리 UI의 표시 레이블 |
type | FieldType | 16가지 필드 타입 중 하나 |
required | boolean | 필드에 값이 필요한지 여부 |
unique | boolean | 값이 항목 간에 고유해야 하는지 여부 |
defaultValue | unknown | 새 항목의 기본값 |
validation | object | 타입별 검증 규칙 |
widget | string | 사용자 정의 위젯 식별자 |
options | object | 위젯별 구성 |
sortOrder | number | 편집기의 표시 순서 |
검증 규칙
validation 객체는 필드 타입에 따라 다릅니다. 전체 형식은 다음과 같습니다:
interface FieldValidation {
required?: boolean; // All types
min?: number; // number, integer
max?: number; // number, integer
minLength?: number; // string, text
maxLength?: number; // string, text
pattern?: string; // string (regex)
options?: string[]; // select, multiSelect
}
다음 필드는 패턴과 일치하는 고유한 이메일 주소가 필요합니다:
{
slug: "email",
type: "string",
label: "Email Address",
required: true,
unique: true,
validation: {
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
}
}
위젯 옵션
options 객체는 필드별 UI 동작을 구성합니다. 전체 형식은 다음과 같습니다:
interface FieldWidgetOptions {
rows?: number; // text (textarea rows)
showPreview?: boolean; // image, file
collection?: string; // reference (target collection)
allowMultiple?: boolean; // reference (multiple refs)
[key: string]: unknown; // Custom widget options
}
다음 참조 필드는 여러 제품을 연결합니다:
{
slug: "relatedProducts",
type: "reference",
label: "Related Products",
options: {
collection: "products",
allowMultiple: true
}
}
컬렉션 쿼리
제공된 쿼리 함수를 사용하여 콘텐츠를 가져옵니다. 이들은 Astro의 라이브 컬렉션 패턴을 따르며 구조화된 결과를 반환합니다. 다음 예제는 일반적인 쿼리 옵션을 보여줍니다:
import { getEmDashCollection, getEmDashEntry } from "emdash";
// Get all entries - returns { entries, error }
const { entries: posts } = await getEmDashCollection("posts");
// Filter by status
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
// Limit results
const { entries: recent } = await getEmDashCollection("posts", {
limit: 5,
});
// Filter by taxonomy
const { entries: newsPosts } = await getEmDashCollection("posts", {
where: { category: "news" },
});
// Get a single entry by slug - returns { entry, error, isPreview }
const { entry: post } = await getEmDashEntry("posts", "my-post-slug");
// Handle errors
const { entries, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
}
타입 생성
스키마에서 TypeScript 타입을 생성하려면 npx emdash types를 실행하세요. 생성된 파일에는 컬렉션당 하나의 인터페이스가 포함됩니다:
export interface Post {
title: string;
content: PortableTextBlock[];
excerpt?: string;
featuredImage?: string;
author: string; // reference ID
}
export interface Product {
title: string;
price: number;
description: PortableTextBlock[];
}
데이터베이스 매핑
필드 타입은 다음과 같이 SQLite 열 타입에 매핑됩니다:
| 필드 타입 | SQLite 타입 | 비고 |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | TEXT | |
url | TEXT | |
number | REAL | 64비트 부동 소수점 |
integer | INTEGER | 64비트 부호 있는 정수 |
boolean | INTEGER | 0 또는 1 |
datetime | TEXT | ISO 8601 형식 |
select | TEXT | |
multiSelect | JSON | 문자열 배열 |
portableText | JSON | 블록 배열 |
image | TEXT | 미디어 ID |
file | TEXT | 미디어 ID |
reference | TEXT | 항목 ID |
json | JSON | 임의의 JSON |
repeater | JSON | 하위 필드 배열 |