Prisma en Astro
Astro puede consultar Prisma desde páginas de servidor, endpoints y Actions. La consulta ocurre donde se ejecuta esa ruta: durante el build si se prerenderiza, o en cada petición si se renderiza bajo demanda.
Requisitos
Sección titulada «Requisitos»Completa Prisma 7 con PostgreSQL: esquema, migraciones, cliente src/lib/prisma.ts y prueba de lectura/escritura. Esta integración usa un servidor Node y el mismo esquema User/Post.
Para atender peticiones en ejecución necesitas un adapter. En un proyecto Astro existente:
pnpm exec astro add nodeComprueba que el adapter quede configurado y elige output: "server" si la mayoría de las rutas son dinámicas. También puedes conservar salida estática y marcar las rutas necesarias con prerender = false.
Implementación: endpoint de lectura
Sección titulada «Implementación: endpoint de lectura»import type { APIRoute } from "astro"import { prisma } from "../../lib/prisma"
export const prerender = false
export const GET: APIRoute = async () => { try { const posts = await prisma.post.findMany({ where: { published: true }, orderBy: [{ createdAt: "desc" }, { id: "desc" }], take: 20, select: { id: true, title: true } }) return Response.json(posts) } catch { return Response.json({ error: "No se pudieron cargar los posts" }, { status: 500 }) }}La respuesta pública incluye solo posts publicados y dos campos. Limitar filas evita devolver toda la tabla, pero no implementa navegación entre páginas; añade paginación cuando el listado la necesite.
Implementación: Action autenticada
Sección titulada «Implementación: Action autenticada»Esta parte requiere autenticación en Astro: middleware que verifica la sesión, App.Locals tipado y locals.user.id correspondiente a un User persistido. No basta con aceptar un identificador enviado por el navegador.
Crea también el servicio src/lib/posts.ts de la guía compartida, que valida el título y aplica el límite con una transacción serializable.
import { ActionError, defineAction } from "astro:actions"import { z } from "astro/zod"import { crearPostConLimite } from "../lib/posts"
export const posts = { crear: defineAction({ accept: "form", input: z.object({ title: z.string().trim().min(1).max(200) }), handler: async (input, context) => { const user = context.locals.user if (!user) throw new ActionError({ code: "UNAUTHORIZED", message: "Inicia sesión" })
const post = await crearPostConLimite(user.id, input.title) return { id: post.id, title: post.title } } })}Registra el grupo para que Astro lo exponga:
import { posts } from "./posts"
export const server = { posts }Si ya hay otras Actions, añade posts al objeto existente. No sobrescribas sus registros.
---import { actions } from "astro:actions"export const prerender = falseconst result = Astro.getActionResult(actions.posts.crear)---<form method="POST" action={actions.posts.crear}> <label for="title">Título</label> <input id="title" name="title" required maxlength="200" /> <button>Crear post</button></form>{result?.error && <p role="alert">No se pudo crear el post. Revisa el título y tu sesión.</p>}{result?.data && <p role="status">Creado: {result.data.title}</p>}La acción vuelve a verificar la identidad aunque la página ya la haya comprobado. El formulario ofrece feedback sin necesitar una isla React. Añade errores de negocio específicos y protección ante envíos duplicados si el flujo lo requiere.
Comprobación
Sección titulada «Comprobación»- Abre
/api/posts: devuelve[]en una base sin posts publicados. - Publica un post desde un entorno de desarrollo y repite la petición: aparece con
idytitle. - Envía el formulario sin sesión: la Action lo rechaza y la tabla no cambia.
- Con sesión válida, crea un título y comprueba su
authorIden la base. Un título vacío o mayor de 200 caracteres debe rechazarse también sin depender de HTML. - Detén la base: el endpoint responde 500 con un mensaje público; registra el diagnóstico detallado en el servidor.
Límites y recursos
Sección titulada «Límites y recursos»No importes Prisma desde scripts del navegador ni componentes hidratados. Esta receta corresponde a Node; otro adapter puede requerir otro driver y otra estrategia de conexiones.
El CRUD, las relaciones, las migraciones y las transacciones están en la guía compartida, para que las tres integraciones usen el mismo contrato.