Référence de configuration

Sur cette page

La configuration principale d’EmDash se trouve dans astro.config.mjs, tandis que src/live.config.ts enregistre le chargeur de contenu. Les valeurs propres au déploiement peuvent aussi provenir de variables d’environnement. Un petit bloc de métadonnées dans package.json prend en charge les libellés de modèle et d’anciens flux locaux de la CLI.

Intégration Astro

Configurez EmDash comme intégration Astro dans astro.config.mjs :

import { defineConfig } from "astro/config";
import emdash, { local, s3 } from "emdash/astro";
import { sqlite, libsql } from "emdash/db";

export default defineConfig({
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data.db" }),
			storage: local({
				directory: "./uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
			plugins: [],
		}),
	],
});

Options de l’intégration

database

Obligatoire. Configuration de l’adaptateur de base de données. Choisissez un adaptateur :

// SQLite (Node.js)
database: sqlite({ url: "file:./data.db" });

// PostgreSQL
database: postgres({ connectionString: process.env.DATABASE_URL });

// libSQL
database: libsql({
	url: process.env.LIBSQL_DATABASE_URL,
	authToken: process.env.LIBSQL_AUTH_TOKEN,
});

// Cloudflare D1 (import from @emdash-cms/cloudflare)
database: d1({ binding: "DB" });

Consultez Options de base de données pour plus de détails.

migrations

Facultative. Contrôle la gestion à l’exécution des migrations internes de la base de données d’EmDash. Si cette option est omise, la valeur par défaut est { runtime: "auto" }.

migrations: {
	runtime: "check", // "auto" | "check" | "manual"
	dev: "auto",     // optional development override
}

auto vérifie et applique les migrations en attente, check renvoie 503 lorsque des migrations connues du build en cours d’exécution sont en attente (sauf pour les requêtes vers le point de terminaison d’images qu’EmDash installe), et manual n’effectue aucune requête de migration à l’exécution. EMDASH_MIGRATIONS_MODE remplace le mode d’exécution effectif. Consultez Gérer les migrations de la base de données du cœur avant d’adopter check ou manual.

storage

Facultative. Configuration de l’adaptateur de stockage des médias. Lorsque cette option est omise, EmDash stocke les fichiers dans ./.emdash/uploads et les sert via /_emdash/api/media/file. Choisissez un adaptateur lorsque le répertoire local par défaut ne convient pas :

// Local filesystem (development)
storage: local({
	directory: "./uploads",
	baseUrl: "/_emdash/api/media/file",
});

// R2 binding (Cloudflare Workers)
storage: r2({
	binding: "MEDIA",
	publicUrl: "https://pub-xxxx.r2.dev", // optional
});

// S3-compatible (any platform) — all fields from S3_* environment variables
storage: s3()

// Or with explicit values
storage: s3({
	endpoint: "https://s3.amazonaws.com",
	bucket: "my-bucket",
	accessKeyId: process.env.S3_ACCESS_KEY_ID,
	secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
	region: "us-east-1", // optional, default: "auto"
	publicUrl: "https://cdn.example.com", // optional
});

Consultez Options de stockage pour plus de détails.

images

Facultative. Contrôle si EmDash intègre les médias stockés à l’optimisation d’images d’Astro. La valeur par défaut est true.

Lorsqu’elle est activée, EmDash enveloppe le point de terminaison d’images d’Astro afin que <Image> et getImage() puissent lire les octets sources directement depuis l’adaptateur de stockage configuré. Cela fonctionne aussi lorsque l’URL d’origine du média se trouve derrière Cloudflare Access. Les requêtes vers le point de terminaison enveloppé ignorent le démarrage du runtime d’EmDash ; sur ces requêtes, locals.emdash ne contient donc que storage, ainsi que db pour un utilisateur connecté. locals.user est défini comme sur les autres routes publiques. Définissez images: false lorsqu’un autre service d’images gère les médias ou lorsque chaque image doit être rendue sans l’enveloppe de point de terminaison d’EmDash.

emdash({
	images: false,
});

mediaProviders

Facultative. Ajoute des services de médias à la médiathèque. Le fournisseur local adossé au stockage reste disponible automatiquement ; chaque descripteur de ce tableau ajoute un autre endroit où les éditeurs peuvent parcourir ou téléverser des médias.

L’exemple suivant ajoute Cloudflare Images et Cloudflare Stream :

import { cloudflareImages, cloudflareStream } from "@emdash-cms/cloudflare";

emdash({
	mediaProviders: [cloudflareImages({}), cloudflareStream({})],
});

Les identifiants des fournisseurs sont résolus à l’exécution. Les configurations vides ci-dessus utilisent les variables d’environnement Cloudflare par défaut décrites dans les sections d’adaptateurs cloudflareImages(config) et cloudflareStream(config). Consultez Médiathèque : fournisseurs de médias pour la configuration des bindings et du rendu.

objectCache

Facultative. Met en cache les résultats des requêtes de contenu et de configuration dans un magasin clé/valeur, afin que les lectures soient servies sans interroger la base de données à chaque requête. Désactivée si omise. Choisissez un adaptateur :

// Cloudflare KV (shared across all isolates)
import { kvCache } from "@emdash-cms/cloudflare";
objectCache: kvCache({ binding: "CACHE" });

// In-memory (Node.js / development)
import { memoryCache } from "emdash/astro";
objectCache: memoryCache();

Consultez Cache d’objets pour la configuration et les options.

middleware.outer

Facultative. Enregistre un module de middleware Astro en dehors de toute la pile de middlewares d’EmDash. Comme l’intégration l’enregistre avec order: "pre" d’Astro, il s’exécute aussi avant le middleware défini dans src/middleware.ts. Utilisez-le pour des filtres de requêtes ou des caches de réponse complète qui doivent éviter l’initialisation du runtime et de la base de données en cas de succès du cache, ou pour des en-têtes de réponse qui dépendent du HTML final d’EmDash.

emdash({
	middleware: {
		outer: "./src/outer-middleware.ts",
	},
});

L’ordre d’exécution est le suivant :

  1. Le middleware externe s’exécute jusqu’à await next().
  2. EmDash initialise son runtime et sa base de données, puis exécute les middlewares de configuration, d’authentification et de contexte de requête.
  3. La route Astro est rendue.
  4. EmDash applique les modifications de la réponse, y compris le HTML d’édition visuelle et les en-têtes de sécurité et de chronométrage.
  5. next() se résout dans le middleware externe avec cette réponse finale.

