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

mithink

v1.1.0

Published

meteor-like rethinkdb integrations for socket.io using thinky with support for mithril.js out of the box on the client-side

Downloads

2

Readme

Mithink Build Status

npm install mithink --save

A plug-n-play module which aims for Meteor.js like capabilities without the overhead for transparently syncing a RethinkDB instance across clients using Socket.IO and Mithril.js on the client-side out of the box, but it's easy enough to roll your own adapter for Angular/Ember/Vue/whatever the hot framework of the week is.

Under The Hood

server

On the server mithink uses the excellent thinky module for interaction with RethinkDB. It should always have the same API with a few additions to add functionality, rather than replicating it. We are using socket.io rooms to separate table events from the global event space.

Example usage:


rethinkdb = require("mithink")(config.dev)
io        = require('socket.io')

# set up the event bus
rethinkdb.bus(io)

# this returns an extended version of the thinky Model 
Thing = rethinkdb.createModel "Thing", {
  name   : rethinkdb.type.string()
  id     : rethinkdb.type.number()
  active : rethinkdb.type.boolean()
}

# add access control
Thing.guard
  load: (socket)->
    return true if socket.session.authenticated
    return false

  update: (socket)->
    return true if socket.session.isAdmin
    return false

  mapreduce: (socket)->
    return true is socket.session.whatever
    return false

  # Async access control transparently handles Promises
  connection: (socket)->
    return new Promise (resolve, reject)->
      Dosomestuff().then (passed)->
        if passed
          return resolve(true)
        
        # if you want to override the default error message 
        # for this check in your logs because it is special
        reject message: "you failed the Dosomestuff check"

# add or override actions
Thing.registerActions
  mapreduce: (data)->
    # a special query
    @socket.emit "reduction", fancyData

  # override default action
  load: (data)->
    # context includes:
    # @model  { the model of the current context }
    # @socket { the socket that emitted the event }

client

On the client mithink caches the synced data in memory after connection and loading using socket.io in the background. You must include socket.io in your webapp, as mithink makes no assumptions about the version you want to use or how you want to deliver it to the client.

example usage:

# connect to socket.io
r = require('mithink')()

# for no conflict & sharing the same rendering engine  
# otherwise mithink cannot redraw diff changes from the server in the background.  
# you can set this to your own redrawing function if needed
r.redraw = m.redraw

# what to do when an "http_error" event occurs in the background
r.errorHandler = (err)->
  m.route "/error"

# a normal mithril controller/view module
Things =
  controller: ->
    # ask mithink to lazy load the Things table
    @list   = r.table("Things").load()

    @update = (evt)->
      r.table("Things").update @set('name', evt.target.value)
    return @

  view: (ctrl)->
    return m 'h1', 'loading...' if ctrl.list.isLoading()

    m 'ol.things', ctrl.list.map (thing)->
      m 'li',
        m 'input', onchange: ctrl.update.bind(thing), value: thing.get('name')


m.mount(document.getElementById("things"), Things)

custom events & other random examples

r.require('mithink')()
r.redraw = m.redraw

# register a global default event handler

r.adapter.Table.handler.mapreduce = (data)->
  # do your fancy stuff

invoices = r.table('Invoices')

invoices.on "pivot", (data)->
  r.table("Invoices:pivot").reset(data).finishLoading()
  r.redraw()

# create a virtual table on the client
# it will be initalized in a loading state which you must manually reset
pivot = r.table("Invoices:pivot")

# emit the pivot event to the server
r.table('Invoices').emit('pivot')

# you can then use the r.table("Invoices:pivot") table in your views

Client-side Inbound Events Catalog

load

populdate a client-side table from RethinkDB. You can add params to it which are passed to a filter

sync

When an update is attempted, but failed due to any reason, the table on the client side resyncs the document that failed to update back to the originally value and emits an http_error

destroy

Whenever a document is deleted from RethinkDB, this event is received and updates the client-side table replicate if the document exists in the table replicate.

upsert

Whenever a document was updated or created on the server. It transparently adds it to the r.table(tableName) in the background and triggers a redraw (if there are no diffs in the HTML this is a no-op).

http_error

Anytime something unexpected occurs, from a failed permission check to a failed validation check. The event data returned is structured like this:

{
  code    : code
  message : err.message
  raw     : err
  data    : data
  table   : "Things"
  action  : "action"
}

Server-side Inbound Events Catalog

The defaults are as follows:

load

create

update

destroy

sync

http_error

A variety of situations can cause an http_error event to be emitted from the server, a few examples are anytime thinky catches an error, or a permission check is not passed.

Roadmap

v1.1 (TTL: < 3 Weeks)
  • Documentation
  • Test coverage
  • Wercker CI integration
  • delete event will be migrated to the destroy event

I mistakenly published the first version using the delete keyword in several places because of how easy it is to use in Coffeescript, but I would like to make it as easy to use to ES6/Vanilla JS as possible, so in the next release we will be migrating from that.