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

bmlt-query-client

v1.0.5

Published

A TypeScript client for querying BMLT (Basic Meeting List Tool) servers with built-in geocoding support

Readme

BMLT Query Client

npm version License: MIT Node.js npm

A modern TypeScript/JavaScript client for querying BMLT (Basic Meeting List Tool) servers with built-in geocoding support using the native fetch API.

Demo

https://bmlt-enabled.github.io/bmlt-query-client/

Features

  • 🚀 Zero dependencies - Uses native fetch API
  • 🏛️ Complete BMLT API coverage - All semantic endpoints supported
  • 🌍 Built-in geocoding - Uses Nominatim for address-to-coordinates conversion
  • 🔍 Fluent query builder - Chainable API for complex meeting searches
  • Rate limiting & retry logic - Stable operation with automatic retries
  • 📱 Browser ready - Works in all modern browsers via ES modules
  • 🎯 TypeScript support - Full type definitions included
  • 📦 ES Module format - Single optimized browser-compatible build

Quick Start

For Browser (ES Modules)

The easiest way to use the BMLT Query Client in the browser is via ES modules:

<script type="module">
  // Import directly from a CDN (when published)
  import { BmltClient, VenueType, QuickSearch } from 'https://cdn.aws.bmlt.app/app.js';

  // Or import from your local build
  // import { BmltClient, VenueType, QuickSearch } from './dist/app.js';

  // Initialize the client
  const client = new BmltClient({
    rootServerURL: 'https://latest.aws.bmlt.app/main_server', // NYC demo server
  });

  // Search for virtual meetings
  const virtualMeetings = await client.searchMeetings({
    venue_types: VenueType.VIRTUAL,
    page_size: 10,
  });

  // Search meetings by address
  const nearbyMeetings = await client.searchMeetingsByAddress({
    address: 'Times Square, New York, NY',
    radiusMiles: 5,
    searchParams: { page_size: 10 },
  });

  // Use the fluent query builder
  const quickSearch = new QuickSearch(client);
  const todaysMeetings = await quickSearch.today().virtualOnly().execute();

  console.log('Found meetings:', nearbyMeetings);
</script>

For Node.js

npm install bmlt-query-client
import { BmltClient, VenueType, MeetingQueryBuilder } from 'bmlt-query-client';

const client = new BmltClient({
  rootServerURL: 'https://your-bmlt-server.org/main_server',
});

// Search for meetings
const meetings = await client.searchMeetings({
  weekdays: [1, 2, 3], // Sunday, Monday, Tuesday
  venue_types: VenueType.IN_PERSON,
});

// Use the query builder for complex searches
const builder = new MeetingQueryBuilder(client);
const eveningMeetings = await builder
  .onWeekdays(1, 2, 3, 4, 5) // Weekdays
  .startingAfter(17, 0) // After 5 PM
  .inPersonOnly()
  .nearCoordinates({ latitude: 40.7589, longitude: -73.9851 }, 2) // 2 mile radius
  .execute();

Bundle Size

The client has been optimized for minimal bundle size:

  • ES Module: ~55KB (15KB gzipped) - Zero external dependencies, fully self-contained

Browser Support

  • ✅ Chrome 63+
  • ✅ Firefox 67+
  • ✅ Safari 13.1+
  • ✅ Edge 79+

All modern browsers with ES2020 support and native fetch API.

Key Features

Comprehensive BMLT API Support

// Server information
const serverInfo = await client.getServerInfo();

// Meeting formats
const formats = await client.getFormats();

// Service bodies
const serviceBodies = await client.getServiceBodies();

// Field values
const fieldValues = await client.getFieldValues({
  meeting_key: 'location_municipality',
});

// Changes within date range
const changes = await client.getChanges({
  start_date: '2023-01-01',
  end_date: '2023-01-31',
});

Built-in Geocoding

// Geocode an address
const result = await client.geocodeAddress('Times Square, New York');
console.log(result.coordinates); // { latitude: 40.758, longitude: -73.985 }