Avant d’appeler next(), le middleware dispose de la requête Astro normale et du contexte d’exécution de la plateforme, mais locals.emdash, locals.user, la base de données et l’état d’EmDash lié à la requête ne sont pas disponibles. Une Response anticipée contourne entièrement EmDash ; elle doit donc inclure les en-têtes de sécurité et de cache dont elle a besoin. Une fois next() résolu, vous pouvez finaliser sans risque les nonces CSP, mettre en cache le corps complet ou définir Content-Length. Si le middleware modifie le corps, supprimez ou recalculez tout en-tête Content-Length existant.

Le hook utilise l’API de middleware d’Astro à la fois sur Node et sur Cloudflare. Cet exemple minimal avec la Cache API de Cloudflare ne met en cache que les réponses HTML anonymes et renvoie les succès avant l’initialisation d’EmDash :

import { waitUntil } from "cloudflare:workers";
import { defineMiddleware } from "astro:middleware";

export const onRequest = defineMiddleware(async ({ request }, next) => {
	if (request.method !== "GET" || request.headers.has("cookie")) {
		return next();
	}

	const cacheKey = new Request(request.url, { method: "GET" });
	const cached = await caches.default.match(cacheKey);
	if (cached) return cached;

	const response = await next();
	const isHtml = response.headers.get("content-type")?.includes("text/html");
	const isPrivate = response.headers.get("cache-control")?.includes("no-store");
	if (response.ok && isHtml && !isPrivate) {
		waitUntil(caches.default.put(cacheKey, response.clone()));
	}

	return response;
});

Sur Node, utilisez la même forme de middleware avec un cache compatible Node, comme Redis. Les clés de cache et les règles de contournement doivent inclure chaque propriété de la requête qui modifie la réponse rendue.

playground

Facultative. Active le middleware utilisé par les playgrounds EmDash jetables, exécutés dans le navigateur. Il crée une base de données Durable Object accessible en écriture pour chaque session, applique le seed configuré et connecte le visiteur en tant qu’administrateur anonyme avant l’exécution du middleware EmDash normal.

import { playgroundDatabase } from "@emdash-cms/cloudflare";

emdash({
	database: playgroundDatabase({ binding: "PLAYGROUND_DB" }),
	playground: {
		middlewareEntrypoint: "@emdash-cms/cloudflare/db/playground-middleware",
	},
});

Ce mode nécessite @emdash-cms/cloudflare et un binding Durable Object. Il contourne les middlewares normaux de configuration et d’authentification ; ne l’utilisez donc que pour des sites de démonstration éphémères, pas pour un CMS de production.

plugins

Facultative. Tableau de plugins qui s’exécutent dans le même processus que le site Astro. Les plugins natifs vont ici. Un plugin compatible avec le sandbox peut aussi s’exécuter ici lorsque vous lui faites confiance pour un accès complet au processus et que vous n’avez pas besoin d’isolation.

L’exemple suivant enregistre un plugin natif :

import seoPlugin from "@emdash-cms/plugin-seo";

plugins: [seoPlugin()];

Les plugins natifs peuvent utiliser directement les API du serveur et du framework ; ils ne peuvent donc pas être déplacés vers sandboxed, sauf si le paquet fournit aussi un point d’entrée de plugin compatible avec le sandbox. Consultez Choisir un format de plugin pour les différences de développement et de déploiement.

sandboxed

Facultative. Tableau de plugins compatibles avec le sandbox qui utilisent les API de plugin déclarées d’EmDash et s’exécutent dans des environnements isolés. Ne placez pas ici un plugin natif : le code natif peut dépendre d’un accès au processus et au framework que le sandbox ne fournit pas.

import thirdPartyPlugin from "third-party-emdash-plugin";
import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxed: [thirdPartyPlugin()],
	sandboxRunner: sandbox(),
});

Les plugins en sandbox sont ignorés lorsqu’aucun exécuteur de sandbox utilisable n’est configuré. Consultez Sandbox des plugins pour la configuration de l’exécuteur sur Cloudflare et Node.js.

sandboxRunner

Facultative. Spécificateur de module de la fabrique qui démarre les environnements d’exécution isolés des plugins. Il est obligatoire pour les plugins de sandboxed et pour les plugins du marketplace ou du registre.

Sur Cloudflare Workers, utilisez l’adaptateur sandbox() :

import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxRunner: sandbox(),
});

Les déploiements Node.js utilisent le module d’exécuteur workerd décrit dans Sandbox des plugins : Node.js.

sandbox

Facultative. Contrôle si un exécuteur de sandbox configuré isole les plugins. Le sandbox est activé lorsque sandboxRunner est configuré. Définissez sandbox: false uniquement pour diagnostiquer si un problème provient d’un plugin ou de son environnement d’exécution en sandbox :

emdash({
	sandboxRunner: sandbox(),
	sandbox: false,
});

Avec false, les plugins déclarés dans sandboxed et ceux installés depuis le marketplace s’exécutent dans le processus serveur principal, sans isolation ni limites de ressources. Rétablissez le sandbox après le diagnostic.

registry

Facultative. Configure l’agrégateur et la politique du registre de plugins. Sans valeur explicite, EmDash utilise https://registry.emdashcms.com lorsque sandboxRunner est configuré et que sandbox n’est pas false.

Définissez registry: false pour désactiver la découverte dans le registre et les plugins installés depuis le registre, tout en gardant l’exécuteur de sandbox disponible pour les plugins déclarés dans sandboxed et les anciens plugins du Marketplace :

emdash({
	sandboxRunner: sandbox(),
	registry: false,
});

Transmettez l’URL du service de registre sous forme de chaîne, ou utilisez un objet lorsque le site a besoin de sources de modération ou d’une politique d’ancienneté des versions. L’exemple suivant utilise la forme objet :

import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxRunner: sandbox(),
	registry: {
		aggregatorUrl: "https://registry.emdashcms.com",
		acceptLabelers: "did:web:labels.emdashcms.com",
		policy: {
			minimumReleaseAge: "48h",
			minimumReleaseAgeExclude: ["did:plc:yourfirstpartydid"],
		},
	},
});
OptionTypeDescription
aggregatorUrlstringURL de base du service de registre. Utilisez HTTPS en production.
acceptLabelersstringIdentifiants décentralisés (DID) facultatifs, séparés par des virgules, des services de modération acceptés par la requête. Un DID est un identifiant de compte Atmosphere stable. Ce paramètre ne peut pas remplacer la politique du service de registre.
policy.minimumReleaseAgestring | numberRetient les versions plus récentes que cette ancienneté. Chaîne de durée ("48h", "7d") ou secondes.
policy.minimumReleaseAgeExcludestring[]DID d’éditeurs, ou paires <did>/<plugin-slug>, exemptés de la retenue.

