Ir al contenido

CLI

Cuatro comandos, todos bajo el prefijo db:, que cubren el ciclo entero: de tu cms.config.ts a las tablas en D1, y de vuelta si te arrepientes.

Ventana de terminal
pnpm cms --help
Usage: cms [options] [command]
Genera el schema, los tipos y las migraciones de Kevin CMS
Options:
-h, --help Muestra esta ayuda
Commands:
db:generate [options] Escribe .cms/ desde cms.config.ts y avisa si hay deriva
db:migrate [options] Ejecuta db:generate y después drizzle-kit generate
db:apply [options] Aplica las migraciones pendientes a D1, en local salvo
--remote
db:pop [options] Borra la última migración generada

db:generate lleva el prefijo aunque no toque la base de datos: un solo grupo se lee mejor que un grupo más una excepción suelta.

Lee tu configuración y escribe .cms/schema.ts y .cms/types.d.ts.

Usage: cms db:generate [options]
Escribe .cms/ desde cms.config.ts y avisa si hay deriva
Options:
--config <ruta> Ruta al cms.config.ts, en vez de buscarlo en el directorio
actual
--watch Regenera cada vez que cambia el config
--check Convierte la deriva en un fallo y sale con código 1
-h, --help Muestra esta ayuda

Una ejecución normal:

✔ Cargando config
✔ Emitiendo .cms/
3 colecciones desde /mi-sitio/cms.config.ts
/mi-sitio/.cms/schema.ts
/mi-sitio/.cms/types.d.ts

Se queda escuchando y regenera cada vez que guardas el config. Útil si trabajas sin astro dev; con él no hace falta, porque la integración ya lo vigila.

No genera migraciones. Nunca.

Para integración continua. Igual que sin flag, pero si hay deriva sale con código 1 en vez de limitarse a avisar:

El schema ha cambiado desde la última migración:
+ posts.views (integer)
Ejecuta `cms db:migrate` para generar la migración.

Compara contra los snapshot.json de migrations/, que están commiteados, así que funciona sobre un clon limpio. Sin ninguna migración todavía no hay nada que comparar y pasa.

Ventana de terminal
pnpm cms db:generate --config ./config/cms.config.ts

Sin este flag busca en el directorio actual, en este orden: cms.config.ts, cms.config.js, cms.config.mjs. Si no encuentra ninguno, el error te dice los tres nombres que buscó y dónde miró.

.cms/ se escribe junto al config, no en el directorio desde el que lanzas el comando, para que los tipos queden donde su tsconfig.json los va a buscar.

Usage: cms db:migrate [options]
Ejecuta db:generate y después drizzle-kit generate
Options:
--config <ruta> Ruta al cms.config.ts, en vez de buscarlo en el directorio
actual
-h, --help Muestra esta ayuda

Regenera .cms/ y después llama a drizzle-kit, que escribe el SQL en migrations/. Si la migración va a ser destructiva —recrear una tabla, borrar una columna— pide confirmación antes.

Ahí se para. Aplicarla es db:apply, y es un comando aparte a propósito.

drizzle-kit lo instalas tú (pnpm add -D drizzle-kit). La CLI lo lanza como subproceso y te pasa su salida y su código tal cual, así que lo que ves es drizzle-kit hablando, sin intermediarios. Si no está instalado, el error te da el comando exacto en vez de un ENOENT.

Usage: cms db:apply [options]
Aplica las migraciones pendientes a D1, en local salvo --remote
Options:
--config <ruta> Ruta al cms.config.ts, en vez de buscarlo en el directorio
actual
--db <binding> Binding de la base D1, en vez del primero de wrangler.jsonc
--remote Aplica en producción en vez de en local
-h, --help Muestra esta ayuda
Ventana de terminal
pnpm cms db:apply # local
pnpm cms db:apply --remote # producción, tras confirmar
Aplicando en local sobre el binding DB
🚣 8 commands executed successfully.

Aplica lo que ya haya en migrations/. No genera nada: si encuentra deriva sin migrar, te lo dice antes de aplicar y sigue con lo que hay. Encadenar generar y aplicar en un solo comando es justo lo que no quieres que ocurra sin querer.

No hace falta que le digas cuál es. Lee tu wrangler.jsonc —o wrangler.json, o wrangler.toml— y usa el binding de la primera D1 que encuentre, que es el mismo nombre con el que tu código habla con ella (env.DB).

Con varias bases declaradas usa la primera y te avisa de cuál eligió. --db <binding> manda sobre todo eso:

Ventana de terminal
pnpm cms db:apply --db ANALYTICS
Usage: cms db:pop [options]
Borra la última migración generada
Options:
--config <ruta> Ruta al cms.config.ts, en vez de buscarlo en el directorio
actual
--db <binding> Binding de la base D1, en vez del primero de wrangler.jsonc
-h, --help Muestra esta ayuda

Deshace la última migración generada: borra su directorio con el migration.sql y el snapshot.json. Para el caso que pasa de verdad — generas, lees el SQL, no te convence, y lo quieres fuera antes de que lo vea nadie más.

Borrada la migración 20260730051522_smooth_exiles
La línea base de la deriva vuelve a la migración anterior.

Después de un pop, db:generate vuelve a avisarte de la deriva que esa migración cubría, porque la comparación pasa a hacerse contra la migración anterior. El ciclo queda como si nunca la hubieras generado.

Sólo mira la base local. Comprobar remoto metería una llamada de red en cada pop, y quien haya aplicado en producción lo que ahora quiere tirar tiene un problema más gordo que este aviso.

Sin ninguna migración que borrar, te lo dice y sale con 0.

Situación Salida Código
Sin argumentos Ayuda 0
-h, <comando> -h Ayuda 0
Comando desconocido El comando que no existe, y la ayuda 1
db:generate correcto, con o sin deriva Resumen de lo escrito 0
db:generate --check con deriva El listado de la deriva 1
Config no encontrado, o config inválido El error, con el motivo 1
db:migrate con drizzle-kit fallando Lo que imprima drizzle-kit El suyo
db:apply con wrangler fallando Lo que imprima wrangler El suyo
db:apply --remote cancelado en el prompt Aviso de cancelación 0
db:pop correcto, o sin nada que borrar Qué borró, o que no había nada 0
Binding no resoluble y sin --db El error, nombrando los ficheros que buscó 1

Pedir ayuda no es un error: sin argumentos sale con 0. Equivocarse de comando sí. Cancelar un prompt tampoco: dijiste que no y se te hizo caso.

Lo mínimo que merece la pena:

- run: pnpm cms db:generate --check

Falla la build si alguien cambió cms.config.ts y se olvidó de generar la migración, que es el despiste que más caro sale después.