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

@firebreak/lookout

v1.0.0

Published

TypeScript client for Lookout deployment notifications

Readme

Lookout

TypeScript/JavaScript client for sending deployment notifications to Lookout with smart step tracking and automatic timing.

Features

  • 🚀 Simple API - Start tracking deployments in just a few lines of code
  • ⏱️ Automatic Timing - SDK automatically tracks step duration
  • 🔄 Auto Retry - Built-in retry logic with exponential backoff
  • 📝 TypeScript - Full type definitions for excellent IDE support
  • Validation - Input validation prevents bad API calls
  • 🎯 Smart State Management - Tracks deployment and step state automatically

Installation

npm install @firebreak/lookout

Quick Start

import { LookoutClient } from '@firebreak/lookout';

// Create client
const client = new LookoutClient({
  webhookUrl: process.env.LOOKOUT_WEBHOOK_URL,
  apiToken: process.env.LOOKOUT_API_TOKEN,
  teamId: process.env.SLACK_TEAM_ID,
});

// Start deployment
const deployment = await client.startDeployment({
  deploymentId: 'deploy-123',
  version: 'v1.2.0',
  environment: 'production',
  steps: ['Build', 'Test', 'Deploy'],
});

// Run steps with automatic timing
await deployment.runStep('Build', async () => {
  // Your build logic here
});

await deployment.runStep('Test', async () => {
  // Your test logic here
});

await deployment.runStep('Deploy', async () => {
  // Your deploy logic here
});

// Mark deployment as successful
await deployment.success();

GitHub Actions Integration

Step 1: Add Secrets

Add these secrets to your GitHub repository:

  • LOOKOUT_WEBHOOK_URL - Your Lookout webhook URL
  • LOOKOUT_API_TOKEN - Your Lookout API token
  • SLACK_TEAM_ID - Your Slack workspace ID
  • SLACK_RELEASE_MANAGER_ID - Slack user ID for release manager

Step 2: Create Deployment Script

Create deploy-with-lookout.js:

const { LookoutClient } = require('@firebreak/lookout');

async function deploy() {
  const client = new LookoutClient({
    webhookUrl: process.env.LOOKOUT_WEBHOOK_URL,
    apiToken: process.env.LOOKOUT_API_TOKEN,
    teamId: process.env.SLACK_TEAM_ID,
  });

  const deployment = await client.startDeployment({
    deploymentId: `${process.env.GITHUB_RUN_ID}-${process.env.GITHUB_RUN_NUMBER}`,
    version: process.env.GITHUB_REF_NAME || 'unknown',
    environment: 'production',
    releaseManager: process.env.SLACK_RELEASE_MANAGER_ID,
    steps: ['Build', 'Test', 'Deploy', 'Verify'],
  });

  try {
    await deployment.runStep('Build', async () => {
      // Build commands
      console.log('Building...');
    });

    await deployment.runStep('Test', async () => {
      // Test commands
      console.log('Testing...');
    });

    await deployment.runStep('Deploy', async () => {
      // Deploy commands
      console.log('Deploying...');
    });

    await deployment.runStep('Verify', async () => {
      // Verification commands
      console.log('Verifying...');
    });

    await deployment.success();
  } catch (error) {
    await deployment.fail(error.message);
    throw error;
  }
}

deploy();

Step 3: Update GitHub Actions Workflow

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-node@v3
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm install @firebreak/lookout

      - name: Deploy with Lookout notifications
        run: node deploy-with-lookout.js
        env:
          LOOKOUT_WEBHOOK_URL: ${{ secrets.LOOKOUT_WEBHOOK_URL }}
          LOOKOUT_API_TOKEN: ${{ secrets.LOOKOUT_API_TOKEN }}
          SLACK_TEAM_ID: ${{ secrets.SLACK_TEAM_ID }}
          SLACK_RELEASE_MANAGER_ID: ${{ secrets.SLACK_RELEASE_MANAGER_ID }}

API Reference

LookoutClient

Main entry point for the SDK.

Constructor

new LookoutClient(config: LookoutConfig)

