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

finlight-client

v3.0.3

Published

Finlight.me client for API and WebSocket

Downloads

1,088

Readme

finlight API Client

The finlight API Client is a modern TypeScript SDK for accessing the finlight.me platform. It provides robust and fully-typed REST and WebSocket interfaces to fetch market-relevant news articles enriched with sentiment, metadata, and company tagging.

✨ Features

  • 🔎 Advanced article search with flexible query language
  • 🔌 Real-time article streaming via WebSocket
  • 💡 Full support for company tagging and content filters
  • 🔁 Built-in retries and automatic reconnection
  • 🔐 Secure API key authentication
  • 📝 Configurable logging (console, winston, pino, custom)
  • 🔔 Webhook support with HMAC verification
  • ✅ Strong TypeScript types for better DX

📦 Installation

npm install finlight-client

🚀 Quick Start

Initialize the Client

import { FinlightApi } from 'finlight-client';

const api = new FinlightApi({
  apiKey: 'your-api-key', // Required
});

With Custom Logging

const api = new FinlightApi({
  apiKey: 'your-api-key',
  logger: console,      // Use console, winston, pino, or custom
  logLevel: 'info',     // 'debug' | 'info' | 'warn' | 'error'
});

📘 REST API Usage

Fetch Articles

const response = await api.articles.fetchArticles({
  query: '(ticker:AAPL OR ticker:TSLA) AND "earnings"',
  tickers: ['AAPL', 'TSLA'],
  countries: ['US'],
  language: 'en',
  pageSize: 10,
  includeEntities: true,
  includeContent: true,
  from: '2024-01-01',
  to: '2024-12-31',
});

console.log(response.articles);

Fetch Sources

const sources = await api.sources.getSources();
console.log(sources);

🔄 WebSocket Streaming

Subscribe to Live Articles

const client = new FinlightApi(
  {
    apiKey: 'your-api-key',
    logger: console,
    logLevel: 'info',
  },
  {
    // WebSocket-specific options
    takeover: false,          // takeover existing connections (default: false)
  }
);

client.websocket.connect(
  {
    query: 'AI AND ticker:NVDA',
    tickers: ['NVDA'],
    language: 'en',
    includeContent: true,
    includeEntities: true,
  },
  (article) => {
    console.log('Live article:', article);
  },
);

// To disconnect
client.websocket.stop();

🔔 Webhook Support

Securely receive webhook events from finlight with HMAC signature verification:

import { WebhookService } from 'finlight-client';
import express from 'express';

const app = express();

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const article = WebhookService.constructEvent(
      req.body.toString(),
      req.headers['x-webhook-signature'] as string,
      process.env.WEBHOOK_SECRET!,
      req.headers['x-webhook-timestamp'] as string
    );

    console.log('New article:', article.title);
    res.sendStatus(200);
  } catch (err) {
    console.error('Webhook verification failed:', err);
    res.sendStatus(400);
  }
});

🛠️ Configuration

Client Options

const api = new FinlightApi({
  apiKey: 'your-api-key',                  // Required
  baseUrl: 'https://api.finlight.me',      // Optional
  wssUrl: 'wss://wss.finlight.me',         // Optional
  timeout: 5000,                           // Request timeout in ms (default: 5000)
  retryCount: 3,                           // Retry count (default: 3)
  logger: console,                         // Logger instance (default: console)
  logLevel: 'info',                        // Log level (default: 'info')
});

WebSocket Options

const api = new FinlightApi(
  { apiKey: 'your-api-key' },
  {
    pingInterval: 25,            // Heartbeat interval in seconds (default: 25)
    pongTimeout: 60,             // Pong timeout in seconds (default: 60)
    baseReconnectDelay: 0.5,     // Initial reconnect delay in seconds (default: 0.5)
    maxReconnectDelay: 10,       // Max reconnect delay in seconds (default: 10)
    takeover: false,             // Takeover existing connections (default: false)
    onClose: (code, reason) => { // Custom close handler
      console.log('Closed:', code, reason);
    },
  }
);

📝 Logging

Built-in Loggers

import { FinlightApi, noopLogger } from 'finlight-client';

