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

@hangarx/node

v1.0.2

Published

HangarX SDK for Node.js and backend applications - AI-powered Growth OS with analytics, SEO intelligence, and workflow automation

Readme

@hangarx/node

npm version Bundle Size TypeScript

Server-Side Mission Control for Your Growth Analytics 🚀

Track server-side events, analyze backend flows, and optimize conversions with AI-powered insights.
Like having Jarvis in your backend—intelligent, reliable, and always on duty.

Quick StartAPI ReferenceExamplesSupport


⚡ 60-Second Takeoff

Install:

npm install @hangarx/node

Track:

import { HangarX } from '@hangarx/node'

const hangarx = new HangarX({ apiKey: 'proj_YOUR_KEY' })

// Track events
await hangarx.track('user-123', 'purchase_completed', {
  amount: 99.99,
  product: 'Premium Plan'
})

// Identify users
await hangarx.identify('user-123', {
  email: '[email protected]',
  plan: 'premium'
})

That's it. You're airborne. ✈️


🎯 Why HangarX Node?

| Feature | What You Get | |---------|-------------| | 12KB | Lightweight. Won't bloat your backend. | | Auto-Batching | Smart queueing. Efficient network usage. | | Retry Logic | Exponential backoff. Never lose events. | | TypeScript | Full type safety. Catch errors before runtime. | | Graceful Shutdown | Flushes events on SIGTERM/SIGINT. No data loss. | | Environment Config | Auto-loads from HANGARX_API_KEY. Zero config. |


📦 Installation

npm install @hangarx/node
# or
yarn add @hangarx/node
# or
pnpm add @hangarx/node

🚀 Flight Controls (API)

Track Events

await hangarx.track('user-123', 'event_name', {
  property: 'value'
})

Common server-side events:

  • user_signup - New user registered
  • purchase_completed - Purchase processed
  • subscription_created - Subscription started
  • api_request - API endpoint called
  • email_sent - Email delivered

Identify Users

await hangarx.identify('user-123', {
  email: '[email protected]',
  plan: 'premium',
  company: 'Acme Corp',
  created_at: new Date().toISOString()
})

Track Pages (Server-Side Rendering)

await hangarx.page('user-123', 'Home Page', {
  category: 'marketing',
  referrer: req.headers.referer
})

Track Conversions

await hangarx.conversion('user-123', 'purchase', 99.99, {
  product: 'Premium Plan',
  currency: 'USD',
  payment_method: 'stripe'
})

Reset Session

hangarx.reset()  // Clear session, start fresh

Manual Flush

await hangarx.flush()  // Send queued events immediately

Graceful Shutdown

await hangarx.shutdown()  // Flush and cleanup

🎨 Framework Integration

Express.js

import express from 'express'
import { HangarX } from '@hangarx/node'

const app = express()
const hangarx = new HangarX({ apiKey: process.env.HANGARX_API_KEY! })

// Track API requests
app.use((req, res, next) => {
  hangarx.track(req.user?.id || 'anonymous', 'api_request', {
    method: req.method,
    path: req.path,
    user_agent: req.headers['user-agent']
  })
  next()
})

// Track user signup
app.post('/api/signup', async (req, res) => {
  const user = await createUser(req.body)
  
  await hangarx.identify(user.id, {
    email: user.email,
    name: user.name
  })
  
  res.json({ success: true })
})

// Graceful shutdown
process.on('SIGTERM', async () => {
  await hangarx.shutdown()
  process.exit(0)
})

Next.js API Routes

// app/api/track/route.ts
import { HangarX } from '@hangarx/node'
import { NextRequest, NextResponse } from 'next/server'

const hangarx = new HangarX({ apiKey: process.env.HANGARX_API_KEY! })

export async function POST(request: NextRequest) {
  const { userId, event, properties } = await request.json()
  
  await hangarx.track(userId, event, properties)
  
  return NextResponse.json({ success: true })
}

NestJS

import { Injectable, OnModuleDestroy } from '@nestjs/common'
import { HangarX } from '@hangarx/node'

@Injectable()
export class AnalyticsService implements OnModuleDestroy {
  private hangarx: HangarX
  
  constructor() {
    this.hangarx = new HangarX({
      apiKey: process.env.HANGARX_API_KEY!
    })
  }
  
  async trackEvent(userId: string, event: string, properties?: any) {
    await this.hangarx.track(userId, event, properties)
  }
  
