npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@customyai/web

v0.2.4

Published

Customy same-origin session handlers over the standard Request and Response: auth proxy, social sign-in, sign-out, impersonation callback, server session, route protection, cookie names and local session token verification. Node and edge; never in a brows

Readme

@customyai/web

Handlers de sesión same-origin de Customy sobre Request/Response estándar. La app expone /api/auth/* en su propio origen y lo reenvía a Customy Access: las cookies de sesión son de host (sin Domain), HttpOnly y nunca viajan a otro origen. Funciona en node y edge y en cualquier framework cuyas rutas reciban una Request y devuelvan una Response. Solo servidor: la condición browser del paquete no exporta nada.

npm install @customyai/web
  • customyAuthProxyHandlers(options): proxy de /api/auth/* (GET, POST, PUT, PATCH, DELETE). Adapta las Set-Cookie de Access al host (sin Domain, SameSite=Lax, Secure en https), rechaza peticiones cross-site que cambian estado (CSRF) y rutas fuera de allowedAuthPaths. enforceTenantScope fija la identidad a la configuración del servidor. Los errores de Access salen con el sobre { error: { code, message } } (más code/message planos durante la transición; normalizeErrors: false lo apaga).
  • customySocialRedirectHandlers, customySignOutHandlers, customyClearOAuthStateHandlers, handleCustomyAuth (callback de impersonación).
  • getServerSession(source, options) y verifyActionSession: sesión validada en Access. source es la Request, unas cabeceras (Headers o el headers() del framework: cualquier objeto con get), un almacén de cookies con getAll() o la cabecera Cookie. Las Set-Cookie de renovación vienen en setCookies: aplícalas con applySessionCookies(response, session).
  • customyMiddleware(options): protección de rutas; devuelve { action: "next", requestHeaders?, responseHeaders? } o { action: "respond", response }. La renovación viaja en responseHeaders; applySessionCookies(response, result) también la acepta.

Seguridad por defecto

  • Origen público: configura publicOrigin. Si está, manda él para CSRF, redirecciones y el callback social; las cabeceras reenviadas (x-forwarded-host…) solo cuentan con trustProxyHeaders: true. Detrás de varios proxies el último salto puede dar un host interno y, sin publicOrigin, se rechazarían logins legítimos.
  • CSRF (proxy, sign-out y limpieza de estado): una mutación sin Origin solo pasa si Sec-Fetch-Site es same-origin/none o Referer es del origen público; con Origin, debe ser exactamente el público; Sec-Fetch-Site: cross-site nunca. Un cliente de servidor que llame al proxy debe mandar Origin. csrfProtection: false lo apaga (no recomendado).
  • Destino tras el login social: el ?callbackURL= solo se usa si resuelve al origen público y pasa allowedCallbackPaths (ruta exacta y sus subrutas) e isCallbackAllowed(url); si no, defaultCallbackPath (o /).
  • Organización: el slug viaja en x-organization-slug y en la heredada x-organization-id; se lee cualquiera de las dos.
import { applySessionCookies, getServerSession } from "@customyai/web";

export async function GET(request: Request) {
  const session = await getServerSession(request, { accessUrl, publicOrigin, environmentId, publishableKey });
  return applySessionCookies(Response.json({ user: session?.user ?? null }), session);
}

Migrar desde @customyai/customy-access/nextjs

| Antes | Ahora | |---|---| | getServerSession(options) leía cookies() | getServerSession(await headers(), options) (o la Request, o await cookies()); en un Route Handler o Server Action, applySessionCookies(response, session) para renovar. El adaptador customy-access/nextjs sigue aplicándolas solo con cookies().set donde se puede. | | middleware que devolvía NextResponse | result.action === "respond" → result.response; si no, sigue y copia result.responseHeaders (las Set-Cookie de renovación) a tu respuesta. | | URL de Access y origen desde variables de entorno | accessUrl y publicOrigin explícitos (el SDK no adivina hosts). | | sin CSRF fuera del ámbito fijo | CSRF activo; los formularios propios deben mandar Origin (los navegadores lo hacen). | | callbackURL social de la query sin lista | allowedCallbackPaths / isCallbackAllowed y defaultCallbackPath. | | errores de Access en su formato | { error: { code, message } } (+ code/message planos). |

  • createEdgeClient({ publishableKey, authUrl }): verificación local del JWT de sesión con el JWKS de Access (rotación y caché de @customyai/server).
  • Nombres de cookie de Access y utilidades de Cookie/Set-Cookie.
import { customyAuthProxyHandlers } from "@customyai/web";

// Ruta /api/auth/[...path] de la app
export const { GET, POST, PUT, PATCH, DELETE } = customyAuthProxyHandlers({
  accessUrl: "https://access-api.customy.ai",
  publicOrigin: "https://app.example.com",
  publishableKey: "pk_live_...",
});