// Search meetings by address (uses geocoding automatically)
const meetings = await client.searchMeetingsByAddress({
  address: 'Central Park, New York',
  radiusMiles: 2,
  sortByDistance: true,
});

Fluent Query Builder

const builder = new MeetingQueryBuilder(client);

// Build complex queries with method chaining
const meetings = await builder
  .onWeekdays(Weekday.SATURDAY, Weekday.SUNDAY)
  .virtualOnly()
  .startingAfter(10, 0) // After 10 AM
  .endingBefore(20, 0) // Before 8 PM
  .searchText('meditation')
  .sortByDistance()
  .paginate(20, 1) // 20 results, page 1
  .execute();

Quick Search Helpers

const quickSearch = new QuickSearch(client);

// Pre-built search methods
const todaysMeetings = await quickSearch.today().execute();
const virtualMeetings = await quickSearch.virtual().execute();
const eveningMeetings = await quickSearch.evening().execute();
const weekendMeetings = await quickSearch.weekend().execute();

// Combine quick searches with additional filters
const todaysVirtualMeetings = await quickSearch
  .today()
  .virtualOnly()
  .startingAfter(18, 0) // After 6 PM
  .execute();

Error Handling

The client provides comprehensive error handling with specific error types:

import { BmltQueryError, BmltErrorType } from 'bmlt-query-client';

try {
  const meetings = await client.searchMeetings({ invalid: 'parameter' });
} catch (error) {
  if (error instanceof BmltQueryError) {
    console.log('Error type:', error.type);
    console.log('User message:', error.getUserMessage());

    if (error.isRetryable()) {
      // Handle retryable errors (network, timeout, rate limit)
      console.log('This error can be retried');
    }

    if (error.isType(BmltErrorType.GEOCODING_ERROR)) {
      // Handle geocoding-specific errors
      console.log('Geocoding failed');
    }
  }
}

Examples

Development

# Install dependencies
npm install

# Run tests
npm test

# Build the ES module bundle
npm run build

# Clean build directory
npm run clean

# Code formatting
npm run format        # Format all files
npm run format:check  # Check formatting

# Code quality
npm run lint          # Lint code
npm run type-check    # TypeScript checking

Configuration

Runtime Configuration

You can update client settings after initialization:

// Update user agent for all requests
client.setUserAgent('my-updated-app/2.0.0');
console.log(client.getUserAgent()); // 'my-updated-app/2.0.0'

// Update request timeout
client.setTimeout(60000); // 60 seconds
console.log(client.getTimeout()); // 60000

// Update root server URL
client.setRootServerURL('https://new-server.org/main_server');
console.log(client.getRootServerURL());

// Update default data format
client.setDefaultFormat(BmltDataFormat.JSONP);
console.log(client.getDefaultFormat());

Client Options

const client = new BmltClient({
  rootServerURL: 'https://your-server.org/main_server', // Required
  defaultFormat: BmltDataFormat.JSON, // Optional
  timeout: 30000, // 30 seconds
  userAgent: 'my-app/1.0.0', // Custom user agent
  enableGeocoding: true, // Enable address search
  geocodingOptions: {
    countryCode: 'us', // Bias results to US
    retryCount: 3, // Retry failed requests
    timeout: 10000, // Geocoding timeout
  },
});

Geocoding Options

const client = new BmltClient({
  rootServerURL: 'https://your-server.org/main_server',
  geocodingOptions: {
    countryCode: 'us', // ISO country code bias
    viewbox: [-74.2, 40.4, -73.7, 40.9], // Geographic bounding box [w,s,e,n]
    bounded: true, // Restrict to viewbox
    retryCount: 3, // Request retry attempts
    timeout: 10000, // Request timeout (ms)
    intervalCap: 1, // Rate limit: requests per interval
    interval: 1000, // Rate limit interval (ms)
    concurrency: 1, // Max concurrent requests
  },
});

License

MIT License

Contributing

Contributions are welcome! Please read the contributing guidelines and submit pull requests.