La politique d’ancienneté des versions n’exempte la première version d’un paquet que lorsque le registre signale une version conservée et confirme qu’il a observé le paquet en continu. Un paquet rempli après coup, une version antérieure supprimée ou l’absence de preuves d’historique maintiennent la retenue en vigueur. Les exemptions explicites d’éditeurs et de paquets s’appliquent quel que soit l’historique.

Consultez Le registre de plugins pour le flux d’installation et le modèle de confiance.

marketplace

Obsolète. URL de base utilisée pour mettre à jour les plugins installés depuis l’ancien Marketplace. La navigation dans le Marketplace et les nouvelles installations ne sont pas affichées dans l’administration. Les plugins Marketplace existants restent actualisables et désinstallables tant que cette option est configurée.

emdash({
	marketplace: "https://marketplace.emdashcms.com",
	sandboxRunner: sandbox(),
});

Les URL de production doivent utiliser HTTPS ; HTTP n’est accepté que pour localhost et 127.0.0.1 pendant le développement. Conservez cette option jusqu’à ce que chaque plugin Marketplace ait été remplacé ou désinstallé, puis supprimez-la. Suivez Migrer depuis Marketplace pour la procédure complète.

fonts

Facultative. Configuration des polices de l’interface d’administration.

Par défaut, EmDash charge Noto Sans via l’API de polices d’Astro. Les polices sont téléchargées depuis Google au moment du build et auto-hébergées ; il n’y a donc aucune requête CDN à l’exécution. La police de base couvre les écritures latine, cyrillique, grecque, devanagari et vietnamienne.

Pour prendre en charge d’autres systèmes d’écriture, transmettez des noms de scripts. L’exemple suivant ajoute l’arabe et le japonais :

emdash({
  fonts: {
    scripts: ["arabic", "japanese"],
  },
})

Les scripts disponibles sont arabic, armenian, bengali, chinese-simplified, chinese-traditional, chinese-hongkong, devanagari, ethiopic, farsi, georgian, gujarati, gurmukhi, hebrew, japanese, kannada, khmer, korean, lao, malayalam, myanmar, oriya, sinhala, tamil, telugu, thai et tibetan.

Chaque script correspond à la variante Noto Sans associée sur Google Fonts (p. ex. "arabic" charge Noto Sans Arabic). Toutes les graisses partagent un même nom de font-family et utilisent unicode-range, de sorte que le navigateur ne télécharge que les fichiers dont il a besoin pour les caractères de la page.

Définissez-la sur false pour désactiver entièrement l’injection de polices et utiliser les polices système :

emdash({
	fonts: false,
})

Le CSS de l’administration utilise la variable CSS --font-emdash. Elle est définie automatiquement par la configuration des polices ci-dessus.

auth

Facultative. Un adaptateur d’authentification. La connexion intégrée d’EmDash repose sur les passkeys ; définir auth les remplace par un fournisseur externe. L’adaptateur Cloudflare Access, access(), est fourni par @emdash-cms/cloudflare :

import { access } from "@emdash-cms/cloudflare";

emdash({
	auth: access({
		teamDomain: "myteam.cloudflareaccess.com",
		audience: "your-app-audience-tag",
		roleMapping: {
			Admins: 50,
			Editors: 40,
		},
	}),
});

Options de access() :

OptionTypePar défautDescription
teamDomainstringobligatoireVotre domaine d’équipe Cloudflare Access
audiencestring—Balise d’audience (AUD) de l’application. Sur Workers, préférez audienceEnvVar.
audienceEnvVarstring"CF_ACCESS_AUDIENCE"Variable d’environnement dans laquelle lire la balise d’audience à l’exécution
autoProvisionbooleantrueCrée un utilisateur EmDash à la première connexion
defaultRolenumber30Niveau de rôle des utilisateurs non couverts par roleMapping (voir Rôles des utilisateurs)
syncRolesbooleanfalseRéapplique roleMapping à chaque connexion plutôt qu’au seul provisionnement
roleMappingobject—Associe des noms de groupes du fournisseur d’identité à des niveaux de rôle EmDash ; la première correspondance l’emporte

authProviders

Facultative. Un tableau de fournisseurs de connexion enfichables (au niveau supérieur, à côté de auth). Chaque entrée est le résultat de l’appel d’une fabrique de fournisseur, comme illustré ci-dessous :

import { github } from "emdash/auth/providers/github";
import { google } from "emdash/auth/providers/google";
import { atproto } from "@emdash-cms/auth-atproto";

emdash({
	authProviders: [github(), google(), atproto()],
});

Fournisseurs intégrés :

  • github() — lit EMDASH_OAUTH_GITHUB_CLIENT_ID / EMDASH_OAUTH_GITHUB_CLIENT_SECRET (ou les équivalents sans préfixe).
  • google() — lit EMDASH_OAUTH_GOOGLE_CLIENT_ID / EMDASH_OAUTH_GOOGLE_CLIENT_SECRET.
  • microsoft() — lit EMDASH_OAUTH_MICROSOFT_CLIENT_ID / EMDASH_OAUTH_MICROSOFT_CLIENT_SECRET / EMDASH_OAUTH_MICROSOFT_TENANT_ID (ou les équivalents sans préfixe). Accepte { emailVerified }. Voir Microsoft.
  • atproto() — connexion avec un compte Atmosphere (Bluesky et l’ensemble du réseau AT Protocol). Aucune variable d’environnement requise. Accepte { allowedDIDs, allowedHandles, defaultRole }. Voir le guide de connexion Atmosphere.

Les paquets tiers peuvent enregistrer leurs propres fournisseurs avec la même forme AuthProviderDescriptor — voir Fournisseurs de connexion.

mcp

Facultative. Active le point de terminaison du Model Context Protocol (MCP) à /_emdash/api/mcp. Le point de terminaison est activé par défaut et exige un jeton porteur ; l’activer n’accorde donc aucun accès anonyme.

Définissez l’option sur false lorsque le site ne doit pas exposer de point de terminaison MCP :

emdash({
	mcp: false,
});

