コレクションは EmDash のコンテンツモデルの基盤です。各コレクションはコンテンツタイプ(投稿、ページ、製品など)を表し、データの形を決めるフィールド定義を含みます。
コレクションの作成
管理画面の コンテンツタイプ からコレクションを作成します。各コレクションには次があります。
| プロパティ | 説明 |
|---|---|
slug | URL 安全な識別子(例: posts, products) |
label | 表示名(例: 「Blog Posts」) |
labelSingular | 単数形(例: 「Post」) |
description | 編集者向けの任意の説明 |
icon | 管理サイドバー用の Lucide アイコン名 |
supports | 下書き、リビジョン、プレビュー、予約公開、検索、SEO などの機能 |
コレクションの機能
コレクション作成時に必要な機能を有効にします。
| 機能 | 説明 |
|---|---|
drafts | 下書き/公開のワークフロー |
revisions | バージョンスナップショットによるコンテンツ履歴 |
preview | 下書き用の署名付きプレビュー URL |
scheduling | 将来日時の公開を予約 |
// すべての機能を有効にしたコレクションの例
{
slug: "posts",
label: "Blog Posts",
labelSingular: "Post",
supports: ["drafts", "revisions", "preview", "scheduling"]
}
フィールド型
EmDash は 15 種類のフィールド型をサポートし、SQLite の列型にマッピングします。
テキスト系
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
リストから 1 つ選択。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 | 15 種類のいずれかのフィールド型 |
required | boolean | 値が必須かどうか |
unique | boolean | エントリ間で値が一意である必要があるか |
defaultValue | unknown | 新規エントリのデフォルト値 |
validation | object | 型ごとのバリデーション規則 |
widget | string | カスタムウィジェット識別子 |
options | object | ウィジェット固有の設定 |
sortOrder | number | エディタでの表示順 |
バリデーション規則
validation オブジェクトはフィールド型ごとに異なります。
interface FieldValidation {
required?: boolean; // すべての型
min?: number; // number, integer
max?: number; // number, integer
minLength?: number; // string, text
maxLength?: number; // string, text
pattern?: string; // string(正規表現)
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 の行数)
showPreview?: boolean; // image, file
collection?: string; // reference(参照先コレクション)
allowMultiple?: boolean; // reference(複数参照)
[key: string]: unknown; // カスタムウィジェット用オプション
}
参照フィールドの例:
{
slug: "relatedProducts",
type: "reference",
label: "Related Products",
options: {
collection: "products",
allowMultiple: true
}
}
コレクションのクエリ
付属のクエリ関数でコンテンツを取得します。Astro の Live Collections パターンに従い、構造化された結果を返します。
import { getEmDashCollection, getEmDashEntry } from "emdash";
// すべてのエントリ — { entries, error } を返す
const { entries: posts } = await getEmDashCollection("posts");
// ステータスで絞り込み
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
// 件数制限
const { entries: recent } = await getEmDashCollection("posts", {
limit: 5,
});
// タクソノミーで絞り込み
const { entries: newsPosts } = await getEmDashCollection("posts", {
where: { category: "news" },
});
// slug で 1 件 — { entry, error, isPreview } を返す
const { entry: post } = await getEmDashEntry("posts", "my-post-slug");
// エラー処理
const { entries, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
}
型の生成
npx emdash types でスキーマから TypeScript 型を生成します。
// .emdash/types.ts(生成)
export interface Post {
title: string;
content: PortableTextBlock[];
excerpt?: string;
featuredImage?: string;
author: string; // 参照 ID
}
export interface Product {
title: string;
price: number;
description: PortableTextBlock[];
}
データベースへのマッピング
フィールド型は SQLite の列型にマッピングされます。
| フィールド型 | SQLite 型 | メモ |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | 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 |