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

dg-level-userdb

v2.0.0

Published

LevelDB-backed user database for things like web applications

Downloads

5

Readme

level-userdb

Build Status

LevelDB-backed user database for Node.js. This does standard web/mobile app account storage:

  • Users are stored by email address
  • Passwords are hashed with bcrypt
  • Created and modified timestamps
  • Store arbitrary JSON metadata along with each account
  • Compatible with multilevel for network access
  • Multi-step write-after-read operations (such as changeEmail, changePassword and modifyUser) are run serially to avoid race conditions.

Tools & libraries:

Installation

npm install level-userdb

Quickstart


var db = require('level-userdb')()

// Adding a user
db.addUser('[email protected]', 'supersecret',
  {some:{nested:"metadata", associatedWithUser:true}, foo:[1,2,3]},
  function(err) {
    if (err) return console.log("error adding user: %s", err)
    console.log("ok")
  }
)

// Checking a password for an account
db.checkPassword('[email protected]', 'supersecret', function(err, user) {
  if (err) return console.log("invalid password: %s", err)
  console.log("password ok")
})


// Using with sublevel

var LevelUp = require("level");
var Sublevel = require("level-sublevel");
var db = Sublevel(LevelUp("./db"));

//you have to specify key- and valueEncoding
var users = db.sublevel("users", { keyEncoding: 'binary', valueEncoding: "json" })
var levelUserDb = require("level-userdb")(users);

CLI tool

npm install -g level-userdb-cli

Learn more about the CLI tool: level-userdb-cli

Tests

Test suite can be run via npm test. It requires Chai and Mocha.

Benchmark / Performance / Stress-test

level-userdb-bench is an attempt at a somewhat-useful benchmark or stress test. It attempts to create a mixed, concurrent workload of reads and writes. Feel free to look at the code and poke holes in how it is written. I don't claim it is a perfect or even especially-meaningful performance test. Note that it disables bcrypt on passwords for all writes.

Here are some results from a 2013 11" MBA (SSD, 1.7Ghz Haswell i7) on OS X 10.8.4:

Starting benchmark with concurrency level 20
reads: 3262.1/s changePasswords: 3312.4/s inserts: 3291.7/s modifies: 3292.2/s total ops: 13158.4/s errs: 0/s
reads: 3179.3/s changePasswords: 3161.2/s inserts: 3220.9/s modifies: 3193.1/s total ops: 12754.5/s errs: 0/s
reads: 3067.3/s changePasswords: 3092.8/s inserts: 3079.2/s modifies: 3079/s total ops: 12318.3/s errs: 0/s
reads: 2918.1/s changePasswords: 2923.6/s inserts: 2949.7/s modifies: 2960/s total ops: 11751.4/s errs: 0/s
reads: 2880/s changePasswords: 2897.7/s inserts: 2873.6/s modifies: 2879.4/s total ops: 11530.7/s errs: 0/s
reads: 2758.7/s changePasswords: 2797.4/s inserts: 2777.3/s modifies: 2785.2/s total ops: 11118.6/s errs: 0/s
reads: 2688.6/s changePasswords: 2711/s inserts: 2693/s modifies: 2685.3/s total ops: 10777.9/s errs: 0/s
reads: 2586/s changePasswords: 2586.6/s inserts: 2586.4/s modifies: 2615.4/s total ops: 10374.4/s errs: 0/s
benchmark completed
total reads 249005 changePasswords: 250234 inserts: 250197 modifies: 250564 ops: 1000000 errs: 0

Database

level-userdb uses LevelUP as a database for users. The current schema is very simple: Users are keyed by email address and converted to a JavaScript array with first item "user:". Key encoding is set to Bytewise. Value encoding is set to JSON, in other words values are transparently marshalled to/from native JavaScript objects by LevelUP itself.

User values are JSON objects with the properties:

  • email: Email address of user account
  • password: Hashed password string (bcrypt)
  • createdTimestamp: User creation timestamp. This has properties:
    • unixtime: milliseconds since Jan 1st 1970. Used for creating JavaScript Date objects.
    • hrtime: high-resolution time data from process.hrtime(). This can be used to avoid race conditions as unixtime is not high-resoltion enough.
  • createdDate: User created timestamp. JavaScript Date() object already marshalled for convenience.
  • modifiedTimestamp: User last modified timestamp. This has properties:
    • unixtime: milliseconds since Jan 1st 1970. Used for creating JavaScript Date objects.
    • hrtime: high-resolution time data from process.hrtime(). This can be used to avoid race conditions as unixtime is not high-resoltion enough.
  • modifiedDate: User last modified timestamp. JavaScript Date() object already marshalled for convenience.
  • data: Property under which arbitrary JSON data can be stored

Database API

Require the level-userdb module and instantiate:


var db = require('level-userdb')('./mydatabase')

LevelUP plugins

You can also pass an existing LevelUP compatible object. This enables you to take advantage of the many LevelUP plugins and modules.

For example level-userdb-server takes advantage of this to make level-userdb accessible over the network with multilevel.

var db = require('level-userdb')(myLevelUpDB)

The db object has the following methods:

findUser

findUser(email, cb)

Returns the user object if found,

CB should be a signature of form:

function(err, user)

If account is not found, err is set and user is undefined.

addUser

addUser(email, password, data, cb)

Adds a new user to the database. Passwords are hashed with bcrypt.

data is an optional parameter for non-indexed data. It defaults to an empty object ({}).

checkPassword

checkPassword(email, password, cb)

Checks whether the supplied password is correct for the given account. Only bcrypt passwords are stored in the database.

CB should be a signature of form:

function(err, user)

If account is found and the password is a match, user parameter will contain user object. Otherwise, err will be set and user parameter will be false.

changeEmail

changeEmail(email, newEmail, cb)

Update the email address on an account.

deleteUser

deleteUser(email, cb)

Delete a user object by email address.

modifyUser

modifyUser(email, data, cb)

Update the data property for the given email address.

createUserStream

createUserStream(opts)

Returns an object stream of users. This accepts the same options object as LevelUP's createReadStream() so can be used for range queries etc.