Consultez la Référence du serveur MCP pour la création de jetons et la configuration des clients.

siteUrl

L’origine publique du site visible par le navigateur (schéma + hôte + port facultatif, sans chemin). Définissez-la avant d’exécuter la configuration de production, sauf si le site est déployé sur Cloudflare Workers. Sinon, seuls les hôtes de développement en loopback peuvent terminer la configuration sans origine configurée.

Derrière un proxy inverse qui termine le TLS, Astro.url renvoie l’adresse interne (http://localhost:4321) au lieu de l’adresse publique (https://cms.example.com). Cela casse les passkeys, la correspondance d’origine CSRF, les redirections OAuth, les redirections de connexion, la découverte MCP, les exports d’instantanés, le sitemap, robots.txt et les données structurées JSON-LD. Définir siteUrl corrige tout cela d’un seul coup.

L’intégration valide cette valeur au chargement : ce doit être une URL valide avec le protocole http: ou https:, normalisée en origine (le chemin est supprimé).

L’exemple suivant définit l’origine publique :

emdash({
	database: sqlite({ url: "file:./data.db" }),
	storage: local({
		directory: "./uploads",
		baseUrl: "/_emdash/api/media/file",
	}),
	siteUrl: "https://cms.example.com",
});

Lorsque siteUrl n’est pas définie dans la configuration, EmDash consulte les variables d’environnement dans cet ordre : EMDASH_SITE_URL, puis SITE_URL. C’est utile pour les déploiements en conteneurs, où l’URL publique est définie à l’exécution.

La configuration échoue avec SITE_URL_REQUIRED sur un hôte hors loopback lorsqu’aucune des deux sources n’est définie. Cela empêche la première requête de configuration non authentifiée de choisir l’origine utilisée dans les e-mails d’authentification ultérieurs. Un build de production déployé sur Cloudflare Workers fait exception : Cloudflare n’achemine que les requêtes destinées aux noms d’hôte liés au Worker, si bien que la configuration enregistre https:// et le nom d’hôte sur lequel elle s’exécute. Le même build servi par wrangler dev, astro preview ou un workerd auto-hébergé sur une adresse accessible n’offre pas cette garantie ; définissez-y d’abord siteUrl ou EMDASH_SITE_URL.

Sur Cloudflare Workers, le repli sur les variables d’environnement lit process.env. Avec nodejs_compat, Cloudflare renseigne process.env par défaut pour les dates de compatibilité à partir du 2025-04-01. Les projets figés sur une date antérieure doivent aussi ajouter nodejs_compat_populate_process_env.

// wrangler.jsonc
{
	"compatibility_date": "2026-02-24",
	"compatibility_flags": ["nodejs_compat"],
	"vars": { "EMDASH_SITE_URL": "https://cms.example.com" },
}

allowedOrigins

Facultative. Origines de navigateur supplémentaires acceptées par la vérification des passkeys pour un déploiement disponible sous plusieurs noms d’hôte.

siteUrl définit une seule origine canonique. Lorsque le même déploiement EmDash est accessible sous plusieurs noms d’hôte partageant un domaine parent enregistrable (p. ex. https://example.com et https://preview.example.com), la vérification des passkeys rejette les assertions dont l’origine ne correspond pas exactement à siteUrl — alors même que WebAuthn permet aux passkeys d’être valides entre sous-domaines sous le même rpId.

Déclarez les origines supplémentaires acceptées via allowedOrigins dans astro.config.mjs ou la variable d’environnement EMDASH_ALLOWED_ORIGINS. La siteUrl canonique reste la source du rpId ; les entrées listées ici sont acceptées au moment de la vérification. Les deux sources sont fusionnées à l’exécution : la configuration peut ainsi déclarer les origines stables (versionnées, relues dans le code), tandis que l’environnement ajoute des compléments propres à l’environnement (p. ex. des aperçus de PR éphémères).

L’exemple suivant déclare une origine supplémentaire dans la configuration :

emdash({
	siteUrl: "https://example.com",
	allowedOrigins: ["https://preview.example.com"],
})

Les valeurs équivalentes peuvent aussi provenir de variables d’environnement :

EMDASH_SITE_URL=https://example.com
EMDASH_ALLOWED_ORIGINS=https://preview.example.com,https://staging.example.com
Validation

EmDash valide ces valeurs pour éviter une configuration morte que le navigateur ne respecterait jamais :

  • Chaque entrée doit être une URL http: ou https: analysable, sans point final et sans étiquette vide dans le nom d’hôte.
  • Lorsque allowedOrigins n’est pas vide, siteUrl doit être définie (par l’une ou l’autre source) et ne doit être ni un littéral IP ni un nom d’hôte avec point final.
  • Chaque origine doit être le même nom d’hôte que siteUrl ou l’un de ses sous-domaines. (WebAuthn exige que rpId soit un suffixe enregistrable de chaque origine.)

Lorsque la validation échoue, vous voyez une erreur indiquant sa source, comme EmDash config error in EMDASH_ALLOWED_ORIGINS: "https://other-site.com" is not a subdomain of siteUrl "https://example.com". Allowed origins must be the same hostname as siteUrl or a subdomain of it.

L’endroit où l’erreur apparaît dépend de l’endroit où les valeurs sont déclarées :

  • Au démarrage d’Astro, lorsque config.allowedOrigins et config.siteUrl proviennent tous deux de astro.config.mjs — les fautes de frappe dans le code font échouer le build.
  • À la première vérification de passkey, lorsque l’une des valeurs provient de EMDASH_ALLOWED_ORIGINS ou de EMDASH_SITE_URL — les incohérences d’environnement se manifestent par des erreurs 500 à la première tentative de vérification.

Configuration d’un proxy inverse

Astro ne répercute X-Forwarded-* que lorsque l’hôte public est autorisé. Configurez security.allowedDomains pour le nom d’hôte (et les schémas) auxquels vos utilisateurs accèdent. Dans astro dev, ajoutez les vite.server.allowedHosts correspondants pour que Vite accepte l’en-tête Host du proxy.

Corrigez d’abord allowedDomains (et les en-têtes transférés) ; utilisez siteUrl lorsque l’URL reconstruite diverge toujours de l’origine du navigateur (typique lorsque le TLS est terminé en amont et que la requête vers l’origine reste en http://).

Avec du TLS en amont, lier le serveur de développement au loopback (astro dev --host 127.0.0.1) suffit souvent : le proxy se connecte en local tandis que siteUrl correspond à l’origine HTTPS publique.

Si votre proxy écrit un en-tête contenant l’IP du client, définissez trustedProxyHeaders pour que les limites de débit d’EmDash puissent utiliser la vraie IP du client. Sans IP client de confiance, les limites de débit d’authentification sont ignorées et toutes les soumissions publiques de commentaires partagent un seul compartiment de limite de débit (20 commentaires par 10 minutes pour l’ensemble des visiteurs).

La configuration suivante définit ensemble allowedDomains, vite.server.allowedHosts et siteUrl pour un déploiement derrière un proxy inverse :

import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
	security: {
		allowedDomains: [
			{ hostname: "cms.example.com", protocol: "https" },
			{ hostname: "cms.example.com", protocol: "http" },
		],
	},
	vite: {
		server: {
			allowedHosts: ["cms.example.com"],
		},
	},
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data.db" }),
			storage: local({
				directory: "./uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
			siteUrl: "https://cms.example.com",
		}),
	],
});

