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 🙏

© 2024 – Pkg Stats / Ryan Hefner

hyperlog-index

v5.2.2

Published

forking indexes for hyperlog

Downloads

46

Readme

hyperlog-index

Forking indexes for hyperlog

Built on the map/reduce pattern; hyperlog-index will call a map function on every hyperlog insert, building the index incrementally.

example

forking key/value store

Using hyperlog-index, we can easily build a key/value store backed to a hyperlog that implements a multi-value register conflict strategy:

var level = require('level')
var indexer = require('hyperlog-index')
var hyperlog = require('hyperlog')
var sub = require('subleveldown')
var mkdirp = require('mkdirp')

var minimist = require('minimist')
var argv = minimist(process.argv.slice(2), {
  default: { d: '/tmp/kv.db' }
})
mkdirp.sync(argv.d)

var hdb = level(argv.d + '/h')
var idb = level(argv.d + '/i')
var log = hyperlog(hdb, { valueEncoding: 'json' })
var db = sub(idb, 'x', { valueEncoding: 'json' })

var dex = indexer({
  log: log,
  db: sub(idb, 'i'),
  map: function (row, next) {
    // This method reduces our new state. In this example, db is used for the state.
    db.get(row.value.k, function (err, doc) {
      if (!doc) doc = {}
      row.links.forEach(function (link) {
        delete doc[link]
      })
      doc[row.key] = row.value.v
      db.put(row.value.k, doc, next)
    })
  }
})

if (argv._[0] === 'get') {
  dex.ready(function () {
    db.get(argv._[1], function (err, values) {
      if (err) console.error(err)
      else console.log(values)
    })
  })
} else if (argv._[0] === 'put') {
  // Structure `doc` as expected by `map` above
  var doc = { k: argv._[1], v: argv._[2] }
  dex.ready(function () {
    db.get(doc.k, function (err, values) {
      // Link the new entry to the "parents", from the current index, if any
      log.add(Object.keys(values || {}), doc, function (err, node) {
        if (err) console.error(err)
      })
    })
  })
} else if (argv._[0] === 'sync') {
  var r = log.replicate()
  process.stdin.pipe(r).pipe(process.stdout)
  r.on('end', function () { process.stdin.pause() })
}

Each key maps to an object of hashes to values:

$ node kv.js -d /tmp/db1 put A beep
$ node kv.js -d /tmp/db1 put A boop
$ node kv.js -d /tmp/db1 get A
{ '06e4130fc5f2392cb8bdb065d18eaa523d716f2c61b4877853340a5cc727fb42': 'boop' }

Meanwhile, a second database may have additional edits:

$ node kv.js -d /tmp/db2 put A whatever
$ node kv.js -d /tmp/db2 put B hey

When these two databases are merged together, the key at A has two values:

$ dupsh 'node kv.js -d /tmp/db1 sync' 'node kv.js -d /tmp/db2 sync'
$ node kv.js -d /tmp/db1 get A
{ '06e4130fc5f2392cb8bdb065d18eaa523d716f2c61b4877853340a5cc727fb42': 'boop',
  cba756b45e279ae5c3f3ebc8cfe0d50e1f2205e37a4443ce9e0e5a41491c234c: 'whatever' }

The B key has only a single element:

$ node kv.js -d /tmp/db1 get B
{ '53a374617fb8839b6f19646d6658188a4fc08d19f35c084dab835847532a3468': 'hey' }

This is because put does the linking of new nodes to old ones, which is not done in merge. New updates that link at both existing keys will merge into a single key:

$ node kv.js -d /tmp/db1 put A whatboop
$ node kv.js -d /tmp/db1 get A
{ '85915730b3e7a4f715057e74af79b564a5be2ec14d334d344cb84d1544ec6107': 'whatboop' }

and these merges can be communicated over replication:

$ dupsh 'node kv.js -d /tmp/db1 sync' 'node kv.js -d /tmp/db2 sync'
$ node kv.js -d /tmp/db2 get A
{ '85915730b3e7a4f715057e74af79b564a5be2ec14d334d344cb84d1544ec6107': 'whatboop' }

And the index can be destroyed (and recalculated) at any time:

$ rm -rf /tmp/db1/i
$ node kv.js -d /tmp/db1 get A
{ '85915730b3e7a4f715057e74af79b564a5be2ec14d334d344cb84d1544ec6107': 'whatboop' }

This is a useful strategy when you need to update the code in your indexes.

Note: If you run the included example, the value is assumed to be a json object. The command line put format will be more like this:

$ node example/kv.js -d /tmp/db1 put A '{"baap":"boop"}'

Note: If you are primarily interested in a key/value index, like in this example - check out hyperkv

api

var indexer = require('hyperlog-index')

var dex = indexer(opts)

Create a new hyperlog index instance dex from:

  • opts.log - a hyperlog instance (required)
  • opts.db - a level instance (required)
  • opts.map - an indexing function function (row, next) {}

You can have as many indexes as you like on the same log, just create more dex instances on sublevels.

opts.map(row, next)

The indexing function fn runs for each row. The indexing function should write its computed indexes to durable storage and call next(err) when it is finished.

dex.ready(fn)

Registers the callback fn() to fire when the indexes have "caught up" to the latest known change in the hyperlog. The fn() function fires exactly once. You may call dex.ready() multiple times with different functions.

dex.pause()

Pause calculating the indexes. dex.ready() will not fire until the indexes have been resumed.

dex.resume()

Resume calculation of the indexes after dex.pause().

dex.on('error', function (err) {})

If the underlying system generates an error, you can catch it here.

install

With npm do:

npm install hyperlog-index

license

MIT