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

@secuprint/mmdbjs

v1.0.0

Published

A module that allow MaxMind Database in the browser.

Readme

secuprint_mmdbjs

Frontend-only — Library to load and query MaxMind-style database files (MMDB) in the browser or from an ArrayBuffer/Uint8Array. Provides fast prefix-based IP lookup (IPv4/IPv6), pointer caching and utilities with no external dependencies.


Table of contents


Status / Purpose

secuprint_mmdbjs is a TypeScript module designed to integrate a MaxMind-style binary database into web (client) applications. It parses the MMDB binary format, resolves IP prefixes via a bitwise trie, implements a pointer LRU cache, and exposes synchronous lookup functions once the DB is loaded.

Important: This library is implemented for browser / frontend use. When a string source is provided it uses fetch internally. For non-browser environments, pass an ArrayBuffer/Uint8Array directly.


Installation

Install from npm or yarn:

npm install git+https://github.com/secuprint/secuprint_mmdbjs.git

It can also be imported from the published bundle (e.g. dist/index.mjs) if you include the generated bundle in a project.


Quick usage (examples)

Browser / URL

import Geo from 'secuprint_mmdbjs';

const geo = new Geo();

(async () => {
  await geo.load('https://example.com/path/to/GeoLite2-City.mmdb');
  const result = geo.lookup('8.8.8.8'); // result object | null
  console.log(result);
})();

ArrayBuffer / File (FileReader)

import Geo from 'secuprint_mmdbjs';

const geo = new Geo();

const fileInput = document.querySelector('input[type=file]')!;

fileInput.addEventListener('change', async (ev) => {
  const f = (ev.target as HTMLInputElement).files![0];
  const buffer = await f.arrayBuffer(); // ArrayBuffer
  await geo.load(buffer);
  console.log(geo.lookup('2001:4860:4860::8888'));
});

Constructor with autoload

import Geo from 'secuprint_mmdbjs';

const geo = new Geo({ source: 'https://example.com/geo.mmdb', autoload: true });

// If autoload is true, the public promise can be awaited.
await geo.loadPromise;
const r = geo.lookup('1.2.3.4');

Direct query with query

query is a convenience method that ensures the DB is loaded (and reloads if a different URL is provided), then performs the lookup.

import Geo from 'secuprint_mmdbjs';

const geo = new Geo();
const result = await geo.query('https://example.com/geo.mmdb', '8.8.4.4');
console.log(result);

Public API (reference)

Exported types

type RecordValue = any;
type RecordObj = { value: RecordValue; ptr: number };

export interface GeoOptions {
  source?: string | ArrayBuffer | Uint8Array;
  lru?: number;         // pointer cache size (default: 2000)
  autoload?: boolean;   // if true and source provided: load automatically
}

Class Geo

export default class Geo {
  constructor(options?: GeoOptions);

  // Loads the DB. `source` can be a URL (string) or ArrayBuffer|Uint8Array.
  // `lru` overrides the pointer cache size.
  public async load(source: string | ArrayBuffer | Uint8Array, lru = 2000): Promise<void>;

  // Synchronous lookup by IP (IPv4 or IPv6).
  // Requires the DB to be already loaded (load() called previously).
  // Returns `any` (data object) or `null` if not found.
  public lookup(ip: string): any | null;

  // Ensures the DB is loaded (if not, loads from sourceOrUrl) and does lookup.
  // Returns Promise<any | null>.
  public async query(sourceOrUrl: string | ArrayBuffer | Uint8Array, ip: string): Promise<any | null>;

  // Clears all buffers and resets state (frees memory).
  public clear(): void;

  // Indicates whether a DB is currently loaded.
  public hasDB(): boolean;

  // Public property that may contain a promise if autoload was requested in constructor.
  public loadPromise: Promise<void> | null;
}

Behavior details and errors