trustedProxyHeaders

Facultative. En-têtes auxquels faire confiance pour déterminer l’IP du client lorsque le site s’exécute derrière un proxy inverse que vous contrôlez. Utilisés par les limites de débit d’authentification (lien magique, inscription, passkey, flux d’appareil OAuth, enregistrement de client OAuth) et par le point de terminaison public des commentaires.

Sur Cloudflare, l’objet cf attaché à la requête est utilisé automatiquement : vous n’avez normalement pas besoin de le définir. Pour les déploiements auto-hébergés derrière nginx, Caddy, Traefik, Fly, Railway ou équivalent, définissez ici l’en-tête que votre proxy écrit afin que les limites de débit puissent compter les requêtes par IP client réelle.

L’exemple suivant fait confiance à l’en-tête x-real-ip défini par nginx, Caddy ou Traefik :

emdash({
	database: sqlite({ url: "file:./data.db" }),
	trustedProxyHeaders: ["x-real-ip"],
});

Les en-têtes sont essayés dans l’ordre. Les valeurs correspondant à *-forwarded-for sont analysées comme des listes séparées par des virgules et la première entrée est utilisée. L’exemple suivant privilégie l’en-tête de Fly.io et se replie sur x-forwarded-for :

emdash({
	trustedProxyHeaders: ["fly-client-ip", "x-forwarded-for"],
});

Lorsqu’elle n’est pas définie dans la configuration, EmDash lit la variable d’environnement EMDASH_TRUSTED_PROXY_HEADERS (séparée par des virgules). Un tableau vide explicite dans la configuration remplace la variable d’environnement.

maxUploadSize

Facultative. Taille maximale autorisée, en octets, pour le téléversement d’un fichier média. S’applique aux téléversements multipart directs comme aux téléversements par URL signée. La valeur par défaut est 52_428_800 (50 Mo). L’exemple suivant relève la limite à 100 Mo :

emdash({
	database: sqlite({ url: "file:./data.db" }),
	storage: local({
		directory: "./uploads",
		baseUrl: "/_emdash/api/media/file",
	}),
	maxUploadSize: 100 * 1024 * 1024, // 100 MB
});
ValeurDescription
number (octets)Doit être un entier fini positif
omisePar défaut, 50 Mo

Les téléversements qui dépassent la limite configurée sont rejetés avec une réponse 413 Payload Too Large sur le chemin de téléversement direct, ou 400 Validation Error sur le chemin par URL signée.

admin

Facultative. Remplace l’image de marque d’EmDash dans l’interface d’administration. Ces valeurs ne modifient ni le titre, ni le logo, ni la favicon du site public.

emdash({
	admin: {
		logo: "/images/agency-logo.webp",
		siteName: "Agency CMS",
		footerLabel: "AgencyX",
		favicon: "/favicon.ico",
	},
});
OptionTypeDescription
logostringURL ou chemin du logo pour la page de connexion et la barre latérale
siteNamestringNom affiché dans l’en-tête de la barre latérale et dans le titre du navigateur
footerLabelstring | falseLibellé affiché à côté de la version dans la barre latérale. Par défaut "EmDash" ; false le masque
faviconstringURL ou chemin de la favicon pour les pages d’administration

updateCheck

Facultative. Contrôle l’avis de mise à jour du cœur dans le tableau de bord d’administration. La valeur par défaut est true.

Lorsqu’elle est activée, EmDash interroge le registre npm public pour les versions publiées d’emdash — au plus une fois par jour, en différé après la réponse pour ne jamais ralentir une requête — et affiche une bannière que l’on peut fermer dans le tableau de bord d’administration lorsqu’une version plus récente est disponible. Fermer la bannière la masque pour cette version ; elle réapparaît lorsqu’une version plus récente devient disponible.

La bannière nomme la dernière version stable publique depuis au moins 24 heures ; une version est donc annoncée un jour après sa publication. Pour vous aligner sur une politique d’ancienneté des versions de votre gestionnaire de paquets, comme minimumReleaseAge de pnpm, définissez minimumReleaseAge sur une chaîne de durée ("48h", "7d") ou un nombre de secondes. Avec "7d", la bannière propose la dernière version âgée d’au moins une semaine :

emdash({
	updateCheck: { minimumReleaseAge: "7d" },
})

La vérification est un simple GET vers https://registry.npmjs.org/emdash et ne transmet aucune donnée du site. Les déploiements sans accès Internet sortant n’affichent tout simplement jamais la bannière. Définissez l’option sur false pour désactiver entièrement la vérification :

emdash({
	updateCheck: false,
})

La bannière est purement informative — mettre à jour EmDash revient à relever la version du paquet emdash dans votre projet et à redéployer, ce que l’administration ne peut pas (et ne devrait pas) déclencher.

toolbar

Facultative. Contrôle la façon dont la barre d’outils de l’éditeur (la pastille flottante sur les pages publiques) est fournie. La valeur par défaut est "server".

ValeurComportement
"server" (par défaut)La barre d’outils est injectée côté serveur dans chaque réponse HTML rendue pour un éditeur authentifié.
"client"Le HTML public est identique pour chaque visiteur. Un minuscule script d’amorçage affiche une pastille « Edit » dans les navigateurs qui se sont connectés à l’administration ; un clic dessus vérifie la session et recharge la page avec un paramètre de requête _edit, toujours rendue à neuf (jamais mise en cache) avec la barre d’outils complète.
falseNe rend jamais la barre d’outils ni le script d’amorçage.
emdash({
	toolbar: "client",
})