Config Options:

  • webhookUrl (required) - Lookout webhook URL
  • apiToken (required) - API authentication token
  • teamId (required) - Slack team/workspace ID
  • retry (optional) - Retry configuration
    • maxAttempts - Max retry attempts (default: 3)
    • initialDelay - Initial delay in ms (default: 1000)
    • maxDelay - Max delay in ms (default: 10000)
    • backoff - 'linear' or 'exponential' (default: 'exponential')
  • timeout (optional) - Request timeout in ms (default: 30000)
  • defaultEnvironment (optional) - Default environment name
  • defaultVersion (optional) - Default version string

Methods

startDeployment(options: DeploymentOptions): Promise

Create and start a deployment, sending initial notification.

const deployment = await client.startDeployment({
  deploymentId: 'deploy-123',
  version: 'v1.0.0',
  environment: 'production',
  releaseManager: 'U123456',
  releaseNotes: '## Changes\n- Bug fixes',
  steps: ['Build', 'Test', 'Deploy'],
});

createDeployment(options: DeploymentOptions): DeploymentTracker

Create deployment tracker without sending initial notification.

DeploymentTracker

Manages individual deployment lifecycle.

Methods

runStep(name: string, fn: () => Promise): Promise

Run a step with automatic timing and error handling.

await deployment.runStep('Build', async () => {
  // Build logic
});

startStep(name: string): Promise

Manually start a step.

await deployment.startStep('Build');

completeStep(name: string): Promise

Manually complete a step.

await deployment.completeStep('Build');

failStep(name: string, error?: string): Promise

Mark a step as failed.

await deployment.failStep('Build', 'Compilation failed');

success(): Promise

Mark deployment as successful.

await deployment.success();

fail(error?: string): Promise

Mark deployment as failed.

await deployment.fail('Deployment timed out');

update(): Promise

Manually send current state to Lookout.

await deployment.update();

getState(): DeploymentState

Get current deployment state (read-only).

getDeploymentId(): string

Get deployment ID.

getStatus(): DeploymentStatus

Get current deployment status.

isComplete(): boolean

Check if deployment is complete (success or failed).

Error Handling

The SDK provides typed errors for different failure scenarios:

import { LookoutClient, ApiError, ValidationError, LookoutError } from '@firebreak/lookout';

try {
  await deployment.success();
} catch (error) {
  if (error instanceof ApiError) {
    if (error.is('UNAUTHORIZED')) {
      console.error('Invalid API token');
    } else if (error.is('NOT_FOUND')) {
      console.error('Team not configured');
    } else if (error.statusCode >= 500) {
      console.error('Server error - retrying...');
    }
  } else if (error instanceof ValidationError) {
    console.error('Invalid input:', error.message);
    console.error('Field:', error.field);
  } else if (error instanceof LookoutError) {
    console.error('SDK error:', error.code, error.message);
  }
}

Advanced Usage

Manual Step Control

const deployment = client.createDeployment({
  deploymentId: 'deploy-123',
  version: 'v1.0.0',
  steps: [
    { name: 'Build', status: 'pending' },
    { name: 'Test', status: 'pending' },
    { name: 'Deploy', status: 'pending' },
  ],
});

// Send initial notification
await deployment.update();

// Manual control
await deployment.startStep('Build');
// ... build logic ...
await deployment.completeStep('Build');

await deployment.startStep('Test');
// ... if test fails ...
await deployment.failStep('Test', 'Tests failed');
await deployment.fail('Deployment aborted due to test failures');

Custom Retry Configuration

const client = new LookoutClient({
  webhookUrl: process.env.LOOKOUT_WEBHOOK_URL,
  apiToken: process.env.LOOKOUT_API_TOKEN,
  teamId: process.env.SLACK_TEAM_ID,
  retry: {
    maxAttempts: 5,
    initialDelay: 2000,
    maxDelay: 30000,
    backoff: 'exponential',
  },
  timeout: 60000, // 60 seconds
});

TypeScript Support

The SDK is written in TypeScript and provides full type definitions:

import type {
  LookoutConfig,
  DeploymentOptions,
  DeploymentStatus,
  StepStatus,
  DeploymentState,
} from '@firebreak/lookout';

const options: DeploymentOptions = {
  deploymentId: 'deploy-123',
  version: 'v1.0.0',
  environment: 'production',
  status: 'in_progress', // Type-safe
  steps: ['Build', 'Test', 'Deploy'],
};

Examples

See the examples/ directory for more usage examples:

License

MIT

Support

For issues and questions, please open an issue.