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

deploy-guard-telemetry

v0.1.0

Published

Agente de telemetría y control de despliegues: reporta instancias activas a un endpoint central y permite bloqueo remoto opcional. Funciona en Node.js y navegador.

Readme

deploy-guard

Agente ligero de telemetría y control de despliegues. Se integra en tu proyecto con una línea y reporta a un endpoint central (p. ej. miempresa360.com) cada vez que el proyecto arranca y mientras sigue vivo. Permite además bloqueo remoto opcional de instancias no autorizadas.

  • ✅ Funciona en backend (Node.js) y frontend (navegador) — autodetección.
  • ✅ Distingue cada señal con side: "backend" | "frontend".
  • ✅ Heartbeat periódico para saber qué instancias están activas ahora.
  • ✅ Identifica cada VPS con un machineId estable (sobrevive a reinicios y cambios de IP).
  • Nunca rompe ni frena tu app: todo es asíncrono y con fallo silencioso.
  • ✅ Cero dependencias en runtime (usa fetch nativo).

📄 El contrato completo de qué se envía y qué responde el servidor está en docs/TELEMETRIA.md.


Instalación

npm install deploy-guard-telemetry

Requiere Node.js >= 18 (por fetch nativo). En navegador funciona en cualquier bundler moderno (Vite, webpack, Next.js, etc.); el exports del paquete resuelve automáticamente la build correcta para cada entorno.


Uso rápido

import { initGuard } from "deploy-guard-telemetry";

initGuard({
  endpoint: "https://miempresa360.com/api/telemetry",
  projectId: "cliente-acme",
  apiKey: "TU_CLAVE",
});

Con eso ya envía un evento startup al arrancar y un heartbeat cada 15 minutos.


Ejemplos por entorno

Backend — Node.js / Express

// server.ts
import express from "express";
import { initGuard } from "deploy-guard-telemetry";

const guard = initGuard({
  endpoint: "https://miempresa360.com/api/telemetry",
  projectId: "cliente-acme",
  apiKey: process.env.GUARD_API_KEY,
  version: process.env.npm_package_version, // versión de tu app
  heartbeatMinutes: 15,
  onBlock: "warn",
});

const app = express();
app.get("/", (_req, res) => res.send("ok"));

const server = app.listen(3000);

// Apagado limpio: avisa al servidor central.
process.on("SIGTERM", async () => {
  await guard.stop();
  server.close();
});

→ Reporta con side: "backend", runtime: "node" y los datos del VPS (hostname, platform, arch, cpus, machineId estable).

Backend — NestJS

// main.ts
import { initGuard } from "deploy-guard-telemetry";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  initGuard({
    endpoint: "https://miempresa360.com/api/telemetry",
    projectId: "cliente-acme",
    apiKey: process.env.GUARD_API_KEY,
  });

  await app.listen(3000);
}
bootstrap();

Frontend — app de navegador (Vite / React / Vue / vanilla)

// main.ts (punto de entrada de tu app web)
import { initGuard } from "deploy-guard-telemetry";

initGuard({
  endpoint: "https://miempresa360.com/api/telemetry",
  projectId: "cliente-acme",
  apiKey: import.meta.env.VITE_GUARD_API_KEY,
  version: __APP_VERSION__,
});

→ Reporta con side: "frontend", runtime: "browser", usando el dominio como hostname y un id persistido en localStorage. Intenta un shutdown al cerrar la pestaña (best-effort).

Next.js (SSR + cliente)

Como Next corre en Node y en navegador, puedes inicializarlo en ambos lados. Si quieres marcar el render de servidor como frontend, usa el override side:

// instrumentación de servidor (p. ej. instrumentation.ts)
import { initGuard } from "deploy-guard-telemetry";

initGuard({
  endpoint: "https://miempresa360.com/api/telemetry",
  projectId: "cliente-acme",
  side: "frontend", // fuerza la clasificación aunque corra en Node
});

API

initGuard(config): GuardHandle

Arranca el agente. Devuelve un handle para controlar su ciclo de vida.

config

| Opción | Tipo | Por defecto | Descripción | |--------------------|----------------------------------------|----------------------------------|------------------------------------------------------------------------| | endpoint | string (requerido) | — | URL del endpoint receptor. | | projectId | string (requerido) | — | Identificador del proyecto/cliente. | | apiKey | string | — | Se envía como cabecera x-api-key. | | version | string | "unknown" | Versión de tu proyecto. | | env | string | NODE_ENV o "production" | Entorno lógico. | | side | "backend" \| "frontend" | autodetectado por runtime | Override de la clasificación backend/frontend. | | heartbeatMinutes | number | 15 | Minutos entre heartbeats. 0 desactiva el heartbeat. | | timeoutMs | number | 3000 | Timeout de cada request. | | onBlock | "warn" \| "throw" \| "callback" | "warn" | Qué hacer si el servidor responde block: true. | | onBlockCallback | (res) => void | — | Callback usado cuando onBlock === "callback". | | debug | boolean | false | Loguea la actividad interna del agente. |

GuardHandle

| Miembro | Tipo | Descripción | |------------------|-------------------------------------------|--------------------------------------------------------| | stop() | () => Promise<void> | Detiene el heartbeat y envía un shutdown. | | ping() | () => Promise<TelemetryResponse \| null>| Fuerza un heartbeat inmediato. | | lastResponse | TelemetryResponse \| null | Última respuesta del servidor. | | blocked | boolean | true si la última respuesta ordenó bloqueo. |


Bloqueo remoto (enforcement opcional)

Si el servidor responde { "ok": true, "block": true, "message": "..." }, la librería actúa según onBlock:

import { initGuard, DeployBlockedError } from "deploy-guard-telemetry";

try {
  const guard = initGuard({
    endpoint: "https://miempresa360.com/api/telemetry",
    projectId: "cliente-acme",
    onBlock: "throw", // lanza DeployBlockedError si el server bloquea
  });
} catch (err) {
  if (err instanceof DeployBlockedError) {
    console.error("Despliegue no autorizado:", err.message);
    process.exit(1);
  }
}

O con callback, para tu propia lógica:

initGuard({
  endpoint: "https://miempresa360.com/api/telemetry",
  projectId: "cliente-acme",
  onBlock: "callback",
  onBlockCallback: (res) => {
    // mostrar un aviso, deshabilitar funciones, etc.
    console.warn("Bloqueado:", res.message);
  },
});

⚠️ El bloqueo solo ocurre con una orden explícita del servidor. Un fallo de red o un timeout nunca bloquea, para no apagar apps legítimas si el endpoint está caído. Ten en cuenta que un cliente con acceso al código puede parchear la librería para ignorar el bloqueo; sirve contra despliegues no autorizados de buena fe, no contra un atacante decidido.


¿Qué envía exactamente?

Resumen del payload (detalle completo en docs/TELEMETRIA.md):

{
  "projectId": "cliente-acme",
  "event": "startup",            // startup | heartbeat | shutdown
  "instanceId": "uuid-por-arranque",
  "machineId": "hash-estable-del-vps",
  "version": "1.2.0",
  "env": "production",
  "runtime": "node",             // node | browser
  "side": "backend",             // backend | frontend
  "host": { "hostname": "...", "platform": "linux", "arch": "x64", "cpus": 4 },
  "sentAt": "2026-06-09T12:00:00.000Z"
}

La IP pública no la manda el cliente: la lees en el servidor desde X-Forwarded-For.


Desarrollo

npm install      # dependencias de build (tsup, typescript)
npm run build    # genera dist/ (ESM + CJS + tipos)
npm run typecheck
npm run dev      # build en watch

Licencia

MIT