Utilisez "client" lorsque votre HTML public est servi via un cache partagé (Cloudflare Cache Everything / Workers Cache, Fastly, Varnish, …). Avec l’injection côté serveur, un éditeur qui parcourt le site public reçoit la variante anonyme en cache — sans la barre d’outils — dès qu’un visiteur anonyme a amorcé le cache en premier ; la barre d’outils apparaît et disparaît donc selon l’état du cache. En mode client, rien de propre à la session n’est injecté dans le HTML partageable : le cache reste pleinement efficace et la barre d’outils est fiable.

Remarques sur le mode "client" :

  • Les visiteurs déconnectés qui ouvrent une URL ?_edit partagée sont redirigés vers l’URL canonique, de sorte que le paramètre ne peut ni divulguer des brouillons ni amorcer des entrées de cache supplémentaires avec le contenu de la page.
  • Le signal « connecté » est un indicateur localStorage non secret défini par l’administration ; la pastille vérifie la vraie session avant d’entrer dans la vue d’édition.
  • L’amorçage est un petit <script> en ligne. Si votre site envoie un Content-Security-Policy strict sans 'unsafe-inline', ajoutez-y un hachage — il en va de même pour la barre d’outils injectée côté serveur.
  • EmDash n’injecte rien de propre à la session — mais si vos propres modèles se ramifient selon Astro.locals.user (p. ex. un lien de navigation « Admin » pour les utilisateurs connectés), cette variation reste dans votre HTML et fragmente toujours le cache.

Quel que soit le mode, la barre d’outils peut être masquée dans le navigateur avec son bouton × (par navigateur, jusqu’à la prochaine ouverture de l’administration par un éditeur). Les réponses d’aperçu et de mode édition sont toujours rendues côté serveur avec Cache-Control: private, no-store.

Adaptateurs de base de données

Importez les adaptateurs depuis emdash/db :

import { sqlite, libsql, postgres } from "emdash/db";

sqlite(config)

Base de données SQLite utilisant le pilote de base de données intégré de Node.js. L’exemple suivant se connecte à un fichier local :

OptionTypeDescription
urlstringChemin de fichier avec le préfixe file:
sqlite({ url: "file:./data.db" });

libsql(config)

Base de données libSQL. L’exemple suivant se connecte à une base de données libSQL distante :

OptionTypeDescription
urlstringURL de la base de données
authTokenstringJeton d’authentification à l’exécution (facultatif pour les fichiers locaux)
migrationAuthTokenEnvstringNom de la variable du jeton de migration (par défaut TURSO_AUTH_TOKEN)
libsql({
	url: process.env.LIBSQL_DATABASE_URL,
	authToken: process.env.LIBSQL_AUTH_TOKEN,
});

postgres(config)

Base de données PostgreSQL avec pool de connexions.

OptionTypeDescription
connectionStringstringURL de connexion PostgreSQL
hoststringHôte de la base de données
portnumberPort de la base de données
databasestringNom de la base de données
userstringUtilisateur de la base de données
passwordstringMot de passe de la base de données
sslbooleanActive SSL
pool.minnumberTaille minimale du pool (par défaut : 0)
pool.maxnumberTaille maximale du pool (par défaut : 10)
pool.connectionTimeoutMillisnumberAttente maximale de connexion (défaut de pg : 0, sans délai d’expiration)
pool.idleTimeoutMillisnumberDurée de vie d’un client inactif (défaut de pg : 10 000 ms)
migrationConnectionStringEnvstringNom de la variable de la chaîne de connexion de migration (par défaut DATABASE_URL)

L’exemple suivant se connecte avec une chaîne de connexion :

postgres({ connectionString: process.env.DATABASE_URL });

d1(config)

Base de données Cloudflare D1. À importer depuis @emdash-cms/cloudflare.

OptionTypePar défautDescription
bindingstring—Nom du binding D1 provenant de wrangler.jsonc
sessionstring"disabled"Mode de réplication en lecture : "disabled", "auto" ou "primary-first"
bookmarkCookiestring"__em_d1_bookmark"Nom du cookie pour les signets de session
coalescebooleanfalseRegroupe les lectures concurrentes dans le même tour de la boucle d’événements ; nécessite un mode de session autre que "disabled"

L’exemple suivant montre un binding de base et un binding avec réplicas de lecture activés :

// Basic
d1({ binding: "DB" });

// With read replicas
d1({ binding: "DB", session: "auto" });

Lorsque session vaut "auto" ou "primary-first", EmDash utilise l’API Sessions de D1 pour diriger les requêtes de lecture vers des réplicas proches. Les utilisateurs authentifiés bénéficient d’une cohérence de lecture de leurs propres écritures fondée sur des signets. Consultez Options de base de données — Réplicas de lecture pour plus de détails.

hyperdrive(config?)

PostgreSQL via un binding Cloudflare Hyperdrive. Importez cet adaptateur depuis @emdash-cms/cloudflare.

OptionTypePar défautDescription
bindingstring"HYPERDRIVE"Binding Hyperdrive principal avec le cache de requêtes désactivé
cachedBindingstring—Second binding facultatif, avec cache activé, pour les lectures publiques anonymes
preferUncachedAfterWriteMsnumber60_000Durée pendant laquelle les lectures publiques utilisent le binding principal après une écriture de contenu lorsque cachedBinding est défini
migrationConnectionStringEnvstringDérivé du binding principalVariable d’environnement contenant l’URL PostgreSQL directe utilisée par emdash migrate
maxnumber5Nombre maximal de connexions d’un isolat de Worker vers Hyperdrive

L’exemple suivant fait passer les requêtes authentifiées et les écritures par le binding sans cache, tandis que les lectures publiques anonymes peuvent utiliser le binding avec cache :

hyperdrive({
	binding: "HYPERDRIVE",
	cachedBinding: "HYPERDRIVE_CACHED",
	preferUncachedAfterWriteMs: 60_000,
});

Les deux bindings doivent pointer vers la même base de données. Installez pg en version 8.16.3 ou ultérieure, activez le drapeau de compatibilité nodejs_compat et configurez une URL de base de données directe pour les migrations de déploiement. Consultez Options de base de données : Hyperdrive pour la configuration complète du Worker et des migrations.

durableObjects(config)

Stocke le CMS dans un seul Durable Object adossé à SQLite. Importez cet adaptateur depuis @emdash-cms/cloudflare.