load(source, lru)

  • If source is a string: performs fetch(source) internally. Throws Error("Fetch failed: " + res.status) if the response is not OK.
  • If source is ArrayBuffer/Uint8Array, uses it directly.
  • Initializes binary readers, TextDecoder, and cache (Map).
  • Searches for metadata position via an internal binary marker. If not found, throws Error("Bad DB: metadata marker not found").
  • Extracts metadata and configures recordSize, numNodes, nodeSize, dataStart.
  • Creates internal IpDecoder and computes IPv4 start pointer.

lookup(ip)

  • Throws Error("DB not loaded") if the DB is not loaded.
  • Supports IPv4 and IPv6 (IP is parsed internally).
  • Returns null if the trie path leads to the numNodes marker (no entry).

query(sourceOrUrl, ip)

  • If the DB is not loaded, loads sourceOrUrl (if string: fetch).
  • If the DB is already loaded and sourceOrUrl is a string different from "__loaded__", reloads the DB from that URL.

clear()

  • Removes references to the buffer, DataView, TextDecoder, cache and other internals, leaving the object ready to be reused with load().

Specific errors

  • Bad DB: metadata marker not found — incompatible format or truncated file.
  • Fetch failed: <status> — failed to download from URL.
  • DB not loaded — calling lookup before load.

Internals (technical summary)

  • The parser detects the metadata section by searching for a static binary marker.

  • Binary readers:

    • Primitive: _read, _readBuffer, _readUTF8, _read32, _readDouble, _readFloat.
    • High-level: readData (dispatches by type), readPointer (resolves pointers), cachedRead (LRU cache).
  • Supported types: strings, maps, arrays, doubles, floats, 16/32/64/128-bit integers, booleans, bytes.

  • The prefix trie for IPs uses readLeft and readRight, behavior depends on recordSize.

  • IpDecoder supports IPv4 and IPv6 parsing and bitAt(i) for trie traversal.

  • Pointers use size+base arithmetic; optimized paths exist for small sizes and 32-bit addresses.


Performance and configuration

  • Pointer cache: default pointerCacheSize is 2000. Adjustable via GeoOptions.lru or by passing lru to load(...).

    • Simple LRU implemented over Map: when exceeding pointerCacheSize, the oldest entry is removed.
  • Optimized binary reading: once _read* functions are initialized, per-read branching is minimized.

  • lookup is synchronous and optimized; primary latency is in load (I/O + parsing).


Expected return types

  • null — when the IP has no entry.

  • string — for simple string records.

  • number — for numeric types.

  • object — for maps; may include:

    • names — object keyed by language codes, e.g. { en: "Country", es: "País" }.
    • Nested objects, arrays, bytes (as Uint8Array).

No rigid schema is enforced; return values depend on the MMDB file used.


Frequently asked questions (FAQ)

Can I use this in Node.js? The library is intended for the browser and uses fetch for URL loading. It can work in Node.js environments that provide globalThis.fetch (Node 18+). For other Node.js setups, pass ArrayBuffer/Uint8Array directly.

How do I obtain the MMDB file? This README does not include links. Use your preferred data source (MaxMind or compatible dumps). The file must contain the metadata marker expected by the parser.

Does it support streaming or partial loading? No. The library expects the full DB in memory as a Uint8Array.

What does autoload do? If options.autoload is true and options.source is provided, load(source) is started automatically and the promise is assigned to geo.loadPromise.


Final notes / License

  • The package declares "license": "SEE LICENSE FILE". Include a LICENSE file (MIT, Apache, etc.) before publishing.
  • Verify fetch compatibility for your target browsers.
  • For unit tests use small MMDB files and both IPv4/IPv6 test cases.

Reference snippets (relevant code)

Type and default export

type RecordValue = any;
type RecordObj = { value: RecordValue; ptr: number };

export interface GeoOptions {
  source?: string | ArrayBuffer | Uint8Array;
  lru?: number;
  autoload?: boolean;
}

export default class Geo { /* ... */ }

Important detectable errors

  • Bad DB: metadata marker not found
  • Fetch failed: <status>
  • DB not loaded