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

lakeql-lance

v0.2.3

Published

Bounded random-access and indexed Lance reader for JavaScript runtimes

Readme

lakeql-lance

lakeql-lance performs bounded, projection-aware random reads from immutable Lance datasets in Cloudflare Workers, browsers, and Node.js. It is intended for applications that already have stable Lance row IDs from a search index and need to materialize the corresponding records without scanning a key column.

import { openLanceDataset } from "lakeql-lance";

const dataset = await openLanceDataset({
  store,
  path: "catalog.lance",
  indexCacheBytes: 8 * 1024 * 1024,
  budget: {
    maxBytes: 8 * 1024 * 1024,
    maxRangeRequests: 128,
    maxMemoryBytes: 16 * 1024 * 1024,
    maxOutputRows: 32,
    maxConcurrentReads: 4,
    maxElapsedMs: 3_000,
  },
});

const result = await dataset.takeRows({
  snapshotId: dataset.snapshotId,
  rowIds: [42n, 7n, 42n],
  select: ["serial", "mark_text", "owner_name"],
});

Official Lance BTree indexes can produce those stable IDs directly without a key-column scan:

const indexes = await dataset.scalarIndexes();
const result = await dataset.lookupRows({
  snapshotId: dataset.snapshotId,
  index: indexes[0].name,
  values: [1005, 1031],
  select: ["mark_text", "owner_name"],
});

lookupRows performs exact equality lookup, preserves the caller's key order and duplicate keys, returns every indexed duplicate in stable index order, and composes matches with the same snapshot-safe projected materializer. It retains the BTree lookup state, loads each candidate 4,096-row leaf once, and binary-searches its sorted keys locally. BTree page lookup, stable-ID retrieval, and result materialization share one cumulative byte, request, memory, decoded-row, concurrency, cancellation, and elapsed-time budget.

Decoded BTree lookup state and leaves use a separate snapshot-scoped LRU cache. indexCacheBytes sets its byte ceiling and defaults to 8 MiB; set it to 0 to disable decoded-index caching. Supply an explicitly sized SharedMemoryCache as indexCache to share immutable index state across separately opened handles for the same snapshot. Cache population remains subject to the query budgets, while hits consume neither range/byte budget nor decoded-row budget.

Ordered range retrieval uses the same index without decoding intervening key pages:

const result = await dataset.rangeRows({
  snapshotId: dataset.snapshotId,
  index: "serial_btree",
  range: {
    lower: 1000,
    lowerInclusive: true,
    upper: 2000,
    upperInclusive: false,
  },
  select: ["mark_text", "owner_name"],
});

Either bound may be omitted. Results remain in BTree order and output-row budgets are checked from the binary-search bounds before stable IDs or projected data are fetched.

Official Lance IVF_FLAT indexes support bounded vector search without native bindings:

const dataset = await openLanceDataset({
  store,
  path: "catalog.lance",
  budget,
  vectorLimits: {
    maxDimension: 1_536,
    maxPartitionsSearched: 16,
    maxCandidatesScored: 50_000,
  },
});

const result = await dataset.nearest({
  snapshotId: dataset.snapshotId,
  index: "embedding_ivf_flat",
  vector: queryEmbedding,
  k: 20,
  nprobes: 8,
  select: ["title", "url"],
});

The reader selects IVF partitions from the official centroid tensor, reads only their auxiliary vector and stable-ID rows, scores candidates in memory-bounded chunks, retains a deterministic top-k, and materializes projected fields in distance order. L2, cosine, and Lance dot-distance semantics are supported. nprobes is explicit: searching every partition is exact, while fewer partitions trades recall for object-storage I/O.

Store dataset.snapshotId with every external index generation. takeRows requires it and returns a typed LAKEQL_LANCE_SNAPSHOT_MISMATCH error before reading data if it does not match. Duplicate IDs and caller order are preserved. Missing and snapshot-deleted IDs throw by default; use onMissing: "null" to retain their position as null. deletedRowIds distinguishes deleted IDs from IDs that never belonged to the snapshot.

Compatibility

The current reader supports stable-row-ID datasets written with Lance storage version 2.0 and V2 manifest paths. The checked-in compatibility fixtures were produced by the official pylance 8.0.0 writer. Supported projected leaf types are UTF-8 strings, binary values, booleans, signed and unsigned integers, 32/64-bit floats, dates, and second/millisecond/microsecond/nanosecond timestamps using uncompressed flat and nullable encodings. Low-cardinality UTF-8 columns using Lance's dictionary encoding are supported, including its null sentinel. Sparse Arrow-array deletion files are supported, including Zstandard-compressed buffers.

Official version-0 BTree indexes over the supported scalar key types are supported for exact equality and bounded range lookup. Null-key lookup, bitmap/label-list index variants, and index versions other than 0 remain explicit unsupported boundaries.

Official vector index format V3 IVF_FLAT indexes (index_version 1) are supported for float32 fixed-size-list columns. IVF_PQ, IVF_SQ, IVF_RQ, and HNSW layouts remain explicit unsupported boundaries; there is no brute-force dataset fallback when an unsupported index is selected.

The reader deliberately rejects unsupported storage versions, compressed data pages, nested fields, Roaring-bitmap deletion files, and unknown encodings. It never silently scans a column, index, Lance data file, or dataset, and it rejects a data range that would read an entire Lance data file. Arrow deletion vectors are resolved only for fragments containing requested row IDs; the reader range-loads their footer, record-batch metadata, and value buffer without downloading the complete deletion object. Because the official Arrow-array producer writes deletion offsets in hash-set order, membership requires checking that touched fragment's value buffer. Its encoded and decoded bytes remain subject to the same request, byte, elapsed-time, and memory budgets.

All metadata and data access flows through LakeQL's ObjectStore, cancellation, concurrency, cache, and query-budget contracts. The result reports snapshot/data metadata bytes, logical and physical bytes, range requests, fragments/pages touched, cache activity, requested, decoded, and materialized row counts, peak memory, and elapsed time. Vector results additionally report selected partition IDs and candidates scored. Opening and each public dataset operation receive independent elapsed-time windows, while compound index lookup and row materialization share one operation window.

Reproducing the fixture

Create an isolated Python environment with pylance==8.0.0 and run:

python packages/lance/scripts/generate_fixture.py

The generator records producer and storage versions, expected projections, stable row IDs, and SHA-256 hashes in each fixture's expected.json. The generated suite includes single- and multi-page BTree datasets so compatibility tests exercise page boundaries and bounded page-local search, a dictionary-encoded UTF-8 dataset, plus L2, cosine, and dot IVF_FLAT indexes checked against official Lance ground truth.

Reproducing the public-data benchmark

Convert the public MarkWatch USPTO Parquet fixture with official Lance tooling, then exercise 32 scattered stable row IDs through HTTP ranges:

uv run --with pylance==8.0.0 --with pyarrow --with numpy \
  python bench/lance-prepare-uspto.py --output /tmp/uspto.lance
pnpm bench:lance -- --dataset /tmp/uspto.lance --trials 3

The converter records source and dataset hashes, producer/storage versions, stable IDs, and expected projections in benchmark.json. The runner also accepts --base-url, --path, and --manifest for a dataset hosted on R2 or another HTTP range server. See docs/lance-random-read-benchmark.md for the recorded results and interpretation.

For the million-row exact BTree lookup benchmark:

pnpm bench:lance-btree -- \
  --dataset /tmp/parcels-1m.lance \
  --version 3 \
  --key 50000:000000550000 \
  --trials 3

The runner enforces a 27-request cold ceiling by default and reports cold and shared-cache trials. See docs/lance-btree-exact-benchmark.md.