OptionTypePar défautDescription
bindingstringobligatoireBinding de l’espace de noms Durable Object pour la classe EmDashDB
namestring"emdash"Nom de l’objet singleton ; ne le modifiez que pour isoler plusieurs bases de données derrière un même binding
sessionstring"disabled""auto" oriente les lectures anonymes vers des réplicas et les écritures vers le primaire
bookmarkCookiestring"__em_do_bookmark"Cookie utilisé pour la cohérence de lecture de ses propres écritures en mode "auto"
durableObjects({ binding: "DB_DO", session: "auto" });

L’acheminement vers les réplicas nécessite les drapeaux de compatibilité experimental et replica_routing, ainsi que les entrées de classe Durable Object et de migration dans wrangler.jsonc.

previewDatabase(config)

Crée une base de données d’instantané isolée par session d’aperçu dans un Durable Object. La seule option est le nom binding, obligatoire :

previewDatabase({ binding: "PREVIEW_DB" });

Cet adaptateur est destiné à l’infrastructure d’aperçu, pas à la base de données principale d’un site de production.

playgroundDatabase(config)

Crée une base de données accessible en écriture et alimentée par un seed pour chaque session de playground dans un Durable Object. Associez-le à l’option d’intégration playground :

playgroundDatabase({ binding: "PLAYGROUND_DB" });

Le binding obligatoire identifie l’espace de noms Durable Object du playground. Utilisez cet adaptateur uniquement pour des sites de démonstration jetables.

Adaptateurs de stockage

Importez local et s3 depuis emdash/astro. L’adaptateur r2 s’importe depuis @emdash-cms/cloudflare :

import emdash, { local, s3 } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";

local(config)

Stockage sur le système de fichiers local. L’exemple suivant sert les téléversements depuis un répertoire local :

OptionTypeDescription
directorystringChemin du répertoire
baseUrlstringURL de base pour servir les fichiers
local({
	directory: "./uploads",
	baseUrl: "/_emdash/api/media/file",
});

r2(config)

Binding Cloudflare R2. L’exemple suivant utilise un binding R2 avec une URL publique :

OptionTypeDescription
bindingstringNom du binding R2
publicUrlstringURL publique facultative
r2({
	binding: "MEDIA",
	publicUrl: "https://pub-xxxx.r2.dev",
});

s3(config?)

Stockage compatible S3. Tous les champs de configuration sont facultatifs : tout champ omis de s3({...}) est résolu à partir de la variable d’environnement S3_* correspondante au démarrage du processus Node. Les valeurs explicites sont toujours prioritaires.

Une fois les valeurs de configuration et d’environnement fusionnées, endpoint et bucket sont obligatoires. Si l’un des identifiants est défini, accessKeyId et secretAccessKey sont tous deux obligatoires. Les valeurs manquantes font échouer le démarrage avec le code d’erreur MISSING_S3_CONFIG.

Prérequis : installez @aws-sdk/client-s3 et @aws-sdk/s3-request-presigner dans votre projet. Le cœur d’EmDash n’embarque pas le SDK AWS. Consultez Options de stockage : stockage compatible S3 pour plus de détails.

OptionTypeDescription
endpointstringURL du point de terminaison S3 (S3_ENDPOINT)
bucketstringNom du bucket (S3_BUCKET)
accessKeyIdstringClé d’accès (S3_ACCESS_KEY_ID)
secretAccessKeystringClé secrète (S3_SECRET_ACCESS_KEY)
regionstringRégion, par défaut "auto" (S3_REGION)
publicUrlstringURL CDN facultative (S3_PUBLIC_URL)

Les exemples suivants résolvent tous les champs depuis l’environnement, combinent configuration et environnement, ou transmettent chaque champ explicitement :

// All fields from S3_* environment variables (Node container deployments)
s3()

// Mix: CDN from config, rest from environment
s3({ publicUrl: "https://cdn.example.com" })

// All explicit
s3({
	endpoint: "https://xxx.r2.cloudflarestorage.com",
	bucket: "media",
	accessKeyId: process.env.R2_ACCESS_KEY_ID,
	secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
	publicUrl: "https://cdn.example.com",
})

La résolution des variables d’environnement à l’exécution est une fonctionnalité propre à Node. Sur Cloudflare Workers, les secrets et les variables sont exposés par le paramètre env du gestionnaire fetch, et non par process.env ; les variables d’environnement S3_* ne sont donc pas prises en compte. Les déploiements Workers doivent soit utiliser l’adaptateur r2(config), soit transmettre des valeurs explicites à s3({...}). Consultez Options de stockage pour plus de détails.

Adaptateurs de cache d’objets

Transmettez l’un d’eux à l’option objectCache.

kvCache(config)

Backend Cloudflare KV, partagé entre tous les isolats. À importer depuis @emdash-cms/cloudflare.

kvCache({
	binding: "CACHE", // KV binding name (required)
	defaultTtl: 3600, // entry TTL in seconds (optional, KV minimum 60)
	revalidate: 1000, // cross-isolate staleness window in ms (optional)
	timeout: 2000, // per-op timeout in ms before a miss (optional, 0 disables)
	keyPrefix: "em", // cache key prefix (optional)
})

memoryCache(config?)

Backend en processus pour Node.js et le développement. À importer depuis emdash/astro.

memoryCache({
	defaultTtl: 3600, // entry TTL in seconds (optional)
	revalidate: 1000, // staleness window in ms (optional)
	maxEntries: 1000, // max cached keys before eviction (optional)
	keyPrefix: "em", // cache key prefix (optional)
})

Consultez Cache d’objets pour la configuration et le comportement.

Adaptateurs d’authentification et de sandbox

Ces adaptateurs renvoient des valeurs pour les options d’intégration auth et sandboxRunner.

access(config)

Remplace la connexion par passkey intégrée par l’authentification Cloudflare Access. Importez-le depuis @emdash-cms/cloudflare et transmettez le résultat à auth :

import { access } from "@emdash-cms/cloudflare";

emdash({
	auth: access({
		teamDomain: "myteam.cloudflareaccess.com",
		audienceEnvVar: "CF_ACCESS_AUDIENCE",
	}),
});

teamDomain est obligatoire. L’adaptateur peut lire l’audience de l’application dans audience ou dans la variable désignée par audienceEnvVar ; il accepte aussi autoProvision, defaultRole, syncRoles et roleMapping. L’option auth documente leurs valeurs par défaut et le comportement des rôles.

sandbox()

