コンテンツモデル
データベースファーストアプローチを理解する。
コレクションはEmDashのコンテンツモデルの基盤です。各コレクションはコンテンツタイプ(投稿、ページ、商品)を表し、データの構造を決定するフィールド定義を含みます。
コンテンツタイプの下にある管理パネルからコレクションを作成します。各コレクションには以下が含まれます:
| プロパティ | 説明 |
|---|---|
slug | URLセーフな識別子(例:posts、products) |
label | 表示名(例:“ブログ投稿”) |
labelSingular | 単数形(例:“投稿”) |
description | 編集者向けのオプションの説明 |
icon | 管理サイドバー用のLucideアイコン名 |
supports | 下書き、リビジョン、プレビュー、スケジューリング、検索、SEOなどの機能 |
コレクション作成時に必要な機能を有効にします:
| 機能 | 説明 |
|---|---|
drafts | 下書き/公開ワークフローを有効化 |
revisions | バージョンスナップショットでコンテンツ履歴を追跡 |
preview | 下書きコンテンツ用の署名付きプレビューURLを生成 |
scheduling | 将来の日時にコンテンツを公開するようにスケジュール |
// Example collection with all features enabled{ slug: "posts", label: "Blog Posts", labelSingular: "Post", supports: ["drafts", "revisions", "preview", "scheduling"]}EmDashはSQLiteのカラムタイプにマッピングする15のフィールドタイプをサポートしています:
短いテキスト入力。TEXTカラムにマッピングされます。
{ slug: "title", type: "string", label: "Title" }複数行のテキストエリア。TEXTカラムにマッピングされます。
{ slug: "excerpt", type: "text", label: "Excerpt" }URLセーフなスラッグフィールド。TEXTカラムにマッピングされます。
{ slug: "handle", type: "slug", label: "URL Handle" }リッチテキストエディター(TipTap/ProseMirror)。JSONとして保存されます。
{ slug: "content", type: "portableText", label: "Content" }Portable Textは、HTMLを埋め込まずに構造を保持するブロックベースのフォーマットです。
任意のJSONデータ。JSONとして保存されます。
{ slug: "metadata", type: "json", label: "Custom Metadata" }10進数。REALカラムにマッピングされます。
{ slug: "price", type: "number", label: "Price" }整数。INTEGERカラムにマッピングされます。
{ slug: "quantity", type: "integer", label: "Stock Quantity" }真/偽のトグル。INTEGER(0/1)にマッピングされます。
{ slug: "featured", type: "boolean", label: "Featured Post" }日付と時刻のピッカー。ISO 8601文字列として保存されます。
{ slug: "eventDate", type: "datetime", label: "Event Date" }リストからの単一オプション。TEXTカラムにマッピングされます。
{ slug: "status", type: "select", label: "Product Status", validation: { options: ["active", "discontinued", "coming_soon"] }}リストからの複数オプション。JSON配列として保存されます。
{ slug: "features", type: "multiSelect", label: "Product Features", validation: { options: ["wireless", "waterproof", "eco-friendly"] }}メディアライブラリからの画像ピッカー。メディアIDをTEXTとして保存します。
{ slug: "featuredImage", type: "image", label: "Featured Image" }メディアライブラリからのファイルピッカー。メディアIDをTEXTとして保存します。
{ slug: "attachment", type: "file", label: "PDF Attachment" }別のコレクションのエントリーへの参照。エントリー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; // 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";
// すべてのエントリーを取得 - { 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" },});
// スラッグで単一エントリーを取得する - { 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);}スキーマからTypeScript型を生成するには npx emdash types を実行します:
// .emdash/types.ts (generated)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 | |
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 |