  async onModuleDestroy() {
    await this.hangarx.shutdown()
  }
}

Fastify

import Fastify from 'fastify'
import { HangarX } from '@hangarx/node'

const fastify = Fastify()
const hangarx = new HangarX({ apiKey: process.env.HANGARX_API_KEY! })

// Track requests
fastify.addHook('onRequest', async (request, reply) => {
  await hangarx.track(request.user?.id || 'anonymous', 'api_request', {
    method: request.method,
    url: request.url
  })
})

// Graceful shutdown
fastify.addHook('onClose', async () => {
  await hangarx.shutdown()
})

⚙️ Configuration

Option 1: Constructor

const hangarx = new HangarX({
  apiKey: 'proj_YOUR_KEY',
  endpoint: 'https://ingest.hangarx.ai',  // Default
  batchSize: 100,                          // Events per batch
  flushInterval: 10000,                    // Flush every 10s
  maxRetries: 3,                           // Retry failed requests
  timeout: 30000,                          // Request timeout (30s)
  debug: false                             // Enable debug logs
})

Option 2: Environment Variables

# .env
HANGARX_API_KEY=proj_YOUR_KEY
HANGARX_ENDPOINT=https://ingest.hangarx.ai
HANGARX_BATCH_SIZE=100
HANGARX_FLUSH_INTERVAL=10000
HANGARX_DEBUG=true
import { hangarx } from '@hangarx/node'

// Auto-configured from environment
await hangarx.track('user-123', 'event_name')

🔄 Batching & Performance

Smart Batching

Events are automatically batched for efficiency:

// These 3 events are batched into 1 request
await hangarx.track('user-1', 'event1')
await hangarx.track('user-2', 'event2')
await hangarx.track('user-3', 'event3')

// Batch sent when:
// 1. Queue reaches batchSize (default: 100)
// 2. flushInterval expires (default: 10s)
// 3. Manual flush() called
// 4. Process exits (graceful shutdown)

Manual Flush

// Queue events
await hangarx.track('user-1', 'event1')
await hangarx.track('user-2', 'event2')

// Send immediately
await hangarx.flush()

Queue Size

const queueSize = hangarx.getQueueSize()
console.log(`Events in queue: ${queueSize}`)

🛡️ Error Handling & Retries

Automatic Retries

Failed requests are automatically retried with exponential backoff:

const hangarx = new HangarX({
  apiKey: 'proj_YOUR_KEY',
  maxRetries: 3  // Retry up to 3 times
})

// Retry schedule:
// 1st retry: 1 second
// 2nd retry: 2 seconds
// 3rd retry: 4 seconds

Error Handling

try {
  await hangarx.track('user-123', 'event_name')
} catch (error) {
  console.error('Failed to track event:', error)
  // Event is re-queued automatically
}

Graceful Degradation

// Events are queued even if network is down
await hangarx.track('user-123', 'event1')  // Queued
await hangarx.track('user-123', 'event2')  // Queued

// Sent when network recovers

🚨 Graceful Shutdown

Always flush events before process exits:

const hangarx = new HangarX({ apiKey: 'proj_YOUR_KEY' })

// Automatic shutdown on signals
process.on('SIGTERM', async () => {
  await hangarx.shutdown()
  process.exit(0)
})

process.on('SIGINT', async () => {
  await hangarx.shutdown()
  process.exit(0)
})

// Or use built-in handler (automatically registered)
// No need to add listeners manually

🧪 Testing

Debug Mode

const hangarx = new HangarX({
  apiKey: 'proj_YOUR_KEY',
  debug: true  // See all events in console
})

// Output:
// HangarX: Initialized { projectId: 'abc123', batchSize: 100 }
// HangarX: Enqueued event { type: 'purchase', userId: 'user-123' }
// HangarX: Successfully flushed 1 events

Mock for Testing

// test/analytics.test.ts
import { HangarX } from '@hangarx/node'

jest.mock('@hangarx/node')

describe('Analytics', () => {
  it('should track events', async () => {
    const hangarx = new HangarX({ apiKey: 'test-key' })
    
    await hangarx.track('user-123', 'test_event', { foo: 'bar' })
    
    expect(hangarx.track).toHaveBeenCalledWith(
      'user-123',
      'test_event',
      { foo: 'bar' }
    )
  })
})

📊 Performance Monitoring

