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

@plotdb/datahub

v0.5.9

Published

access scoped data via piped operational transformation

Downloads

51

Readme

@plotdb/datahub

Access scoped data via piped operational transformation.

Installation

npm install @plotdb/datahub

Usage

after including datahub.bundle.min.js:

# this is our data source.
src = new datahub.src do
  ops-out: (ops) -> # update data src by incoming ops
  get: -> # return complete data. raw data is returned, users should make their own copy if to use.

# this is our view controller
des = new datahub.des do
  ops-in (ops): -> # update ui / widget

# data through pipe, scoped under "my-view"
view-hub = new datahub {scope: ["my-view"]}
# ... from srchub / through view-hub / to deshub
src.pipe view-hub .pipe des

# notify all users (deshub) about data changed
src.ops-in [... /* ops */ ...]

# update data source (srchub)
des.ops-out [... /* ops */ ...]

Memhub, Userhub

Datahub also provides auxiliary hubs for quick testing and evaluation.

  • memhub - data source hub. store data in memory.
  • usrhub - simple destination hub. constructor options:
    • render(ops): called when there are updates from data source.

A sample usage of memhub and usrhub as follows:

mhub = new datahub.mem!
uhub = new datahub.usr {render: -> console.log('ok'); }
mhub.pipe uhub
document.querySelector('textarea').addEventListener \input, ->
  uhub.ops-out [
    { p: ['str',0], si: @value[@value.length - 1] }
  ]

Wrap constructor

Instead of userhub, you can use datahub.as to wrap your constructor to support hub mechanism directly with your own class:

someClass = datahub.as (opt = {}) -> @
someClass.prototype <<< { ... }

You can pipe source hub to the constructed hub object:

hub = new myHub();
src.pipe(hub);

Wrapped hub only provides following methods:

  • state()
  • on(name, cb)
  • fire(name, ...args)
  • ops-out(ops)
  • get()

And following member variables to use:

  • hub: the actual hub object used to accept source data.
  • data: data object from source.

As a wrapped hub user, you should do the following:

  • implement ops-in function to render / update your application. note:
    • ops has been applied to data member before your ops-in is called.
    • however any data kept locally should still be updated based on ops.
  • watch open / close event or use state method to track data stream status.

Following is a sample wrapped hub:

form = datahub.as (o = {}) ->
  # udate based on a input element change
  o.node.addEventListener \input, (evt = {}) ~> @update evt.target.value 
  # keep a local _data to diff original data for ops
  @on \open, ~> @_data = JSON.parse(JSON.stringify(@data)); @render!
  @ <<< o{name}
form.prototype <<<
  # re-render on every ops-in
  ops-in: (ops) ->
    json0.type.apply @_data, ops
    @render!
  render: -> console.log @_data
  update: (v) ->
    if @state! == \closed => return
    @_data[@name] = v
    @ops-out json0.diff(@data, @_data)

For a live, working example, please check web/src/pug/as.pug.

Sharehub

Sharehub provides a simple interface and implementation reference for adopting ShareDB with data hub to keep edited data in database:

uhub = new datahub.usr!
shub = new sharehub({
  id: 'my-sharedb-doc-id'
  create: -> {} # init obj if doc not found.
})
shub.init!
  .then -> shub.pipe uhub

Sharehub is in a standalone JS file. include sharehub.js / sharehub.min.js / sharehub.bundle.min.js if you want to use it.

Constructor options:

  • id: id of the sharedb doc to connect. optional
  • collection: collection of the sharedb collection to connect. optional, default doc if omitted.
  • initConnect: default true. if true, auto connect to sharedb if id is given.
  • create(): empty object creator function. should return an object for initial value.
    • when omitted, a creator function returing an empty object is used.
  • watch(ops, src): watcher function. optional
  • ews: @plotdb/ews instance to use. required.

APIs:

  • connect(opt): connect to sharedb. return Promise, resolved when connected.
    • opt is either:
      • omitted (undefined): connect() will use stored id and collection to (re)connect.
      • a string for id of the sharedb doc to connect. In this case, collection will be set to doc.
      • an object with fields:
        • id: sharedb id. use stored id if omitted. this id will be stored for future use. (e.g., auto-reconnect)
        • collection: doc if omitted.
        • force: default true. when true, force to reconnect even if id / collection is the same.
          • when opt is a string or omitted, force will also be true.
    • if id / collection are provided in opt, they will be stored internal for future use.
  • disconnect(): disconnect current doc from sharedb. return Promise, resolved when disconnected.
    • this will be automatically called when internal sdb-client is closed.
  • config(opt): update configuration. opt has following fields:
    • id: sharedb id.
    • collection: doc if omitted.

Additionally, sharehub fire following events

  • open: fired when a connect is successfully done.
  • close: fired when disconnect is called.
  • error: fired when internal sdb-client object fires error events.

Scoping

Passing scope option ( an array of strings / numbers ) into datahub constructor to filter incoming op and data based on the specified scope. For example, assume our data source keeps data in datasrc variable, then following hub:

new hub({scope: ["users", "deleted"]})

will only pass ops that affect object in datasrc.users.deleted. Furthermore, data get from this hub will only be the subtree in datasrc.users.deleted.

You can pipe data source to a hub that is scoped, and pipe this scoped hub to the destination hubs that use the same subtree.

Object API

  • ops-in(ops): send ops from this hub to subscribers. ( inward / down to client )
  • ops-out(ops): send ops from this hub to src. ( outward / up to server )
  • as-src(o): set this hub as a source hub (provide data and handle outward request).
    • fields of o:
      • get(): a function returning a full snapshot of data.
      • ops-out(ops): a function to handle outward ops.
    • a source hub is responsible to call ops-in(ops) when there are data changes from source (inward ops)
  • as-des(o): set this hub as destination hub ( handle inward events by such as rendering )
    • fields of o:
      • ops-in(ops): a function to handle inward ops.
    • a destination hub is responsible to call ops-out(ops) when there are data changes to source (outward ops)
  • get(): return a snapshot of source data
  • pipe(hub): pipe down events to hub.
  • addon(ops): prepend ops to create node for ops accessing non-existed path
  • cut(hub): remove hub from current object's subscriber list.
  • state(s): change state. s can be either opened or closed.
    • state propagates automatically. Should only be used by source hub.
    • des hub should always call get to retrieve a new object and reinitialize if needed after each open event.

Class API

  • as(constructor): wrap constructor as a hub that can be piped.
    • constructor options depends on how constructor is implemented, with following additional fields:
      • scope: the scope used by hub, as defined above.

License

MIT