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

@hash-stream/index

v1.5.1

Published

The index client to use hash-stream

Readme

Install

npm install @hash-stream/index

Usage

Reader

import { IndexReader } from '@hash-stream/index/reader'
// Using a FS Index Store with Containing format
import { FSContainingIndexStore } from '@hash-stream/index/store/fs-containing'

async function main() {
  // Initialize the stores
  const indexStore = new FSContainingIndexStore('/path/to/index-store')

  // Initialize the readers
  const indexReader = new IndexReader(indexStore)

  // Get records for a given target
  const targetMultihash = // TODO
  const containingMultihash = // TODO

  const indexRecords = []
  for await (const record of indexReader.findRecords(targetMultihash, {
    containingMultihash
  })) {
    indexRecords.push(record)
  }

  console.log(indexRecords)
  // [
  //   {
  //     multihash: MultihashDigest,
  //     location: MultihashDigest,
  //     offset: number,
  //     length: number,
  //     type: IndexRecordType
  //   }
  // ]
}

main().catch(console.error)

The retrieved index records can be used to fetch the bytes behind a given multihash.

Writer

Many implementations of an IndexWriter may be created. This repository includes a MultipleLevelIndexWriter and a SingleLevelIndexWriter.

You can read more about their differences in the Index writer spec.


import { MultipleLevelIndexWriter } from '@hash-stream/index/writer/multiple-level'
import { FSContainingIndexStore } from '@hash-stream/index/store/fs-containing'

async function main() {
  // Initialize the stores
  const indexStore = new FSContainingIndexStore('/path/to/index-store')

  // Initialize the index writer
  const indexWriter = new MultipleLevelIndexWriter(indexStore)

  // Add an array of blobs associated with a Pack
  const packMultihash = // TODO
  const containingMultihash = // TODO
  const blobs = // TODO
    // [
    //   {
    //     multihash: MultihashDigest,
    //     offset: Number,
    //     length: Number,
    //   }
    // ]

  await indexWriter.addBlobs(
    (async function* () {
      for (const blob of blobs) {
        yield {
          multihash: blob.multihash,
          // Where the blob is located
          location: packMultihash,
          offset: blob.offset,
          length: blob.length,
        }
      }
    })(),
    { containingMultihash: containing.multihash }
  )
}

main().catch(console.error)

Stores

Exported Stores

This package already exports a few stores compatible with IndexStore Interface:

  • File system store: store/fs.js
  • Memory store: store/memory.js
  • S3-like Cloud Object store: store/s3-like.js
  • Cloudflare worker bucket like: store/cf-worker-bucket.js

File System store

Stores records within the host file system, by providing the path for a directory.

import fs from 'fs'
import path from 'path'
import os from 'os'

import { FSIndexStore } from '@hash-stream/index/store/fs'

const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'fs-index-store'))
const indexStore = new FSIndexStore(tempDir)

Memory System store

Stores records within a Map in memory. This is a good store to use for testing.

import { MemoryIndexStore } from '@hash-stream/index/store/memory'

const indexStore = new MemoryIndexStore()

S3-like Cloud Object store

Stores records using a S3 compatible Cloud Storage solution like S3 or R2.

import { S3Client } from '@aws-sdk/client-s3'
import { S3LikeIndexStore } from '@hash-stream/index/store/s3-like'

const client = new S3Client({
  // TODO: setup client options according to target
})
const bucketName = 'index-store'
const indexStore = new S3LikeIndexStore({
  bucketName,
  client,
})

Cloudflare worker bucket like

Stores records using a Cloudflare worker bucket reference.

import { CloudflareWorkerBucketIndexStore } from '@hash-stream/index/store/s3-like'

// Worker bindings R2 Bucket
const bucket = // TODO

const packStore = new CloudflareWorkerBucketIndexStore({
  bucket
})

Custom implementations

Given hash-stream provides a set of building blocks to run a HTTP server for content-addressable data, anyone is welcome to write new implementations for each of the building blocks based on their specifications. This library also exports a test suite to verify if the implementation will be comaptible with the remaining pieces. Here is how you can use it:

import { test } from '@hash-stream/index/test'

// Run tests for a reader implementation
await test.reader(readerName, () => getNewReaderImplementation())

// Run tests for a store implementation
await test.store(readerName, () => getNewStoreImplementation())

Using a Custom Store

Other implementations of a Store may be implemented according to the storage backend intended. The Pack Store must implement the IndexStore interface, or separately a IndexStoreReader and a IndexStoreWriter. A store must define the following methods:

export interface IndexStore extends IndexStoreReader, IndexStoreWriter {}

export interface IndexStoreWriter {
  add(entries: AsyncIterable<IndexRecord>): Promise<void>
}

export interface IndexStoreReader {
  get(hash: MultihashDigest): AsyncIterable<IndexRecord>
}

// An index record has the necessary metadata to find the location
// where the bytes behind a given `MultihashDigest` rest.
export interface IndexRecord {
  // MultihashDigest identifiying the record
  multihash: MultihashDigest
  // Type of the record
  type: IndexRecordType
  // hash digest of the location or Path
  location: MultihashDigest
  // length of the data
  length?: number
  // offset of the data in the location byte stream
  offset?: number
  // associated records
  subRecords: Array<IndexRecord>
}

Relevant Specifications

Contributing

Feel free to join in. All welcome. Please open an issue!

License

Dual-licensed under MIT + Apache 2.0