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

couch-party

v1.0.0-alpha.2

Published

A set of functions for building Couch/PouchDB driven community apps.

Readme

Couch Party

ALPHA / WIP

A set of functions for building Couch/PouchDB driven multi-user apps. Currently does basic login, registration, password reset and user profile syncing.

npm install couch-party

Party time

//Login
var baseCouchURL = 'http://admin:admin@localhost:5984/myProject'
var login = {
    nickOrEmail: "Sarah",
    password: 'w00t'
}
couchParty.login(baseCouchURL, login, function(err, doc) {
    if(err) console.log('You were not invited!')
    else console.log('Welcome to the party yo!')
})
//Register
var form = {
    nickname: 'Sarah',
    email : '[email protected]',
    password : 'w00t'
}
couchParty.register(baseCouchURL, form, function(err, couchRes) {
    if(err) console.log(err)
    else console.log('User created with doc._id of: ' couchRes.id)
})

Sync time

There is also a function to sync client-side changes with help from PouchDB:

//server.js
couchParty.syncEverybody(baseCouchURL)

Each user gets their own database. In addition, a single 'mother' database is used for authentication. syncEverybody function keeps changes from the individual user databases to the mother.

On client side, now you can just save stuff to a browser PouchDB and let it's sync feature take care of the rest.

//app.js (browser)
//First, get the user doc by logging in:
var userDoc
$.post('http://localhost:4500/login', form, function(userDoc) {
//^ Assuming your server app is listening on 4500, and calls "couchParty.login" with the route above.
    initPouch(userDoc)
}, 'json')

//Create a database based on the userDoc we got from server:
function initPouch(userDoc) {
    var db = new PouchDB('myproject_user')
    db.post(userDoc, function(err, res) {
        //Now perform a live sync:
        db.sync('http://admin:admin@localhost:5984/' + userDoc.db_name, { live: true, retry: true })
          .on('change', function(info) {
            console.log('Now this is a party!')
          })
    })
}

Lost keys

To reset a password, first call couchParty.resetToken to generate and 'seed' the appropriate user with a secret token (then an implied step where you email the user said token) and then call couchParty.resetPass with the token and new password.

There is no built-in email mecahnism, you can send the email however you like. For example with nodemailer as in the example below.

//Post route from a page that collects an email address for the purpose of password reset...
//(app is an express app)
app.post('/api/reset', function(req, res) {
  console.log('A visitor has requested to reset password for: ' + req.body.email)
  //Lookup the username based on the email provided...
  couchParty.resetToken(baseCouchURL, req.body.email, function(err, token) {
    if(err) return res.send({ok:false, msg: err})  
    //the link contains a secret token
    //the secret token is applied to the userDoc in the user database
    //Now you can send the email however you like:
    var email = {
      to: req.body.email,
      subject:`Password Reset`,
      from : '[email protected]',
      html: `<p>Hello there,</p>
      <p>There has been a request to reset your password.  If you wish to proceed, click the link below: </p>
      <p><a href="http://worlddomination.com/reset-confirm/${token}">www.worlddomination.com/reset-confirm/token</a></p>
      If for any reason you did not request a password reset please reply back to inform [email protected]</p>
      `
    }
    //Send the mail:
    //(nodemailer object initialized already)
    nodemailer.sendMail(email, function(err, nodemailerRes){
      if(err) return console.log(err.message)
      var resultMsg = 'An email with further instruction has been sent to : ' + req.body.email
      res.send({ok:true, msg: resultMsg })
    })
  })
})

//Post route that contains the token; this is hit after the user lands on the URL
//provided in the reset email.
app.post('/api/reset/:secretToken', function(req, res) {
  couchParty.resetPass(baseCouchURL, req.params.secretToken, req.body.new_password, function(err) {
    if(err) return res.send({ok:false, msg: err })
    //If there was no error, the password was reset successfully:
    res.send({ok:true, msg: 'Password was reset successfully.'})
  })
})

API

register
couchParty.register(baseURL, login, callback)
Registers a new user, accepting either a username/email or both and a password. The password is hashed before saving into the database.

  couchParty.register('http://localhost:5984/wedding_', { email:  '[email protected]', password : '6969booyeah' }, (err, signupToken) => {
    //signupToken = { signup_token : 'ba1b581b3318ff102bca0fc69ae688' }
    //now you can send an email to the user with this token for verification
  })

verify
couchParty.verify(baseURL, signupToken, callback)
Finds the user who matches the supplied token and marks that user's doc as { verified : true } Returns an err if no match (or db problem) or the updated user doc if successful.

  couchParty.verify('http://localhost:5984/wedding_', { token : 'ba1b581b3318ff10' }, (err, userDoc) => {
    //userDoc =  { email:  '[email protected]', password : 'afsadfaasdlkj33', verified : true }
  })

login couchParty.login(baseURL, loginObj, callback)
Finds the user who matches the supplied token and marks that user's doc as { verified : true } Returns an err if no match (or db problem) or the updated user doc if successful.

  couchParty.verify('http://localhost:5984/wedding_', { token : 'ba1b581b3318ff10' }, (err, userDoc) => {
    //userDoc =  { email:  '[email protected]', password : 'afsadfaasdlkj33', verified : true }
  })