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

@central-ticket/queue-sdk

v0.6.0

Published

SDK de cola virtual de CentralQ. Por defecto monta la UI de CentralQ (`<central-q>`) con la experiencia publicada en el dashboard, sin bloquear la admisión ni el polling.

Readme

CentralQ Queue SDK

SDK de cola virtual de CentralQ. Por defecto monta la UI de CentralQ (<central-q>) con la experiencia publicada en el dashboard, sin bloquear la admisión ni el polling.

UI de CentralQ o UI propia

La UI incluida se monta siempre, salvo que pases headless: true. La misma opción existe en CentralQ.init, createQueue, las sesiones por recurso (useQueue) y el runtime por URL (createCentralQRouteRuntime, useCentralQRuntime de React y Vue, y createCentralQRuntime de Svelte).

import { createCentralQRouteRuntime } from "@central-ticket/queue-sdk";

// UI de CentralQ (default)
const runtime = createCentralQRouteRuntime({ publishableKey: "ctq_pub_..." });

// UI propia: el SDK gestiona la cola y vos dibujás la espera
const headlessRuntime = createCentralQRouteRuntime({
  publishableKey: "ctq_pub_...",
  headless: true,
});
headlessRuntime.subscribe((state) => {
  if (state.shouldBlockNavigation) renderWaiting(state);
});

headless sólo cambia quién dibuja la espera: la admisión, la sesión y la verificación en el backend son las mismas.

Preview del builder

El subpath @central-ticket/queue-sdk/preview reutiliza exactamente la misma UI y los mismos estilos del runtime, pero no crea sesiones, códigos QR, listeners remotos ni solicitudes de engagement.

import {
  mountCentralQPreview,
  type CentralQPreviewModel,
} from "@central-ticket/queue-sdk/preview";

const model: CentralQPreviewModel = {
  config: {
    schemaVersion: 1,
    layout: "EDITORIAL",
    title: "Tu lugar está reservado",
    palette: {
      primary: "#173D35",
      background: "#F8F5EF",
      text: "#17231F",
      accent: "#E6B98A",
    },
  },
  scenario: "WAITING",
  viewport: "desktop",
};

const preview = mountCentralQPreview(container, model);
preview.update({ ...model, scenario: "QUEUE_PAUSED" });
preview.destroy();

Escenarios disponibles: LOADING, WAITING, QUEUE_PAUSED, PREOPENING, EXPIRED y ERROR. Los fixtures son deterministas: posición 128, 127 personas delante y ETA de 12–18 minutos.

Extensiones de experiencia

WaitingRoomExtensions admite snake y promoBanner. El banner conserva schemaVersion: 1, exige URLs HTTPS en payloads públicos y abre enlaces con noopener noreferrer. Los SDK anteriores ignoran esta extensión.

Secuencia de entrega

Publicar primero el SDK, fijar el dashboard a esa versión exacta y desplegar después el worker/dashboard compatible. Para esta entrega la secuencia es @central-ticket/[email protected] → dashboard 0.3.0 → worker/dashboard.

Admisión agnóstica y acceso conservado (0.5.0)

CentralQ administra presencia, admisión, posición, permisos y vencimientos. La aplicación conserva sus pantallas, formularios, operaciones y reglas para iniciar o suspender la admisión. El SDK no recibe estados de modal, checkout, carrito u orden. La confirmación autoritativa del consumo sigue siendo server-side.

Svelte

useQueue conserva su nombre y sus stores (status, token, position, ahead, expiresAt, waitingCount, pauseReason, error) y agrega configured e isProtected. A partir de 0.5 requiere Svelte 5. Un getter se observa mediante toStore, por lo que los cambios en evento, cliente, identidad y enabled se aplican durante la vida del componente. También admite un Readable de opciones o un objeto estático. Se destruye la sesión anterior al cambiar de recurso y se cancelan sus suscripciones al desmontar.

<script lang="ts">
  import { useQueue } from '@central-ticket/queue-sdk/svelte';
  import { get } from 'svelte/store';

  let { client, resourceId, enabled = true } = $props();
  const queue = useQueue(() => ({
    client,
    eventId: resourceId,
    enabled,
    headless: true
  }));
  const { status, token, position, error } = queue;

  async function runProtectedAction() {
    if (!(await queue.refresh())) return;
    const result = await callApplicationBackend(get(token));
    if (result.accessConsumed) queue.consume();
  }
</script>

El consumidor decide qué significa enabled: puede depender de la ruta, una operación en curso o cualquier condición propia. headless: true conserva la UI de la aplicación; al omitirlo, CentralQ monta su UI con la experiencia publicada.

| Operación | Efecto | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | enabled: false | Detiene solicitudes y polling sin consumir, liberar ni extender un permiso válido. Su vencimiento local permanece activo. | | enabled: true / resume() | Reanuda admisión y vuelve a comprobar el acceso; conserva un permiso todavía válido. | | refresh() | Revalida protección y acceso; devuelve false si la admisión está deshabilitada. | | consume() | Invalida el acceso local y avisa a las otras instancias del mismo scope. Detiene admisión hasta una reanudación explícita. No confirma consumo por HTTP. | | restart() / reset() | Abandona el intento anterior y solicita una nueva admisión normal. | | leave() | Abandona explícitamente el intento y libera una reserva preservada no utilizada. |

