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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@walkeros/server-source-express

v0.4.1

Published

Express server source for walkerOS

Readme

@walkeros/server-source-express

Express server source for walkerOS - turn-key HTTP event collection server with Express.js.

Installation

npm install @walkeros/server-source-express

Quick Start

Standalone Server (Docker-style)

import { startFlow } from '@walkeros/collector';
import { sourceExpress } from '@walkeros/server-source-express';

const { collector } = await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: {
          port: 8080, // Start server on port 8080
        },
      },
    },
  },
  destinations: {
    // Your destinations here
  },
});

// Server is now running!
// POST http://localhost:8080/collect - JSON event ingestion
// GET  http://localhost:8080/collect - Pixel tracking
// GET  http://localhost:8080/health  - Health check

App-Only Mode (Custom Integration)

const { collector } = await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: {
          // No port = app only, no server started
          path: '/events',
          cors: false, // Handle CORS with your own middleware
        },
      },
    },
  },
});

// Access the Express app
const expressSource = collector.sources.express;
const app = expressSource.app;

// Add custom middleware
app.use(yourAuthMiddleware);

// Add custom routes
app.get('/custom', customHandler);

// Start server manually
app.listen(3000);

Configuration

Settings

interface Settings {
  /**
   * HTTP server port to listen on
   * If not provided, server will not start (app-only mode)
   * @optional
   */
  port?: number;

  /**
   * Event collection endpoint path
   * All HTTP methods (POST, GET, OPTIONS) registered on this path
   * @default '/collect'
   */
  path?: string;

  /**
   * CORS configuration
   * - false: Disabled
   * - true: Allow all origins (default)
   * - object: Custom CORS options
   * @default true
   */
  cors?: boolean | CorsOptions;

  /**
   * Enable health check endpoints
   * - GET /health (liveness check)
   * - GET /ready (readiness check)
   * @default true
   */
  status?: boolean;
}

CORS Options

interface CorsOptions {
  /** Allowed origins (string, array, or '*') */
  origin?: string | string[] | '*';

  /** Allowed HTTP methods */
  methods?: string[];

  /** Allowed request headers */
  headers?: string[];

  /** Allow credentials (cookies, authorization) */
  credentials?: boolean;

  /** Preflight cache duration in seconds */
  maxAge?: number;
}

HTTP Methods

POST - Standard Event Ingestion

Send events as JSON in the request body.

Request:

curl -X POST http://localhost:8080/collect \
  -H "Content-Type: application/json" \
  -d '{
    "event": "page view",
    "data": {
      "title": "Home Page",
      "path": "/"
    },
    "user": {
      "id": "user123"
    }
  }'

Response:

{
  "success": true,
  "timestamp": 1647261462000
}

GET - Pixel Tracking

Send events as query parameters. Returns a 1x1 transparent GIF.

Request:

<!-- In your HTML -->
<img
  src="http://localhost:8080/collect?event=page%20view&data[title]=Home&user[id]=user123"
  width="1"
  height="1"
  alt=""
/>

Response:

Content-Type: image/gif
Cache-Control: no-cache, no-store, must-revalidate

[1x1 transparent GIF binary]

OPTIONS - CORS Preflight

Automatically handled for cross-origin requests.

Request:

curl -X OPTIONS http://localhost:8080/collect \
  -H "Origin: https://example.com"

Response:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type

204 No Content

Health Checks

GET /health - Liveness Check

Returns server status (always returns 200 if server is running).

Response:

{
  "status": "ok",
  "timestamp": 1647261462000,
  "source": "express"
}

GET /ready - Readiness Check

Returns readiness status (same as health for Express source).

Response:

{
  "status": "ready",
  "timestamp": 1647261462000,
  "source": "express"
}

Advanced Examples

Custom CORS Configuration

await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: {
          port: 8080,
          cors: {
            origin: ['https://app.example.com', 'https://admin.example.com'],
            credentials: true,
            methods: ['GET', 'POST', 'OPTIONS'],
            headers: ['Content-Type', 'Authorization'],
            maxAge: 86400, // 24 hours
          },
        },
      },
    },
  },
});

Disable Health Checks

await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: {
          port: 8080,
          status: false, // Disable /health and /ready endpoints
        },
      },
    },
  },
});

Custom Endpoint Path