Queue Metrics

const queueSize = hangarx.getQueueSize()
console.log(`Events in queue: ${queueSize}`)

// Monitor queue size
setInterval(() => {
  const size = hangarx.getQueueSize()
  if (size > 1000) {
    console.warn('Queue is getting large:', size)
  }
}, 60000)

🎓 Best Practices

Event Naming

// ✅ Good: snake_case, descriptive
await hangarx.track('user-123', 'purchase_completed')
await hangarx.track('user-123', 'subscription_created')

// ❌ Bad: unclear, inconsistent
await hangarx.track('user-123', 'event1')
await hangarx.track('user-123', 'PurchaseCompleted')

Property Structure

// ✅ Good: consistent, typed
await hangarx.track('user-123', 'purchase', {
  product_id: 'prod-456',
  revenue: 99.99,        // number
  currency: 'USD',       // string
  quantity: 1            // number
})

// ❌ Bad: inconsistent types
await hangarx.track('user-123', 'purchase', {
  prod: 'Premium',
  amount: '99.99',       // should be number
  type: 'sub'            // unclear
})

Identify Early

// ✅ Identify as soon as user is created
const user = await createUser(data)
await hangarx.identify(user.id, {
  email: user.email,
  created_at: new Date().toISOString()
})

Always Shutdown

// ✅ Always flush before exit
process.on('SIGTERM', async () => {
  await hangarx.shutdown()
  process.exit(0)
})

🔒 Privacy & Security

API Key Security

// ✅ Good: Use environment variables
const hangarx = new HangarX({
  apiKey: process.env.HANGARX_API_KEY!
})

// ❌ Bad: Hardcoded keys
const hangarx = new HangarX({
  apiKey: 'proj_abc123...'  // Don't commit this!
})

PII Handling

// Only track what you need
await hangarx.identify('user-123', {
  email: user.email,        // ✅ OK if consented
  // ssn: user.ssn,         // ❌ Never track sensitive data
  // credit_card: user.cc   // ❌ Never track payment data
})

🚨 Common Issues

Events not showing up?

// 1. Check your API key
console.log(hangarx.config.apiKey)  // Should start with 'proj_'

// 2. Enable debug mode
const hangarx = new HangarX({ 
  apiKey: 'proj_YOUR_KEY',
  debug: true 
})

// 3. Manually flush to see errors
try {
  await hangarx.flush()
} catch (error) {
  console.error('Flush failed:', error)
}

// 4. Check queue size
console.log('Queue size:', hangarx.getQueueSize())

Network errors?

// Increase timeout
const hangarx = new HangarX({
  apiKey: 'proj_YOUR_KEY',
  timeout: 60000,  // 60 seconds
  maxRetries: 5    // More retries
})

Memory issues?

// Reduce batch size and flush more frequently
const hangarx = new HangarX({
  apiKey: 'proj_YOUR_KEY',
  batchSize: 50,        // Smaller batches
  flushInterval: 5000   // Flush every 5s
})

📚 Examples

Background Job

import { HangarX } from '@hangarx/node'

const hangarx = new HangarX({ apiKey: process.env.HANGARX_API_KEY! })

async function processOrder(order) {
  // Process order
  await fulfillOrder(order)
  
  // Track completion
  await hangarx.track(order.userId, 'order_fulfilled', {
    order_id: order.id,
    amount: order.total,
    items: order.items.length
  })
}

Webhook Handler

app.post('/webhooks/stripe', async (req, res) => {
  const event = req.body
  
  if (event.type === 'payment_intent.succeeded') {
    await hangarx.track(event.data.object.customer, 'payment_succeeded', {
      amount: event.data.object.amount / 100,
      currency: event.data.object.currency
    })
  }
  
  res.json({ received: true })
})

Scheduled Task

import cron from 'node-cron'

// Track daily metrics
cron.schedule('0 0 * * *', async () => {
  const metrics = await getDailyMetrics()
  
  await hangarx.track('system', 'daily_metrics', {
    active_users: metrics.activeUsers,
    revenue: metrics.revenue,
    signups: metrics.signups
  })
})

📚 Resources


🤝 Support

Need help? We're here:


📄 License

MIT License - see LICENSE


Ready for takeoff? 🚀

Install HangarX and start tracking server-side events.

npm install @hangarx/node

Made with ❤️ by the HangarX crew

WebsiteDocsBlog