시드 파일은 EmDash 사이트의 초기 스키마와 선택적 샘플 데이터를 설명합니다. 현재 템플릿은 이를 seed/seed.json에 두고 package.json#emdash.seed로 가리킵니다.
EmDash는 빌드 시 시드를 임베드합니다. 최초 설정과 명시적 시드 명령용이며, 배포마다 실행되는 마이그레이션이 아닙니다.
파일 검색
Astro 통합은 다음 순서로 시드를 찾습니다.
.emdash/seed.jsonpackage.json#emdash.seed의 경로seed/seed.json- 사용자 시드가 없을 때의 내장 기본 시드
다음 패키지 필드가 템플릿의 관례 경로를 선택합니다.
{
"emdash": {
"seed": "seed/seed.json"
}
}
루트 형태
다음 예는 모든 루트 속성을 포함합니다.
{
"$schema": "https://emdashcms.com/seed.schema.json",
"version": "1",
"defaultLocale": "en",
"meta": {
"name": "Publication",
"description": "A publication seed",
"author": "Example Studio"
},
"settings": {},
"blockTypes": [],
"collections": [],
"relations": [],
"taxonomies": [],
"bylines": [],
"content": {},
"menus": [],
"redirects": [],
"widgetAreas": [],
"sections": []
}
| Property | Required | Purpose |
|---|---|---|
$schema | No | 에디터 스키마 URL |
version | Yes | 시드 형식. 허용 값은 "1"뿐 |
defaultLocale | No | locale을 생략한 로케일 행의 로케일. 기본값은 런타임 설정, 그다음 en |
meta | No | 설정 중 표시되는 설명 이름, 설명, 작성자 |
settings | No | 부분 사이트 설정 |
blockTypes | No | blocks 필드가 쓰는 버전 지정 정의 |
collections | No | 컬렉션 및 필드 정의 |
taxonomies | No | 택소노미 정의와 선택적 용어 |
bylines | No | 선택적 표시 크레딧 프로필 |
content | No | 컬렉션 슬러그별로 그룹화된 샘플 항목 |
menus | No | 메뉴와 중첩 항목 |
redirects | No | 로컬 리다이렉트 규칙 |
widgetAreas | No | 위젯 영역과 위젯 |
sections | No | 재사용 가능한 Portable Text 섹션 |
defaultLocale은 앞뒤 공백이 없는 비어 있지 않은 문자열이어야 합니다.
Settings
settings는 부분 사이트 설정 객체입니다. 흔한 속성은 title, tagline, logo, favicon, url, postsPerPage, dateFormat, timezone, social, seo입니다.
설정 마법사는 관리자가 시드된 제목과 태그라인을 덮어쓸 수 있게 합니다. 기본 onConflict: "skip"은 시드를 다시 적용할 때 그 값을 유지하고, 아직 없는 제공된 설정을 채웁니다.
{
"version": "1",
"settings": {
"title": "Field Notes",
"tagline": "Reports from the team",
"postsPerPage": 12,
"dateFormat": "MMMM d, yyyy",
"timezone": "Europe/London"
}
}
블록 타입
blockTypes는 컬렉션 blocks 필드가 사용하는 버전 지정 형태를 정의합니다. EmDash는 컬렉션보다 먼저 이 정의를 적용하므로, 필드가 validation.allowedTypes에서 이를 지정할 수 있습니다.
다음 시드는 저장된 콘텐츠와 리비전을 위해 버전 1을 유지하면서, 새 블록에는 버전 2를 활성으로 둡니다.
{
"version": "1",
"blockTypes": [
{
"slug": "hero",
"label": "Hero",
"category": "Layout",
"currentVersion": 2,
"versions": [
{
"version": 1,
"fields": [
{ "slug": "heading", "label": "Heading", "type": "string", "required": true }
]
},
{
"version": 2,
"fields": [
{ "slug": "title", "label": "Title", "type": "string", "required": true },
{ "slug": "image", "label": "Image", "type": "image" }
]
}
]
}
],
"collections": [
{
"slug": "pages",
"label": "Pages",
"fields": [
{
"slug": "layout",
"label": "Layout",
"type": "blocks",
"validation": { "allowedTypes": ["hero"], "maxItems": 20 }
}
]
}
]
}
버전 번호는 1부터 시작하는 연속된 양의 정수입니다. currentVersion은 선언된 버전을 지정해야 합니다. 시드 내보내기와 재적용은 정확한 버전 번호와 활성 포인터를 유지합니다. EmDash는 번호를 다시 매기지 않습니다.
onConflict: "update"에서는 새 정의가 호환될 때만 시드가 저장된 버전을 변경할 수 있습니다. 비호환 정의에 기존 번호를 재사용하면 BLOCK_TYPE_VERSION_CONFLICT로 실패합니다. 비호환 정의에는 새 버전 번호를 추가하세요.
저장된 블록 값은 _type, _version, _key를 포함합니다. 시드 콘텐츠가 유지된 버전을 가리킬 때 그 속성을 제공하세요. 런타임은 새로 쓴 블록이 이를 생략하면 활성 버전과 키를 할당합니다.
Collections
컬렉션에는 slug, label, fields가 필요합니다.
{
"version": "1",
"collections": [
{
"slug": "posts",
"label": "Posts",
"labelSingular": "Post",
"description": "Published articles",
"supports": ["drafts", "revisions", "scheduling", "search", "seo"],
"urlPattern": "/posts/{slug}",
"routable": true,
"commentsEnabled": true,
"editLocking": true,
"titleField": "title",
"dateField": "event_date",
"admin": {
"listColumns": ["event_date"]
},
"fields": [
{ "slug": "title", "label": "Title", "type": "string", "required": true },
{ "slug": "event_date", "label": "Event date", "type": "datetime", "indexed": true },
{ "slug": "content", "label": "Content", "type": "portableText" }
]
}
]
}
컬렉션 속성
| Property | Type | Behavior |
|---|---|---|
slug | string | 필수 데이터베이스/API 이름. 소문자로 시작하고 소문자, 숫자, 밑줄을 포함 |
label | string | 필수 복수형 UI 레이블 |
labelSingular | string | 선택적 단수형 UI 레이블 |
description | string | 선택적 관리 설명 |
icon | string | 선택적 아이콘 이름 |
admin.listColumns | string[] | 콘텐츠 목록에 표시할 선언된 필드 슬러그 최대 4개 |
supports | string[] | drafts, revisions, preview, scheduling, search, seo 중 아무거나 |
urlPattern | string | /posts/{slug} 같은 공개 패턴 |
routable | boolean | 게시된 항목에 슬러그가 필요한지. 기본값 true |
hidden | boolean | 생성된 사이드바 링크와 대시보드 빠른 동작을 숨김. 컬렉션은 URL과 API로 계속 도달 가능 |
sortOrder | number | 관리 사이드바의 명시적 위치. 정렬된 컬렉션이 먼저, 오름차순으로 옴 |
group | string | 관리 사이드바 폴더. 같은 그룹의 컬렉션은 접을 수 있는 항목을 공유 |
commentsEnabled | boolean | 컬렉션 댓글 활성화 |
editLocking | boolean | 편집 잠금 활성화. 기본값 true |
titleField | string | 콘텐츠 목록 제목에 쓰는 필드 |
dateField | string | 콘텐츠 목록 날짜에 쓰는 datetime 필드 |
fields | SeedField[] | 필수 필드 정의 |
sortOrder는 컬렉션에 속하며 사이드바 순서를 제어합니다. SeedField에는 sortOrder 속성이 없습니다. 필드는 배열 순서로 생성됩니다.
필드 속성
| Property | Type | Purpose |
|---|---|---|
slug | string | 컬렉션 슬러그와 같은 패턴의 필수 필드 이름 |
label | string | 필수 UI 레이블 |
type | FieldType | 필수 저장 필드 타입 |
required | boolean | 필수 빈 값을 거부 |
unique | boolean | 고유성 제약 추가 |
searchable | boolean | 컬렉션 검색에 필드 포함 |
indexed | boolean | 지원되는 스칼라 타입의 쿼리 인덱스 추가 |
translatable | boolean | 로케일당 값 저장. 기본값 true. false는 번역 간 한 값 공유 |
defaultValue | any | 필드 생략 시 초기값 |
validation | object | 생성된 콘텐츠 스키마가 쓰는 검증 규칙 |
widget | string | 관리 필드 위젯 재정의 |
options | object | 위젯별 옵션 |
지원되는 필드 타입:
string,text,url,slugnumber,integer,booleandatetimeselect,multiSelectportableText,json,repeaterblocksimage,file,reference
reference 필드는 컬렉션 테이블에 아무것도 저장하지 않습니다. 링크는 연결된 관계에 있습니다.
Relations를 보세요.
indexed: true를 설정할 수 있는 것은 string, url, number, integer, boolean, datetime, select, reference, slug뿐입니다. reference 필드에서는 필드에 관계가 없을 때만 플래그가 적용됩니다. 연결된 필드에는 인덱싱할 열이 없기 때문입니다.
필드 검증
생성된 컬렉션 스키마는 필드 타입이 지원하는 곳에서 다음 규칙을 인식합니다.
| Rule | Used by |
|---|---|
min, max | 숫자 필드 |
minLength, maxLength, pattern | 문자열형 필드 |
options | select와 multiSelect |
subFields, minItems, maxItems | repeater |
allowedTypes, minItems, maxItems | blocks |
allowedMimeTypes | 미디어 필드 |
blocks 필드의 retiredTypes는 서버 측에서 처리됩니다. allowedTypes에서 슬러그를 제거하면 폐기되어 기존 저장 블록은 유효하게 두고 새 블록에서는 사용할 수 없습니다.
validateSeed()는 validation이나 options의 모든 규칙을 깊게 검사하지 않습니다. 따라서 잘못된 규칙이 시드 검증을 통과하고 나중에 컬렉션 스키마 생성이나 콘텐츠 쓰기에서 실패할 수 있습니다.
Relations
관계는 두 컬렉션을 묶고 그 항목 간 링크를 소유합니다. reference 필드는 한쪽에 연결되어 그 끝에서 링크를 봅니다. 다음 시드는 게시물당 저자 한 명을 허용하는 posts와 authors 관계를 선언합니다.
{
"relations": [
{
"slug": "post_authors",
"parentCollection": "posts",
"childCollection": "authors",
"parentLabel": "Posts",
"parentLabelSingular": "Post",
"childLabel": "Authors",
"childLabelSingular": "Author",
"maxChildrenPerParent": 1
}
]
}
| Property | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | reference 필드가 주소로 쓰는 고유 이름 |
parentCollection | string | Yes | 부모 쪽 컬렉션 |
childCollection | string | Yes | 자식 쪽 컬렉션 |
parentLabel | string | Yes | 자식에서 본 부모 역할 이름 |
parentLabelSingular | string | No | parentLabel의 단수형 |
childLabel | string | Yes | 부모에서 본 자식 역할 이름 |
childLabelSingular | string | No | childLabel의 단수형 |
maxChildrenPerParent | number | null | No | 부모가 연결할 수 있는 자식 수(null: 제한 없음) |
maxParentsPerChild | number | null | No | 자식이 연결할 수 있는 부모 수(null: 제한 없음) |
collections의 reference 필드는 연결할 관계를 지정합니다.
{
"slug": "author",
"label": "Author",
"type": "reference",
"validation": { "relation": "post_authors" }
}
필드는 대신 targetCollection을 지정하고 그에 대한 관계를 만들게 할 수도 있습니다. 이는 한쪽 컬렉션만 보는 링크로의 가장 짧은 경로입니다. 양쪽 컬렉션이 봐야 하거나 레이블과 한도를 설정하려면 relations에서 관계를 선언하세요.
reference는 두 형태와 각 형태가 받는 검증 키를 문서화합니다.
관계의 두 컬렉션은 한 번 존재하면 고정됩니다. 다른 것을 지정하는 시드는 보유한 링크가 더 이상 끝이 아닌 컬렉션을 가리키게 두지 않고 실패합니다. 레이블과 한도는 시드가 onConflict: "update"로 적용될 때 업데이트됩니다.
택소노미
택소노미 정의는 대상 컬렉션을 식별합니다. 용어는 샘플 데이터이며 includeContent가 true일 때만 적용됩니다.
{
"version": "1",
"taxonomies": [
{
"name": "category",
"label": "Categories",
"labelSingular": "Category",
"hierarchical": true,
"collections": ["posts"],
"terms": [
{ "slug": "engineering", "label": "Engineering" },
{ "slug": "platform", "label": "Platform", "parent": "engineering" }
]
}
]
}
택소노미는 시드 로컬 id, locale, translationOf를 가질 수 있습니다. 용어도 그 속성을 가질 수 있습니다. translationOf는 다른 시드 로컬 ID를 가리킵니다. 용어는 번역하는 용어 뒤에 와야 합니다. 같은 name의 택소노미 항목은 어떤 순서로든 나타날 수 있습니다. 택소노미 형태를 선언하는 항목이 번역보다 먼저 적용되기 때문입니다.
hierarchical과 collections는 택소노미의 모든 로케일에서 공유되므로, 같은 name의 항목을 translationOf가 가리키는 택소노미 항목은 이를 생략할 수 있습니다. 적용 엔진은 같은 name의 항목을 통해 translationOf를 따라가 마지막 것에서 가져옵니다. 검증은 번역이 가져오는 값과 다른 값을 선언하거나, 택소노미에 대해 이를 선언하는 두 항목이 일치하지 않을 때 경고합니다. 기존 택소노미는 translationOf가 없는 항목이 바꿀 때까지 값을 유지합니다. 이는 onConflict: "update"에서 일어나며, Conflict behavior에 설명된 변경되지 않은 내장 category 또는 tag 정의를 항목 로케일이 갖거나 그 내장 정의가 택소노미의 유일한 것일 때는 모든 모드에서 일어납니다.보내기는 번역이 가리키는 항목에만 이를 씁니다.
용어의 parent는 같은 로케일 안 부모 용어의 슬러그입니다. 비계층 택소노미의 부모는 경고를 내고 무시됩니다. translationOf가 있고 parent가 없는 용어는 번역하는 용어의 부모를 가져옵니다.
Bylines
루트 bylines는 표시 크레딧을 정의합니다. 샘플 데이터이며 includeContent: true가 필요합니다.
{
"version": "1",
"bylines": [
{
"id": "byline-editor",
"slug": "alex-editor",
"displayName": "Alex Editor",
"isGuest": true
}
]
}
id는 시드 로컬이며 콘텐츠 크레딧이 사용합니다. 선택 속성은 bio, websiteUrl, isGuest, avatar입니다.
바이라인 아바타는 구성된 스토리지에 이미 있는 파일을 가리킵니다.
{
"id": "byline-editor",
"slug": "alex-editor",
"displayName": "Alex Editor",
"avatar": {
"storageKey": "avatars/alex.jpg",
"filename": "alex.jpg",
"mimeType": "image/jpeg",
"alt": "Alex Editor",
"width": 400,
"height": 400
}
}
바이라인 아바타 시딩은 스토리지 키의 미디어 행을 만들거나 재사용합니다. 파일을 업로드하거나 다운로드하지 않습니다.
Content
content는 컬렉션 슬러그별로 항목을 그룹화합니다. 각 항목에는 시드 로컬 id와 data 객체가 필요합니다. 라우팅 가능한 컬렉션에는 비어 있지 않은 slug도 필요합니다.
{
"version": "1",
"content": {
"posts": [
{
"id": "post-welcome",
"slug": "welcome",
"status": "published",
"data": {
"title": "Welcome",
"content": []
},
"taxonomies": {
"category": ["engineering"]
},
"bylines": [
{ "byline": "byline-editor", "roleLabel": "Editor" }
]
}
]
}
}
| Property | Required | Behavior |
|---|---|---|
id | Yes | 시드 로컬 참조 ID |
slug | 라우팅 가능한 컬렉션용 | 공개 슬러그와 충돌 키 |
status | No | published 또는 draft. 기본값 published |
data | Yes | 컬렉션 필드 슬러그로 키된 값 |
taxonomies | No | 택소노미 이름에서 용어 슬러그 배열로 |
bylines | No | 루트 바이라인 ID를 참조하는 순서 있는 크레딧 |
locale | No | BCP 47 로케일. defaultLocale을 통해 기본값 |
translationOf | No | 같은 컬렉션의 시드 로컬 콘텐츠 ID |
라우팅 가능한 항목에서 시드 로컬 id는 데이터베이스 동일성이 아닙니다. EmDash는 데이터베이스 ID를 만들고 이후 참조를 위해 매핑을 기록합니다. routable: false 컬렉션의 슬러그 없는 항목에서는 EmDash가 시드 id를 저장 ID로 사용해 재적용을 멱등하게 유지합니다.
읽을 때 entry.id는 Astro 라우트 식별자이며 보통 슬러그입니다. 저장된 데이터베이스 ID는 entry.data.id입니다.
콘텐츠 참조
data 안에서 $ref: 문자열을 사용해 시드 로컬 콘텐츠 ID를 생성된 데이터베이스 ID로 바꿉니다.
{
"id": "event-opening",
"slug": "opening-night",
"data": {
"title": "Opening night",
"venue": "$ref:venue-main-hall"
}
}
참조 대상은 적용 엔진의 ID 맵에 올라올 만큼 충분히 일찍 나타나야 합니다. 미해결 $ref: 값은 원래 리터럴 문자열로 남습니다. validateSeed()는 이를 거부하지 않습니다.
reference 필드에서는 그 관계의 부모 쪽에서 링크를 선언하세요. 양쪽이 같은 링크 집합을 보므로, 자식 컬렉션의 필드는 부모가 이미 가진 링크를 다시 주장하게 됩니다.
미디어 참조
콘텐츠 데이터의 $media를 사용해 URL을 다운로드하고, 제공된 스토리지 어댑터로 업로드하고, 미디어 행을 만들고, 객체를 미디어 필드 값으로 바꿉니다.
{
"featured_image": {
"$media": {
"url": "https://example.com/images/launch.jpg",
"filename": "launch.jpg",
"alt": "A product launch on stage",
"caption": "Launch event"
}
}
}
Portable Text image 블록이나 gallery 이미지에서 asset의 $media는 미디어 참조(_type: "reference", _ref, url, provider)가 되고, 미디어의 대체 텍스트와 크기가 없을 때 이미지의 alt, width, height를 채웁니다.
한 번의 적용 호출 안에서 같은 URL에 대한 반복 참조는 해결된 미디어 값을 재사용합니다. 시드 미디어 참조는 로컬 file 속성을 받지 않습니다. mediaBasePath는 공개 타입 SeedApplyOptions에 남아 있지만 현재 적용 엔진은 읽지 않습니다.
스토리지 어댑터가 제공되지 않으면 $media 참조는 건너뛰고 null로 해결됩니다. skipMediaDownload: true에서는 외부 미디어 값이 되며 스토리지 어댑터가 필요하지 않습니다.
메뉴
메뉴는 구조 데이터이며 includeContent가 false여도 적용됩니다.
{
"version": "1",
"menus": [
{
"name": "primary",
"label": "Primary navigation",
"items": [
{
"type": "page",
"label": "About",
"ref": "page-about",
"collection": "pages"
},
{
"type": "custom",
"label": "Contact",
"url": "/contact",
"target": "_self"
}
]
}
]
}
허용되는 항목 타입은 custom, page, post, taxonomy, collection입니다. custom에는 url이, page와 post에는 ref가 필요합니다. 항목은 id, translationOf, label, collection, titleAttr, cssClasses, locale, target, 중첩 children을 포함할 수 있습니다.
page와 post에서 ref는 시드 콘텐츠 ID를 지정합니다. 누락된 대상은 검증 경고를 내고 해결된 콘텐츠 참조가 없는 메뉴 항목이 됩니다. 기존 메뉴 항목은 onConflict와 관계없이 해당 메뉴가 적용될 때마다 삭제되고 다시 만들어집니다.
리다이렉트
리다이렉트에는 로컬 소스와 대상 경로가 필요합니다.
{
"version": "1",
"redirects": [
{
"source": "/old-path",
"destination": "/new-path",
"type": 308,
"enabled": true,
"groupName": "WordPress migration"
}
]
}
두 경로 모두 /로 시작해야 합니다. 프로토콜 상대 URL, 경로 순회 세그먼트, 줄바꿈은 거부됩니다. 허용되는 상태 코드는 301, 302, 307, 308입니다.
위젯 영역
위젯 영역은 content, menu, 또는 component 위젯을 담습니다.
{
"version": "1",
"widgetAreas": [
{
"name": "sidebar",
"label": "Sidebar",
"widgets": [
{
"type": "menu",
"title": "Explore",
"menuName": "primary"
},
{
"type": "component",
"title": "Recent posts",
"componentId": "core:recent-posts",
"props": { "count": 5 }
}
]
}
]
}
콘텐츠 위젯은 Portable Text를 content에 저장합니다. 메뉴 위젯에는 menuName이 필요합니다. 컴포넌트 위젯에는 componentId가 필요하며 props를 전달할 수 있습니다. SeedWidget에는 settings 속성이 없습니다.
영역의 기존 위젯은 onConflict와 관계없이 영역이 적용될 때마다 삭제되고 다시 만들어집니다.
섹션
섹션은 재사용 가능한 Portable Text 콘텐츠를 담습니다.
{
"version": "1",
"sections": [
{
"slug": "newsletter-signup",
"title": "Newsletter signup",
"description": "Signup call to action",
"keywords": ["newsletter", "email"],
"source": "theme",
"content": []
}
]
}
섹션 슬러그는 소문자, 숫자, 하이픈을 포함합니다. source는 theme, user, 또는 import입니다. 시드는 기본적으로 theme으로 설정합니다. 테마 섹션은 관리에서 삭제할 수 없습니다. 섹션은 구조적이며 includeContent가 false여도 적용됩니다.
로컬라이제이션
defaultLocale은 택소노미, 용어, 메뉴, 메뉴 항목, 콘텐츠의 빠진 로케일을 채웁니다. 활성 런타임 i18n 구성이 있으면 우선합니다.
로컬라이즈된 택소노미, 용어, 메뉴, 메뉴 항목, 콘텐츠는 시드 로컬 id와 translationOf 필드를 사용합니다. 적용 엔진이 번역 그룹을 해결할 수 있도록 소스 항목을 번역보다 앞에 두세요. 번역된 콘텐츠 항목은 locale을 설정해야 하며 translationOf는 같은 컬렉션의 다른 항목을 지정해야 합니다.
프로그래밍 방식 시드 적용
applySeed()와 validateSeed()는 emdash/seed에서 내보냅니다. 다음 헬퍼는 적용 전에 검증합니다.
import {
applySeed,
validateSeed,
type SeedApplyOptions,
type SeedFile,
} from "emdash/seed";
type SeedDatabase = Parameters<typeof applySeed>[0];
export async function applyProjectSeed(
db: SeedDatabase,
seed: SeedFile,
options: SeedApplyOptions,
) {
const validation = validateSeed(seed);
if (!validation.valid) {
throw new Error(validation.errors.join("\n"));
}
return applySeed(db, seed, options);
}
SeedApplyOptions
| Option | Default | Current behavior |
|---|---|---|
includeContent | false | 콘텐츠 항목, 바이라인, 택소노미 용어 포함 |
onConflict | "skip" | 지원되는 엔티티 충돌에 대한 "skip", "update", 또는 "error" |
storage | none | $media URL 다운로드에 필요한 스토리지 어댑터 |
skipMediaDownload | false | $media URL을 외부 미디어 값으로 유지 |
mediaBasePath | none | 공개 타입에는 있으나 현재 적용 엔진에서는 사용하지 않음 |
프로그래밍 적용의 기본값은 includeContent가 false입니다. 설정 마법사는 관리자의 샘플 콘텐츠 선택을 전달합니다. CLI emdash seed는 --no-content가 설정되지 않는 한 기본적으로 콘텐츠를 포함합니다.
충돌 동작
onConflict는 전체 시드에 대한 트랜잭션 정책이 아닙니다.
- 컬렉션, 필드, 바이라인, 콘텐츠, 리다이렉트, 섹션은 skip, update, error 동작을 지원합니다.
- 택소노미 정의와 용어는 해당 충돌 모드를 따릅니다. 예외는 새 데이터베이스가 시작하는 내장
category와tag정의입니다. 사이트가 이를 바꾸기 전까지 이를 선언하는 시드는 모든 모드에서 바꿉니다. - 설정은 키별 충돌 처리를 사용합니다.
skip은 빠진 설정을 만들고 기존 값을 유지합니다.update는 제공된 각 설정을 덮어씁니다.error는 첫 기존 설정에서 멈춥니다. 시드 순서에서 먼저 만든 설정은 적용된 채로 남습니다. - 기존 메뉴는 메뉴 행을 유지하면서 모든 항목을 바꿉니다.
- 기존 위젯 영역은 영역 행을 유지하면서 모든 위젯을 바꿉니다.
- 콘텐츠 충돌은 컬렉션, 슬러그, 로케일로 매칭됩니다. 라우팅 불가 컬렉션의 슬러그 없는 항목은 시드 ID로 매칭됩니다.
onConflict: "update"에서는 콘텐츠 데이터가 바뀌고 바이라인과 택소노미 할당이 시드에 맞게 조정됩니다. 기존 사이트에 쓰기 전에 복사본에서 update 모드를 테스트하세요.
applySeed()는 컬렉션, 필드, 택소노미, 바이라인, 메뉴, 리다이렉트, 위젯 영역, 섹션, 설정, 콘텐츠, 미디어에 대한 카운터를 반환합니다.
검증 동작
validateSeed()는 { valid, errors, warnings }를 반환합니다. applySeed()는 이를 호출하고 오류가 있으면 Invalid seed file을 던집니다.
검증기는 적용 엔진이 필요로 하는 구조 규칙을 검사합니다. 예:
- 버전과 비어 있지 않은
defaultLocale - 컬렉션, 필드, 택소노미, 용어, 메뉴, 위젯 영역, 섹션, 바이라인, 콘텐츠 컨테이너 형태
- 필수 이름, 레이블, ID, 슬러그, 지원 필드/위젯 타입
- 관련 범위의 중복 식별자
- 인덱싱된 필드 타입과
admin.listColumns참조 - 택소노미 부모, 콘텐츠 번역, 콘텐츠 바이라인 참조, 메뉴 항목 요구사항
- 안전한 로컬 리다이렉트 경로와 상태 코드
일부 조건은 오류가 아니라 경고입니다. 예: 컬렉션 없는 택소노미, 플랫 택소노미의 부모, 시드에 없는 메뉴 콘텐츠 참조.
검증기는 모든 data 값이 컬렉션 필드에 맞는지 증명하지 않습니다. 사이트 설정, 필드 validation, 필드 options, 임의 Portable Text 블록, 컴포넌트 위젯 props, 콘텐츠 데이터의 $ref: 대상, $media의 원격 가용성도 깊게 검증하지 않습니다. 유효한 시드라도 스키마 생성, 콘텐츠 검증, 네트워크 다운로드, 스토리지 업로드에서 실패할 수 있습니다.
에디터 지원에는 $schema URL을 쓰고, 적용 전에 실행 가능한 검증기를 실행하세요.
npx emdash seed seed/seed.json --validate
CLI 명령
명시적 충돌 동작으로 로컬 SQLite 데이터베이스에 시드를 적용합니다.
npx emdash seed seed/seed.json --database ./data.db --on-conflict skip
현재 로컬 스키마와 모든 콘텐츠를 템플릿 경로로 다시 내보냅니다.
npx emdash export-seed --database ./data.db --with-content=all > seed/seed.json
export-seed는 로컬 SQLite 파일에 대해 직접 동작합니다. 배포된 D1 데이터베이스는 먼저 로컬 파일로 내보내세요. 결과를 커밋하기 전에 내보낸 설정, 콘텐츠, 미디어 참조를 검토하세요. 내보낸 미디어를 다른 사이트에서 가져올 수 있게 하려면 --media-base-url을 전달하세요. Media URLs를 보세요.
다음 단계
- Create a theme — 재사용 가능한 Astro 템플릿에서 시드 사용
- Schema evolution — 기존 배포된 사이트의 스키마 업데이트
- CLI reference — 데이터베이스 및 내보내기 옵션