soul v4.2.0

@jun/soul/admin

Admin

Panel de superadmin: usuarios, organizaciones y cambio de plan.

Que trae#

Un panel funcional para operar la plataforma, con el diseño de tu proyecto. No es un CRUD generico: son las dos pantallas que de verdad se usan a diario.

RutaQue hace
GET /usersLista usuarios con busqueda (?q=) y paginacion (?page=). Muestra cuantas organizaciones tiene cada uno.
GET /orgsLista organizaciones con busqueda, filtro por plan y cambio de plan en linea. Muestra miembros y el email del owner.
POST /orgs/:id/planCambia el plan. Responde 400 si el plan no esta en planNames.

Montarlo#

TypeScript
import { createAdmin } from "@jun/soul/admin";
import { PLANS } from "./config";

export const admin = createAdmin({
  errorPage,
  planNames: Object.keys(PLANS),
  layout: (c, opts) => shell({ title: opts.title, body: opts.content }),
});
TypeScript
const adminPanel = new Hono<{ Bindings: SoulEnv; Variables: AuthVariables }>();
adminPanel.use("*", auth.requireAdmin());
adminPanel.route("/", admin.routes);
app.route("/admin", adminPanel);

Opciones#

errorPage
Requerido.
planNames: string[]
Planes validos. Un plan fuera de esta lista se rechaza con 400.
layout: (c, {title, content, active}) => string
Envuelve el contenido en tu shell. active es "admin-users" o "admin-orgs", para marcar el item del menu.
basePath?: string
Por defecto "/admin". Usalo si lo montas en otra ruta.
pageSize?: number
Por defecto 25. Es LIMIT/OFFSET real, no se lee la tabla entera.

Rendimiento#

Los contadores por fila (organizaciones por usuario, miembros por organizacion, email del owner) salen de un JOIN agregado con GROUP BY / ROW_NUMBER, no de una subconsulta por fila. Con cien organizaciones en pantalla la diferencia entre las dos formas es abismal.

Extras#

El modulo tambien exporta un <select> buscable, util cuando la lista de opciones crece:

searchCombobox(opts)
Renderiza el combobox.
COMBOBOX_SCRIPT
El JS que lo acompaña. Inyectalo una vez en la pagina.