npm.io
3.1.2 • Published 2 weeks ago

ga-pubsub

Licence
Elastic-2.0
Version
3.1.2
Deps
0
Size
271 kB
Vulns
0
Weekly
0

GA-PubSub Core

A lightweight, zero-dependency, in-memory pub/sub event bus for browser TypeScript applications.

License: Elastic-2.0 TypeScript ESM

Website · Community & Support · PRO Pricing


What is GA-PubSub?

GA-PubSub is a publish/subscribe event bus for browser applications. Events remain in the current page's memory and are delivered only to subscribers attached to that in-memory bus instance.

The core package is available under the Elastic License 2.0 (ELv2). It does not provide backend execution, cross-process delivery, external transports, or commercial security features. PRO adds frontend and backend operation, HMAC signing, independent inbound/outbound rate limits, authorization, replay-attack prevention, multi-tenancy, and nine transport adapters.


Features (free, ELv2)

  • Pub / Sub — subscribe to exact event names or wildcard patterns (order.*, payments.**)
  • Priority ordering — subscribers run highest-priority first within the same event
  • subscribeOnce — auto-unsubscribes after the first delivery
  • Middleware pipeline — intercept, enrich, or abort events before they reach subscribers
  • Schema validation — register a validator per event name; invalid payloads are rejected
  • Request / Response (RPC) — bus.request() + bus.respond() with configurable timeout
  • Replay engine — late subscribers receive previously published events (ring-buffer, wildcard-aware)
  • TTL enforcement — expired local and replayed envelopes are dropped before subscriber delivery
  • Metrics — built-in counters for publishes, deliveries, failures, and p95 latency
  • Subscription limit — optional cap to prevent runaway listeners
  • Cancel in-flight requests — handle.cancel() rejects the response promise immediately
  • Zero dependencies — pure TypeScript, ships as ESM + CJS dual build

Installation

npm install ga-pubsub

Quick Start

import { EventBus } from 'ga-pubsub';

const bus = new EventBus({ namespace: 'my-app' });

// Subscribe
bus.subscribe('user.created', (envelope) => {
  console.log('New user:', envelope.payload);
});

// Publish
await bus.publish('user.created', { id: '42', name: 'Ajith' });

// Wildcard — matches user.created, user.updated, user.deleted …
bus.subscribe('user.*', (e) => console.log(e.event, e.payload));

// One-shot
bus.subscribeOnce('app.ready', () => console.log('ready!'));

Middleware

import { EventBus, loggingMiddleware, ttlGuardMiddleware } from 'ga-pubsub';

const bus = new EventBus();

// Built-in middleware
bus.use(loggingMiddleware({ level: 'debug' }));
bus.use(ttlGuardMiddleware());

// Custom middleware — enrich every envelope
bus.use(async (envelope, next) => {
  envelope.payload = { ...envelope.payload as object, enrichedAt: Date.now() };
  await next();
});

Schema Validation

bus.registerSchema('order.placed', {
  name: 'OrderSchema',
  validate: (payload) => {
    const p = payload as { orderId?: unknown; total?: unknown };
    if (typeof p.orderId !== 'string') return { valid: false, errors: [{ path: 'orderId', message: 'required string' }] };
    if (typeof p.total !== 'number')   return { valid: false, errors: [{ path: 'total',   message: 'required number' }] };
    return { valid: true };
  },
});

// Invalid payload → throws ValidationFailedError
await bus.publish('order.placed', { orderId: 123 });

Request / Response (RPC)

// Responder
bus.respond('math.add', (e) => {
  const { a, b } = e.payload as { a: number; b: number };
  return { result: a + b };
});

// Requester
const { response } = bus.request('math.add', { a: 3, b: 7 }, { timeoutMs: 2000 });
const { payload } = await response;
console.log(payload.result); // 10

Replay

const bus = new EventBus({ replay: { limit: 100, replayWildcards: true, maxEventTypes: 1000 } });

await bus.publish('app.started', { version: '2.0' });

// Late subscriber still receives the event
bus.subscribe('app.*', (e) => {
  console.log('replayed:', e.event);
});

API Reference

Method Description
bus.publish(event, payload, opts?) Publish an event; runs middleware then notifies subscribers
bus.subscribe(pattern, handler, opts?) Subscribe; returns { unsubscribe() }
bus.subscribeOnce(pattern, handler, opts?) Subscribe for one delivery only
bus.use(middleware) Add a middleware function to the pipeline
bus.registerSchema(event, validator) Register a payload validator
bus.request(event, payload, opts?) Send an RPC request; returns { response, cancel }
bus.respond(event, handler) Register an RPC responder
bus.getMetrics() Return current metrics snapshot
bus.destroy() Tear down all subscriptions and clear replay history

Error Classes

Class Code When thrown
GAPubSubError base Base class for all errors
ValidationFailedError VALIDATION_FAILED Schema check fails
RequestTimeoutError REQUEST_TIMEOUT No responder within timeoutMs
SubscriptionLimitError SUBSCRIPTION_LIMIT maxSubscriptions reached
MiddlewareAbortError MIDDLEWARE_ABORT Middleware throws to stop delivery

PRO Edition

The free core is intentionally browser-only and in-memory. For licensed frontend/backend operation, security, and external transports, see PRO pricing:

Feature Core PRO
Browser in-memory pub/sub, wildcards, priority
Backend runtime support —
Middleware, schema validation
Replay engine, RPC, metrics
HMAC envelope signing —
Rate limiting (token bucket) —
Authorization (bus.authorize) —
Replay-attack prevention —
Payload size enforcement —
Multi-tenant namespace registry —
Scoped bus (auto-prefix) —
9 adapters (HTTP, WebSocket, SSE, Socket.IO, BroadcastChannel, Redis, Kafka, NATS, RabbitMQ) —
Runtime license key validation —

→ View PRO pricing & details → PRO customer support


Contributing & Community

Questions, ideas, and bug reports are welcome.

→ Join the community

If you find a bug, open an issue on GitHub. For security disclosures, contact the author directly through the community page.


Copy-paste browser example

The published package includes examples/usage.ts. It covers typed publish/subscribe, structural wildcards, priority, one-time subscriptions, middleware, schema validation, replay, TTL, request/response, telemetry, metrics, and cleanup.

npm create vite@latest ga-pubsub-training -- --template vanilla-ts
cd ga-pubsub-training
npm install
npm install ga-pubsub@3.1.0
npm run dev

Copy the package example into the Vite application's src/usage.ts, import it from src/main.ts, and open the local URL printed by Vite. Core does not require a license or broker; all events remain inside the browser page's memory.


License

Elastic License 2.0 (ELv2) — 2026 Ajithraj G

Keywords