Motor independiente del framework

Para JavaScript u otros adaptadores, client.createQueueSession({ eventId }) expone start, subscribe, refresh, setEnabled, consume, restart, leave y destroy. client.notifyAccessConsumed(eventId) notifica consumo local desde otra parte de la aplicación. Estas operaciones no conocen el negocio del consumidor ni ejecutan su acción protegida.

Sin userId, el worker determina la identidad de navegador y el SDK registra presencia también mientras la protección está inactiva. Al activarse, obtiene un init mediante CAPTCHA/PoW cuando corresponde y reclama el acceso preservado. Con userId explícito, conserva esa identidad y la admisión ordinaria sin crear reservas para una identidad de navegador distinta. queueInitToken junto con autoInitToken: false permite credenciales emitidas por el backend integrador.

El polling de presencia usa intervalos de 9–11 segundos sin solapar solicitudes. La vuelta a la pestaña y refresh() revalidan el estado. El worker siempre emite los permisos y controla su vencimiento; el SDK no concede ni extiende acceso. Las credenciales y notificaciones se aíslan por URL, publishable key y recurso. Una aplicación puede proporcionar presenceToken para adoptar una credencial anterior: la lectura de sus claves de almacenamiento pertenece a su adaptador.

Bypass y recuperación

bypassCode se canjea después de la admisión habitual y adopta el token y vencimiento devueltos por el worker. No reclama un segundo turno ordinario. La limpieza de la reserva y el init no utilizados se reintenta sin volver a gastar el código. El permiso confirmado se guarda best-effort en sessionStorage, asociado al scope y a la identidad, para recuperarlo tras desmontar y volver a montar. Consumo, reinicio y vencimiento lo invalidan. Pausar y reanudar conserva el mismo permiso y su fecha de vencimiento.

Una respuesta perdida del canje después de gastar el código en el servidor sigue requiriendo idempotencia del endpoint. Un token local tampoco reemplaza la verificación server-side. El cliente HTTP avanzado conserva registerPresence, claimPreservedSession y releasePreservedSession, con QueueRequestError y status/reason tipados.

Migración desde 0.4

0.5 retira createEventSession, preparePurchase, setCheckoutOpen, markOrderCreated y notifyOrderCreated. Los consumidores Svelte conservan useQueue; las decisiones de negocio quedan en la aplicación. Los consumidores avanzados usan el motor genérico y las operaciones anteriores. Las versiones 0.4 publicadas siguen disponibles para aplicaciones todavía no migradas.

Las dependencias de producción deben apuntar a la versión publicada en npm, sin tarballs ni overrides locales. La adopción de datos de una integración previa se implementa en esa aplicación, no en el SDK.

Tiempo de espera

WAITING conserva los campos de ETA y agrega estimateSource?: "CONFIGURED" | "OBSERVED" | null. La UI de CentralQ usa Tiempo de espera estimado, respeta etaLabel personalizado y muestra rangos redondeados a minutos (o En breve para rangos de hasta 30 segundos). Cuando el worker no dispone de una referencia fiable, muestra Te avisaremos acá cuando sea tu turno. La UI se actualiza con el polling del worker y entre pestañas, sin un contador local independiente. Las estimaciones iniciales de configuración tienen confianza LOW; no representan flujo observado.

Validación de navegador de la espera, sus actualizaciones y el ingreso:

pnpm test:visual e2e/eta.spec.ts

URL rules and application resource IDs

Supply urls alongside eventId to resolve dashboard URL rules before admission or access verification. The application supplies equivalent URLs; the SDK does not infer routes or business identifiers. Matching URL rules take precedence; with no match, protection by eventId remains available. Conflicting waiting rooms, unavailable lookups and malformed responses fail closed. Inactive rooms still resolve so browser presence can be preserved.

Browser: useQueue(() => ({ client, eventId: resourceId, urls, enabled })) keeps the same lifecycle. Its eventId store contains the resolved queue alias; use that alias for local consumption outside the mounted session.

Backend: acquireAccess({ eventId: resourceId, urls: trustedUrls, token }) resolves with the secret key and returns a lease scoped to the queue alias. Construct URLs from trusted application configuration and database metadata, never request headers, a browser-provided queue alias or decoded unverified token claims. Keep resource authorization and transaction checks tied to the business resource ID.

Liberación por falta de conexión (0.5.2)

La sala configura activeInactivitySeconds desde el dashboard: 0 conserva el acceso hasta su vencimiento; 30..86400 habilita un plazo sin heartbeat. El SDK continúa comunicándose al cambiar de pestaña o minimizar; no envía leave al ocultarse o desmontarse. Cerrar o perder red interrumpe la comunicación y el worker recupera el lugar al cumplirse el plazo y ejecutar su ciclo de limpieza.

