SQLite
Desarrollo local con sqlite({ url: "file:./data.db" })
EmDash se integra profundamente con Astro para ofrecer una experiencia completa de CMS. Esta página explica las decisiones arquitectónicas clave y cómo encajan las piezas.
┌──────────────────────────────────────────────────────────────────┐│ Tu sitio Astro ││ ││ ┌────────────────────────────────────────────────────────────┐ ││ │ Integración de EmDash │ ││ │ │ ││ │ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │ ││ │ │ APIs │ │ Panel │ │ Complementos │ │ ││ │ │ de contenido │ │ admin │ │ │ │ ││ │ └──────────────┘ └──────────────┘ └───────────────┘ │ ││ │ │ ││ │ ┌──────────────────────────────────────────────────────┐ │ ││ │ │ Capa de datos │ │ ││ │ │ Base de datos (D1/SQLite) + Almacenamiento (R2/S3) │ │ ││ │ └──────────────────────────────────────────────────────┘ │ ││ └────────────────────────────────────────────────────────────┘ ││ ││ ┌────────────────────────────────────────────────────────────┐ ││ │ Framework Astro │ ││ │ Live Collections · Middleware · Sesiones │ ││ └────────────────────────────────────────────────────────────┘ │└──────────────────────────────────────────────────────────────────┘EmDash se ejecuta como una integración de Astro. Inyecta rutas para el panel de administración y las API REST, proporciona un cargador de contenido para Colecciones en Vivo, y gestiona migraciones de base de datos y conexiones de almacenamiento.
A diferencia de los CMS tradicionales que definen el esquema en código, EmDash almacena las definiciones del esquema en la propia base de datos. Dos tablas del sistema rastrean la estructura de tu contenido:
_emdash_collections — Metadatos de la colección (slug, etiqueta, características)_emdash_fields — Definiciones de campos para cada colecciónCuando creas una colección “products” con campos de título y precio a través de la interfaz de administración, EmDash:
_emdash_collections y _emdash_fieldsALTER TABLE para crear ec_products con las columnas apropiadasEste diseño permite:
Cada colección obtiene su propia tabla SQLite con el prefijo ec_:
-- Creada cuando se agrega la colección "posts"CREATE TABLE ec_posts ( -- Columnas del sistema (siempre presentes) id TEXT PRIMARY KEY, slug TEXT UNIQUE, status TEXT DEFAULT 'draft', -- draft, published, scheduled author_id TEXT, created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')), published_at TEXT, deleted_at TEXT, -- Eliminación lógica version INTEGER DEFAULT 1, -- Bloqueo optimista
-- Columnas de contenido (de tus definiciones de campo) title TEXT NOT NULL, content JSON, -- Portable Text excerpt TEXT);¿Por qué tablas por colección en lugar de una única tabla de contenido con JSON?
EmDash utiliza las Colecciones en Vivo de Astro 6 para servir contenido en tiempo de ejecución. Los cambios en el contenido están disponibles inmediatamente sin reconstrucciones estáticas.
El emdashLoader() implementa la interfaz LiveLoader de Astro:
import { defineLiveCollection } from "astro:content";import { emdashLoader } from "emdash/runtime";
export const collections = { _emdash: defineLiveCollection({ loader: emdashLoader() }),};Consulta contenido usando las funciones envoltorio proporcionadas:
import { getEmDashCollection, getEmDashEntry } from "emdash";
// Obtener todas las publicaciones publicadasconst { entries: posts } = await getEmDashCollection("posts");
// Obtener borradoresconst { entries: drafts } = await getEmDashCollection("posts", { status: "draft",});
// Obtener una sola entrada por slugconst { entry: post } = await getEmDashEntry("posts", "my-post-slug");La integración de EmDash utiliza la API injectRoute de Astro para agregar rutas de administración y API:
| Patrón de Ruta | Propósito |
|---|---|
/_emdash/admin/[...path] | Panel de administración SPA |
/_emdash/api/manifest | Manifiesto de administración (colecciones, complementos) |
/_emdash/api/content/[collection] | CRUD para entradas de contenido |
/_emdash/api/media/* | Operaciones de biblioteca multimedia |
/_emdash/api/schema/* | Gestión de esquemas |
/_emdash/api/settings | Configuraciones del sitio |
/_emdash/api/menus/* | Menús de navegación |
/_emdash/api/taxonomies/* | Categorías, etiquetas, taxonomías personalizadas |
Las rutas se inyectan desde el paquete emdash—nada se copia en tu proyecto.
EmDash utiliza Kysely para consultas SQL con seguridad de tipos en todas las bases de datos soportadas:
SQLite
Desarrollo local con sqlite({ url: "file:./data.db" })
D1
SQL sin servidor de Cloudflare con d1({ binding: "DB" })
libSQL
SQLite remoto con libsql({ url: "...", authToken: "..." })
La configuración de la base de datos se pasa a la integración en astro.config.mjs:
import { defineConfig } from "astro/config";import emdash from "emdash/astro";import { sqlite } from "emdash/db";import { local } from "emdash/storage";
export default defineConfig({ integrations: [ emdash({ database: sqlite({ url: "file:./data.db" }), storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file", }), }), ],});Los archivos multimedia se almacenan por separado de la base de datos. EmDash soporta:
Las subidas utilizan URLs firmadas para cargas directas de cliente a almacenamiento, evitando los límites de tamaño del cuerpo de los Workers.
Los complementos extienden EmDash a través de un sistema de ganchos inspirado en WordPress:
content:beforeSave, content:afterSave, content:beforeDelete, content:afterDeletemedia:beforeUpload, media:afterUploadLos complementos pueden ejecutarse en dos modos:
import { seoPlugin } from "@emdash-cms/plugin-seo";
emdash({ plugins: [seoPlugin({ maxTitleLength: 60 })],});Una solicitud de contenido típica sigue esta ruta:
Astro recibe la solicitud
Se ejecuta tu componente de página.
Consulta de contenido
getEmDashCollection() llama a getLiveCollection() de Astro.
Se ejecuta el cargador
emdashLoader consulta la tabla ec_* correspondiente a través de Kysely.
Se devuelven los datos
Las entradas se mapean al formato de Astro con id, slug y data.
La página se renderiza
Tu componente recibe el contenido y genera el HTML.
Para solicitudes de administración:
El middleware autentica
Valida el token de sesión.
La ruta API procesa la solicitud
Ejecuta operaciones CRUD a través de repositorios.
Se disparan los ganchos
Se ejecutan beforeCreate, afterUpdate y los demás hooks correspondientes.
Se actualiza la base de datos
Kysely ejecuta el SQL necesario.
Se devuelve la respuesta
La SPA de administración recibe una respuesta JSON.
EmDash genera módulos virtuales en tiempo de compilación para configurar el entorno de ejecución:
| Módulo | Propósito |
|---|---|
virtual:emdash/config | Configuración de base de datos y almacenamiento |
virtual:emdash/dialect | Fábrica de dialectos de base de datos |
virtual:emdash/plugin-admins | Importaciones estáticas para las interfaces de administración de complementos |
Este enfoque garantiza que los empaquetadores puedan resolver y eliminar el código no utilizado de los complementos correctamente.
Colecciones
Aprende sobre colecciones de contenido y tipos de campos.
Modelo de Contenido
Comprende el modelo de contenido basado en base de datos.
Panel de Administración
Explora la arquitectura del panel de administración.