EmDash supporta diversi backend di database. Scegli in base al tuo target di deployment.
Panoramica
| Database | Ideale per | Deployment |
|---|---|---|
| D1 | Cloudflare Workers | Edge, distribuito globalmente |
| Hyperdrive | PostgreSQL su Cloudflare Workers | Edge, Postgres esistente |
| PostgreSQL | Produzione Node.js | Qualsiasi piattaforma con Postgres |
| libSQL | Database remoti | Edge o Node.js |
| SQLite | Node.js, sviluppo locale | Server singolo |
Cloudflare D1
D1 è il database SQLite serverless di Cloudflare. Usalo quando effettui il deploy su Cloudflare Workers.
import { d1 } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
database: d1({ binding: "DB" }),
}),
],
});
Configurazione
| Opzione | Tipo | Default | Descrizione |
|---|---|---|---|
binding | string | — | Nome del binding D1 da wrangler.jsonc |
session | string | "disabled" | Modalità di replica in lettura (vedi sotto) |
bookmarkCookie | string | "__em_d1_bookmark" | Nome del cookie per i bookmark di sessione |
Setup
wrangler.jsonc
{
"d1_databases": [
{
"binding": "DB",
"database_name": "emdash-db"
}
]
} wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "emdash-db" Read Replicas
D1 supporta la replica in lettura per ridurre la latenza di lettura per i siti distribuiti globalmente. Quando abilitata, le query di lettura vengono instradate verso le repliche vicine anziché interrogare sempre il database primario.
EmDash utilizza l’API D1 Sessions per gestire questo in modo trasparente. Abilitalo con l’opzione session:
import { d1 } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
database: d1({
binding: "DB",
session: "auto",
}),
}),
],
});
Modalità di sessione
| Modalità | Comportamento |
|---|---|
"disabled" | Nessuna sessione. Tutte le query vanno al primario. Default. |
"auto" | Le richieste anonime leggono dalla replica più vicina. Gli utenti autenticati ottengono consistenza read-your-writes tramite cookie bookmark. |
"primary-first" | Come "auto", ma la prima query va sempre al primario. Per siti con scritture molto frequenti. |
Come funziona
- I visitatori anonimi ottengono
first-unconstrained— le letture vanno alla replica più vicina per la latenza più bassa. Dato che gli utenti anonimi non scrivono mai, non hanno bisogno di garanzie di consistenza. - Gli utenti autenticati (editor, autori) ottengono sessioni basate su bookmark. Dopo una scrittura, un cookie bookmark garantisce che la richiesta successiva veda almeno quello stato.
- Le richieste di scrittura (
POST,PUT,DELETE) partono sempre dal database primario. - Le query al momento del build (Astro content collections) bypassano completamente le sessioni e usano direttamente il primario.
libSQL
libSQL è un fork di SQLite che supporta connessioni remote. Usalo quando hai bisogno di un database remoto senza Cloudflare D1.
import { libsql } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: libsql({
url: process.env.LIBSQL_DATABASE_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
}),
}),
],
});
Configurazione
| Opzione | Tipo | Descrizione |
|---|---|---|
url | string | URL del database (libsql://... o file:...) |
authToken | string | Token di autenticazione per database remoti (opzionale in locale) |
Sviluppo locale
Usa un file libSQL locale durante lo sviluppo:
database: libsql({ url: "file:./data.db" });
PostgreSQL
PostgreSQL è supportato per i deploy Node.js che necessitano di un database relazionale completo.
import { postgres } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: postgres({
connectionString: process.env.DATABASE_URL,
}),
}),
],
});
Configurazione
Puoi connetterti con una stringa di connessione o parametri individuali:
// Stringa di connessione
database: postgres({
connectionString: "postgres://user:password@localhost:5432/emdash",
});
// Parametri individuali
database: postgres({
host: "localhost",
port: 5432,
database: "emdash",
user: "emdash",
password: process.env.DB_PASSWORD,
ssl: true,
});
| Opzione | Tipo | Descrizione |
|---|---|---|
connectionString | string | URL di connessione PostgreSQL |
host | string | Host del database |
port | number | Porta del database |
database | string | Nome del database |
user | string | Utente del database |
password | string | Password del database |
ssl | boolean | Abilitare SSL |
pool.min | number | Connessioni minime del pool (default 0) |
pool.max | number | Connessioni massime del pool (default 10) |
Connection pooling
L’adapter usa pg.Pool internamente. Regola la dimensione del pool in base al tuo deployment:
database: postgres({
connectionString: process.env.DATABASE_URL,
pool: { min: 2, max: 20 },
});
Hyperdrive
Usa l’adapter hyperdrive() per eseguire EmDash su Cloudflare Workers con un database PostgreSQL esistente — o compatibile Postgres (es. PlanetScale Postgres). Hyperdrive raggruppa e accelera la connessione attraverso la rete Cloudflare; il dialetto PostgreSQL di EmDash esegue le query.
import { hyperdrive, r2 } from "@emdash-cms/cloudflare";
export default defineConfig({
integrations: [
emdash({
database: hyperdrive({ binding: "HYPERDRIVE" }),
storage: r2({ binding: "MEDIA" }),
}),
],
});
Requisiti
pg >= 8.16.3installato nel tuo sito (pnpm add pg)compatibility_flags: ["nodejs_compat"]compatibility_date >= "2024-09-23"
Setup
Crea la configurazione Hyperdrive e aggiungi il binding alla tua configurazione Wrangler:
wrangler hyperdrive create emdash-db \
--connection-string "postgres://user:password@host/db?sslmode=verify-full" \
--caching-disabled
wrangler.jsonc
{
"hyperdrive": [
{
"binding": "HYPERDRIVE",
"id": "<your-hyperdrive-id>"
}
]
} wrangler.toml
[[hyperdrive]]
binding = "HYPERDRIVE"
id = "<your-hyperdrive-id>" Configurazione
| Opzione | Tipo | Default | Descrizione |
|---|---|---|---|
binding | string | "HYPERDRIVE" | Binding Hyperdrive primario (caching disabilitato) |
cachedBinding | string | — | Binding opzionale con caching abilitato per le letture anonime |
max | number | 5 | Dimensione max del pool di connessioni in-Worker verso Hyperdrive |
Servire le letture anonime dalla cache
Per default, disabiliti completamente il caching di Hyperdrive poiché l’admin e le scritture necessitano di consistenza read-after-write. Ma le letture pubbliche anonime — nessuna sessione, nessuna scrittura — possono tollerare una breve finestra di dati obsoleti. Se questo compromesso è accettabile, esegui due configurazioni Hyperdrive sullo stesso database: una con caching disabilitato (il binding primario) e una con caching abilitato (cachedBinding). EmDash instrada poi le richieste di lettura anonime tramite il binding con cache mentre ogni richiesta autenticata e ogni scrittura resta sul primario senza cache, preservando la consistenza read-after-write.
# Primario — cache DISABILITATA (admin, richieste auth., scritture, migrazioni)
wrangler hyperdrive create emdash-db \
--connection-string "postgres://user:password@host/db?sslmode=verify-full" \
--caching-disabled
# Con cache — STESSA stringa di connessione, cache ABILITATA (solo letture anonime)
wrangler hyperdrive create emdash-db-cached \
--connection-string "postgres://user:password@host/db?sslmode=verify-full"
{
"hyperdrive": [
{ "binding": "HYPERDRIVE", "id": "<caching-disabled-id>" },
{ "binding": "HYPERDRIVE_CACHED", "id": "<caching-enabled-id>" }
]
}
database: hyperdrive({ binding: "HYPERDRIVE", cachedBinding: "HYPERDRIVE_CACHED" });
Questo è il pattern a due configurazioni che Cloudflare documenta per il caching. EmDash decide quale binding usare per ogni richiesta:
- Letture anonime dei percorsi del sito pubblico (
GET/HEAD, nessuna sessione, non sotto/_emdash) →cachedBindingcon cache. - Richieste autenticate (editor, autori) →
bindingsenza cache. - Scritture (
POST,PUT,DELETE, incluse quelle anonime) →bindingsenza cache. - Qualsiasi richiesta sotto
/_emdash(admin, setup, auth, API interne), anche unGETanonimo →bindingsenza cache. - Migrazioni e avvio a freddo → sempre il
bindingprimario.
SQLite
SQLite con better-sqlite3 è l’opzione più semplice per i deploy Node.js.
import { sqlite } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
}),
],
});
Configurazione
| Opzione | Tipo | Descrizione |
|---|---|---|
url | string | Percorso file con prefisso file: |
Percorso del file
L’url deve iniziare con file::
// Percorso relativo
database: sqlite({ url: "file:./data/emdash.db" });
// Percorso assoluto
database: sqlite({ url: "file:/var/data/emdash.db" });
// Da variabile d'ambiente
database: sqlite({ url: `file:${process.env.DATABASE_PATH}` });
Migrazioni
EmDash esegue le migrazioni automaticamente alla prima richiesta, per ogni dialetto supportato (D1, SQLite, libSQL, PostgreSQL). Le migrazioni sono integrate nel pacchetto emdash e incorporate nel tuo build.
Se il database è vuoto (nessuna collection) e l’assistente di setup non è stato completato, EmDash applica anche un file seed al primo avvio. Il seed viene letto da .emdash/seed.json, dal percorso in package.json#emdash.seed, o da seed/seed.json — il primo trovato — e incorporato nel build al momento della compilazione. Se nessuno è presente, viene usato un seed predefinito integrato. Gli avvii successivi contro un database esistente lasciano il suo contenuto intatto.
Configurazione basata sull’ambiente
Usa database diversi per ambiente:
import { sqlite, libsql, postgres } from "emdash/db";
import { d1 } from "@emdash-cms/cloudflare";
const database = import.meta.env.PROD ? d1({ binding: "DB" }) : sqlite({ url: "file:./data.db" });
export default defineConfig({
integrations: [emdash({ database })],
});
La scelta può anche essere basata su una variabile d’ambiente anziché sulla modalità di build:
const database = process.env.DATABASE_URL
? postgres({ connectionString: process.env.DATABASE_URL })
: sqlite({ url: "file:./data.db" });