useQueue y createQueueSession revalidan el permiso activo al sincronizar, incluidos los accesos por código. La revalidación no extiende expiresAt. Si el worker ya lo revocó, el SDK descarta el token y obtiene admisión nueva mediante el flujo normal. Un fallo temporal de red no se interpreta como una revocación autoritativa. Los adaptadores basados en CentralQ también procesan el rechazo terminal del heartbeat. Las operaciones ya autorizadas conservan su lease.

Actualizar consumidores a 0.5.2 antes de habilitar esta política en salas que utilicen códigos bypass. No cambia el contrato HTTP del backend de operaciones.

Inicio de admisión (0.5.3)

La sesión reutiliza challengeRequired de presencia y la respuesta del primer join. Con un worker compatible, la admisión pública inicial hace cuatro solicitudes: presencia, init, claim y join. El controlador adopta el resultado sin repetir join ni abrir un stream de comunicación para un acceso ya admitido. Las posiciones en espera o pausa conservan polling, promoción y comunicación; los accesos admitidos conservan heartbeat y vencimiento.

CAPTCHA/PoW y recuperación de turnos preservados siguen vigentes. Si un worker anterior omite challengeRequired, se conserva la consulta de protección. La respuesta de admisión sólo se reutiliza al arrancar el controlador: una pestaña seguidora que toma liderazgo más tarde obtiene estado actualizado.

Núcleo server independiente del framework

Importá la entrada @central-ticket/queue-sdk/server en Hono, Express, SvelteKit u otro backend. No requiere Nest, DOM ni navegador.

import { createCentralQServer } from "@central-ticket/queue-sdk/server";

const centralq = createCentralQServer({ secretKey }); // reutilizar por servidor
const lease = await centralq.acquireAccess({ eventId: trustedResourceId, token });
try {
  // La aplicación confirma su operación durable e idempotente.
  const operation = await commitApplicationOperation();
  const completion = await lease.complete(operation.id);
  // Inspeccionar completion; si falla, conservar el recibo y reconciliar.
} finally {
  lease.dispose(); // sólo detiene renovación; no completa ni libera
}

validateQueueTokenServer sólo comprueba vigencia del turno. acquireAccess adquiere el lease de procesamiento y renueva mientras se ejecuta la operación; complete(stableId) consume el turno. release() sólo libera ese lease después de rollback/no operación confirmado, sin abandonar ni consumir el turno.

retryCompletion({ eventId, token, leaseId, completionId }) y retryRelease({ eventId, token, leaseId }) recuperan credenciales persistidas sin adquirir otro lease. Los retries en memoria no son un outbox ni una transacción entre CentralQ y la DB comercial. Ante resultado incierto, no liberar ni repetir la operación: reconciliar mediante su ID durable. Mantener las credenciales fuera del navegador y los logs. Los recursos no protegidos tienen finalización no-op.

La adquisición rechaza con CentralQAccessError: kind distingue denegación, red, timeout, configuración, protocolo y fallo upstream; upstreamStatus conserva el código HTTP cuando la respuesta de acceso está disponible. No existe fail-open implícito. onEvent permite observabilidad opcional sin credenciales; no hay logger por defecto. El adaptador Nest delega en este mismo núcleo y conserva su traducción HTTP. Ver el ejemplo Hono.

Ejemplos completos por framework

Next.js, Nuxt/Vue, SvelteKit y Hono distinguen validación simple y operación simulada con adquisición/finalización. Las interfaces browser gestionan el init y la espera mediante useQueue; después del consumo confirmado notifican el acceso consumido y detienen el flujo, sin utilizar leave como completion.

Son demos sin DB comercial: una respuesta incierta bloquea el reenvío en la página, pero no reemplaza idempotencia ni recibos durables. La app real conserva scope, payload y un ID comercial estable, confirma su transacción y reconcilia los resultados de completion. Las credenciales de recuperación quedan server-side.

Ambientes y hosts fijos

Todas las entradas browser/server y los adaptadores apuntan a uno de dos hosts fijos, elegido con environment ("production" por defecto):

  • production: https://queue.centralticket.com.ar
  • sandbox: https://sandbox-queue.centralticket.com.ar

No hay opción apiUrl, baseUrl, variable de entorno ni excepción de desarrollo para cambiar ese destino. Un valor inválido de environment lanza un TypeError antes de la red. Las URLs de recursos, redirects y orígenes autorizados siguen siendo datos de la integración.

CENTRALQ_API_URLS expone el mapa fijo, resolveCentralQApiUrl(environment) resuelve el host y CENTRALQ_DEFAULT_API_URL conserva su nombre histórico como alias de producción.

Migración del cliente HTTP avanzado: new QueueHttpClient(apiKey?, initToken?, environment?). Se retira el argumento antiguo de URL; API key e init token conservan sus headers. withInitToken(token) mantiene la API key y el ambiente. La propiedad apiUrl es de sólo lectura para identificar el scope de cache/presencia; no configura transporte.