// Silent mode
const api = new FinlightApi({
  apiKey: 'key',
  logger: noopLogger,
});

// Console logging (default)
const api = new FinlightApi({
  apiKey: 'key',
  logger: console,
  logLevel: 'debug',
});

Custom Logger

import { Logger } from 'finlight-client';

const customLogger: Logger = {
  debug: (...args) => console.log('[DEBUG]', ...args),
  info: (...args) => console.log('[INFO]', ...args),
  warn: (...args) => console.warn('[WARN]', ...args),
  error: (...args) => console.error('[ERROR]', ...args),
};

const api = new FinlightApi({
  apiKey: 'key',
  logger: customLogger,
});

Winston/Pino Integration

import winston from 'winston';

const winstonLogger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [new winston.transports.Console()],
});

const api = new FinlightApi({
  apiKey: 'key',
  logger: winstonLogger,  // Pass winston/pino directly!
});

🧾 Types & Interfaces

GetArticlesParams

interface GetArticlesParams {
  query?: string;                // Advanced query: (ticker:AAPL OR ticker:NVDA)
  tickers?: string[];            // Filter by tickers: ['AAPL', 'NVDA']
  sources?: string[];            // Limit to specific sources
  excludeSources?: string[];     // Exclude specific sources
  optInSources?: string[];       // Additional sources to include
  countries?: string[];          // Filter by country codes: ['US', 'GB']
  includeContent?: boolean;      // Include full article content
  includeEntities?: boolean;     // Include tagged company data
  excludeEmptyContent?: boolean; // Skip articles with no content
  from?: string;                 // Start date (YYYY-MM-DD or ISO)
  to?: string;                   // End date (YYYY-MM-DD or ISO)
  language?: string;             // Language filter (default: 'en')
  orderBy?: 'publishDate' | 'createdAt';
  order?: 'ASC' | 'DESC';
  pageSize?: number;             // Results per page (1-1000)
  page?: number;                 // Page number
}

GetArticlesWebSocketParams

interface GetArticlesWebSocketParams {
  query?: string;
  tickers?: string[];
  sources?: string[];
  excludeSources?: string[];
  optInSources?: string[];
  countries?: string[];          // Filter by country codes: ['US', 'GB']
  includeContent?: boolean;
  includeEntities?: boolean;
  excludeEmptyContent?: boolean;
  language?: string;
}

Article

interface Article {
  link: string;
  title: string;
  publishDate: Date;
  source: string;
  language: string;
  sentiment?: string;
  confidence?: number;
  summary?: string;
  images?: string[];
  content?: string;
  companies?: Company[];
}

Company

interface Company {
  companyId: number;
  confidence?: number;
  country?: string;
  exchange?: string;
  industry?: string;
  sector?: string;
  name: string;
  ticker: string;
  isin?: string;
  openfigi?: string;
  primaryListing?: Listing;
  isins?: string[];
  otherListings?: Listing[];
}

❗ Error Handling & Retry Logic

REST API Retries

The client automatically retries failed HTTP requests for:

  • 429 Too Many Requests
  • 500 Internal Server Error
  • 502 Bad Gateway
  • 503 Service Unavailable
  • 504 Gateway Timeout

Retry behavior uses exponential backoff (500ms, 1000ms, 2000ms, etc.).

WebSocket Reconnection

On disconnection, the client automatically attempts to reconnect with:

  • Exponential backoff (0.5s → 1s → 2s → ... → 10s max)
  • Proactive connection rotation (every 115 minutes to avoid AWS 2-hour limit)
  • Rate limit and error handling with appropriate backoff

🧪 Testing

Unit Tests

npm test

Integration Tests

Integration tests require a valid API key:

# All integration tests
FINLIGHT_API_KEY=your_key npm run test:integration

# API tests only
FINLIGHT_API_KEY=your_key npm run test:integration:api

# WebSocket tests only
FINLIGHT_API_KEY=your_key npm run test:integration:ws

📮 Support

If you encounter issues or have questions:


🎉 Happy coding!

finlight helps you stay ahead of the market with real-time, enriched news feeds.