Sélectionne Cloudflare Worker Loader comme exécuteur du sandbox de plugins. Importez-le depuis @emdash-cms/cloudflare et transmettez sa valeur de retour à sandboxRunner :

import { sandbox } from "@emdash-cms/cloudflare";

emdash({
	sandboxRunner: sandbox(),
});

Le site a aussi besoin d’un binding Worker Loader et du point d’entrée du pont de plugins. Consultez Sandbox des plugins : Cloudflare Workers pour ces paramètres de déploiement.

Adaptateurs de fournisseurs de médias

Transmettez des descripteurs de fournisseurs de médias à mediaProviders. Les deux fournisseurs Cloudflare intégrés s’importent depuis @emdash-cms/cloudflare.

Chaque option *EnvVar ci-dessous nomme une variable d’environnement. Le fournisseur la lit dans cet ordre : un binding Cloudflare Workers portant ce nom, puis process.env sur l’adaptateur Node. L’option directe correspondante (accountId, accountHash, apiToken) est toujours prioritaire sur les deux.

cloudflareImages(config)

Ajoute Cloudflare Images pour parcourir, téléverser, supprimer et diffuser des ressources d’image.

OptionTypePar défautDescription
accountIdstringDepuis CF_ACCOUNT_IDIdentifiant du compte Cloudflare
accountIdEnvVarstring"CF_ACCOUNT_ID"Variable utilisée lorsque accountId est omis
accountHashstringDepuis CF_IMAGES_ACCOUNT_HASHHachage du compte utilisé dans les URL de diffusion
accountHashEnvVarstring"CF_IMAGES_ACCOUNT_HASH"Variable utilisée lorsque accountHash est omis
apiTokenstringDepuis CF_IMAGES_TOKENJeton avec les permissions de lecture et de modification de Cloudflare Images
apiTokenEnvVarstring"CF_IMAGES_TOKEN"Variable utilisée lorsque apiToken est omis
deliveryDomainstringimagedelivery.netNom d’hôte personnalisé pour la diffusion des images
defaultVariantstring"public"Variante d’image utilisée pour l’affichage
mediaProviders: [cloudflareImages({ defaultVariant: "public" })];

cloudflareStream(config)

Ajoute Cloudflare Stream pour parcourir, rechercher, téléverser, supprimer et lire des ressources vidéo.

OptionTypePar défautDescription
accountIdstringDepuis CF_ACCOUNT_IDIdentifiant du compte Cloudflare
accountIdEnvVarstring"CF_ACCOUNT_ID"Variable utilisée lorsque accountId est omis
apiTokenstringDepuis CF_STREAM_TOKENJeton avec les permissions de lecture et de modification de Cloudflare Stream
apiTokenEnvVarstring"CF_STREAM_TOKEN"Variable utilisée lorsque apiToken est omis
customerSubdomainstringValeur par défaut de CloudflareNom d’hôte personnalisé pour la diffusion Stream
controlsbooleantrueAffiche les contrôles du lecteur
autoplaybooleanfalseDémarre la lecture automatiquement
loopbooleanfalseRépète la lecture
mutedbooleanfalse, ou true avec autoplayCoupe le son de la lecture
mediaProviders: [cloudflareStream({ controls: true })];

Consultez Médiathèque : fournisseurs de médias pour les bindings et composants de rendu requis.

Collections en direct

Configurez le chargeur EmDash dans src/live.config.ts :

import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";

export const collections = {
	_emdash: defineLiveCollection({
		loader: emdashLoader(),
	}),
};

Options du chargeur

La fonction emdashLoader() ne prend aucun argument :

emdashLoader();

Variables d’environnement

EmDash prend en compte ces variables d’environnement :

VariableDescription
EMDASH_SITE_URLOrigine publique visible par le navigateur (se replie sur SITE_URL)
EMDASH_ALLOWED_ORIGINSListe, séparée par des virgules, d’origines supplémentaires acceptées par la vérification des passkeys (déploiements multi-sous-domaines).
EMDASH_DATABASE_URLRemplace l’URL de la base de données
EMDASH_ENCRYPTION_KEYClé servant à chiffrer les secrets des plugins au repos. Fournie par l’opérateur : jamais stockée dans la base de données.
EMDASH_PREVIEW_SECRETRemplacement facultatif du secret HMAC de l’aperçu. Lorsqu’il n’est pas défini, une valeur stable par site est générée et stockée dans la base de données.
EMDASH_IP_SALTRemplacement facultatif du sel de hachage des adresses IP des commentateurs. Lorsqu’il n’est pas défini, une valeur stable par site est générée et stockée dans la base de données.
EMDASH_AUTH_SECRETObsolète. Utilisé comme source du sel d’IP s’il est défini ; les installations existantes doivent le conserver pour garder des hachages d’IP de commentateurs stables lors d’une mise à niveau.
EMDASH_TURNSTILE_SECRET_KEYClé secrète Cloudflare Turnstile (se replie sur TURNSTILE_SECRET_KEY). Lorsqu’elle est définie, les soumissions de commentaires doivent inclure un jeton Turnstile valide — associez-la à la prop turnstileSiteKey de <CommentForm>.
EMDASH_URLURL EmDash distante pour la synchronisation du schéma

Générez une clé de chiffrement avec la commande suivante :

npx emdash secrets generate

Configuration de package.json

Les modèles et les sites peuvent déclarer des métadonnées facultatives sous une clé emdash dans package.json :

{
	"emdash": {
		"label": "My Blog Template",
		"schema": ".emdash/schema.sql",
		"seed": ".emdash/seed.json"
	}
}
OptionDescription
labelNom du modèle à afficher
schemaSchéma SQL facultatif lu par emdash init
seedChemin du fichier JSON de seed

Configuration de TypeScript

Pendant le développement local, l’intégration Astro génère emdash-env.d.ts à la racine du projet et l’actualise après les modifications de schéma. Le fichier enrichit le module emdash ; les imports standard getEmDashCollection() et getEmDashEntry() déduisent donc les champs des collections locales sans alias de chemin.

La commande distincte emdash types récupère le schéma d’une instance locale ou distante en cours d’exécution et écrit .emdash/types.ts par défaut. N’ajoutez un alias que si le code de l’application importe directement cette sortie autonome :

{
	"compilerOptions": {
		"paths": {
			"@emdash-cms/types": ["./.emdash/types.ts"]
		}
	}
}

Générez les types autonomes du schéma distant avec la commande suivante :

npx emdash types