await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: {
          port: 8080,
          path: '/api/v1/events', // Custom path
        },
      },
    },
  },
});

// All methods now work on /api/v1/events
// POST /api/v1/events
// GET /api/v1/events
// OPTIONS /api/v1/events

Extend Express App

const { collector } = await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: { port: 8080 },
      },
    },
  },
});

// Access Express app for advanced customization
const expressSource = collector.sources.express;
const app = expressSource.app;

// Add authentication middleware
app.use('/collect', authMiddleware);

// Add rate limiting
import rateLimit from 'express-rate-limit';
app.use(
  '/collect',
  rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100, // Limit each IP to 100 requests per windowMs
  }),
);

// Add custom logging
app.use((req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  next();
});

Event Format

Single Event

{
  "event": "page view",
  "data": {
    "title": "Home Page",
    "path": "/"
  },
  "context": {
    "language": ["en", 0],
    "currency": ["USD", 0]
  },
  "user": {
    "id": "user123",
    "device": "device456"
  },
  "globals": {
    "appVersion": "1.0.0"
  },
  "consent": {
    "functional": true,
    "marketing": true
  }
}

Query Parameters (GET)

For pixel tracking, use nested bracket notation:

?event=page%20view
&data[title]=Home%20Page
&data[path]=/
&user[id]=user123
&consent[marketing]=true

This is automatically parsed by requestToData from @walkeros/core.

Architecture

Infrastructure Ownership

The Express source owns its HTTP infrastructure:

  • ✅ Creates Express application
  • ✅ Configures middleware (JSON parsing, CORS)
  • ✅ Registers routes (POST, GET, OPTIONS)
  • ✅ Starts HTTP server (if port configured)
  • ✅ Handles graceful shutdown (SIGTERM, SIGINT)

This design enables:

  1. Turn-key deployment - Just specify a port and deploy
  2. Docker-friendly - Perfect for containerized environments
  3. Flexibility - App-only mode for custom integrations

Request Flow

┌─────────────────────────────────────────┐
│ HTTP Client (Browser, Server, etc.)    │
└─────────────────────────────────────────┘
                 ↓
┌─────────────────────────────────────────┐
│ EXPRESS SOURCE                          │
│ - Receives HTTP request                 │
│ - Parses body/query params              │
│ - Validates request structure           │
│ - Calls env.push() → Collector          │
│ - Returns HTTP response                 │
└─────────────────────────────────────────┘
                 ↓
┌─────────────────────────────────────────┐
│ COLLECTOR                               │
│ - Event validation & processing         │
│ - Consent management                    │
│ - Mapping rules                         │
│ - Routes to destinations                │
└─────────────────────────────────────────┘

Deployment

Docker

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

ENV PORT=8080
EXPOSE 8080

CMD ["node", "server.js"]

server.js:

import { startFlow } from '@walkeros/collector';
import { sourceExpress } from '@walkeros/server-source-express';

await startFlow({
  sources: {
    express: {
      code: sourceExpress,
      config: {
        settings: {
          port: process.env.PORT || 8080,
        },
      },
    },
  },
  // Your destinations...
});

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: walkeros-collector
spec:
  replicas: 3
  selector:
    matchLabels:
      app: walkeros-collector
  template:
    metadata:
      labels:
        app: walkeros-collector
    spec:
      containers:
        - name: collector
          image: your-registry/walkeros-collector:latest
          ports:
            - containerPort: 8080
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 5
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 3

Testing

The package includes comprehensive tests using mocked Express Request/Response objects.

Run tests:

npm test

Example test:

import { sourceExpress } from '@walkeros/server-source-express';

test('should process POST event', async () => {
  const mockPush = jest.fn().mockResolvedValue({ event: { id: 'test' } });

  const source = await sourceExpress(
    {},
    {
      push: mockPush,
      command: jest.fn(),
      elb: jest.fn(),
    },
  );

  const req = {
    method: 'POST',
    body: { event: 'page view', data: { title: 'Home' } },
    headers: {},
    get: () => undefined,
  };
  const res = {
    status: jest.fn().returnThis(),
    json: jest.fn(),
    send: jest.fn(),
    set: jest.fn(),
  };

  await source.push(req, res);

  expect(res.status).toHaveBeenCalledWith(200);
  expect(mockPush).toHaveBeenCalled();
});

License

MIT

Links