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

@gmod/gbz-base

v2.7.0

Published

Pure TypeScript reader for gbz-base pangenome databases (.gbz.db) with random access over HTTP range requests

Readme

@gmod/gbz-base

NPM version Build Status

A pure TypeScript reader for gbz-base pangenome databases (.gbz.db).

Install

npm install @gmod/gbz-base

Usage

import { RemoteFile } from 'generic-filehandle2'
import { GBZBase } from '@gmod/gbz-base'

const db = await GBZBase.open(
  new RemoteFile('https://example.org/graph.gbz.db'),
)

// one record per haplotype crossing the window
const alignments = await db.getAlignmentsForRange(
  'GRCh38#0#chr6',
  31500000,
  31501000,
)

// the same window as a subgraph, for a pangenome view
const subgraph = await db.getSubgraphForRange(
  'GRCh38#0#chr6',
  31500000,
  31501000,
)
const gfa = await subgraph?.toGFA({ names: 'resolved' })

Coordinates are 0-based half-open, and are offsets along the path you named, so ('GRCh38#0#chr6', 31500000, 31501000) is the same window gbz-base query --interval 31500000..31501000 gives. The path is a PanSN sample#haplotype#contig string, or a bare contig for a graph whose reference paths have no sample.

GBZBase reads only the SQLite pages a query touches, so it queries a multi-gigabyte database on an HTTP server through range requests without downloading it. Any generic-filehandle2 source works — LocalFile, RemoteFile, BlobFile — and there is a gbz-base-query command line that mirrors the upstream tool. Every option, method and query function: docs/api.md; what a query does between the call and the records, drawn: docs/dataflow.md.

Alignment records

for (const alignment of alignments) {
  const { refStart, refEnd, strand, cigar } = alignment
  if (alignment.resolved) {
    console.log(alignment.label, alignment.hapStart, alignment.hapEnd)
  }
}

A record is one haplotype's passage through the window, aligned to the reference path you queried. Where a haplotype leaves the subgraph and comes back — a private insertion, a bubble the window does not hold — the pieces are joined back into one record and the stretch between them becomes its insertion and deletion, so context changes what is read rather than how many records you get. The fields, the joining rules and what resolved means: docs/alignments.md.

subgraph.pairAlignments aligns one haplotype to another with the bases compared, so two haplotypes sharing sequence the reference lacks align through it, and gbz-base-query --stack prints each row of a stacked synteny view against the next as PAF: docs/alignments.md.

getAlignmentsForRange hands back data and spans path fragments; getSubgraphForRange hands back the Subgraph itself, because two disjoint fragments do not merge into one graph.

Naming haplotypes

Upstream gbz-base cannot determine which haplotype a subgraph path belongs to, so it emits unknown#N. This package adds that with two side tables that a small Rust tool (tools/haplotype-index/) writes into an existing database, or into a standalone companion beside a database someone else hosts:

const db = await GBZBase.open(new RemoteFile(graphUrl), {
  haplotypeIndex: new RemoteFile(indexUrl),
})

With names in hand, keep cuts a window to a chosen set of haplotypes — the reference walk, the walks the predicate accepts and the nodes those walks visit, so the drawing shows that set's private sequence and nothing else's. On a companion carrying anchors those haplotypes are walked from an anchor before the window, and nothing else is extracted or named, so the query's cost scales with the set rather than the graph: the eight haplotypes of the MHC class II tutorial window come back in 0.97 s against 9.16 s for all 464, both warm. docs/haplotype-index.md covers building the index and the two routes; docs/performance.md has the measurements.

Snarls

The snarls option uses the top-level chains a .gbz.db already stores, the way upstream's --snarls and --extend-snarls do — contained brings a window's variation back without widening it by a bp radius. docs/snarls.md.

Why not compile the Rust to wasm

gbwt-rs and simple-sds serialize usize at native width, so a wasm32 build misreads every file written on a 64-bit host, and the PR to fix that was closed unmerged — reasonably, since the same hazard sits on every other usize in the crate. wasm64 fixes the width but cannot carry gbz-base, whose bundled SQLite has no wasm64 libc. A TypeScript reader has neither problem, and it supports HTTP range access and runs in a JBrowse RPC worker without extra code for either: docs/why-not-wasm.md.

In JBrowse

jbrowse-plugin-graphgenomeviewer is the consumer this was written for. Its GbzBaseSyntenyAdapter opens a .gbz.db and its companion through JBrowse's own file access layer, and calls getSubgraphForRange for the graph view and getAlignmentsForRange for the haplotype lanes — in an RPC worker, like any other adapter.

Because the worker is where the subgraph is built and the main thread is where it is drawn, the representation it crosses in matters more than the representation it is built in. toSubgraphJson returns upstream's format, which uses an object and a stringified id for each of a human window's ~350,000 steps and costs about 295 ms to structured-clone; toCompactSubgraph returns the same subgraph as typed arrays of GBWT handles, which clones in 1.9 ms and can be transferred instead of copied. docs/api.md has both formats and the measurements.

Docs

Footnote

Started from ideas at MemPanG 26!

License

MIT © Colin Diesh