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

graft

v0.3.1

Published

Full-Stack JavaScript Through Microservices

Downloads

69

Readme

Warning: This library is under active development, and should not be considered production ready

Graft

The Graft project explores what the web could become, if we extended microservice architectures into the client.

  • Motivation
  • API
  • About LibChan
  • Contributors
  • License

Interested in Graft and jsChan? Watch @mcollina presentation at NodeConf.eu 2014, "Full Stack Through Microservices"

Motivation

When you graft something, it involves joining together parts to create a new whole. One that is hopefully more adaptable, resilient and ultimately interesting.

"Instead of pretending everything is a local function even over the network ..., what if we did it the other way around? Pretend your components are communicating over a network even when they aren't?" -- Docker's Solomon Hykes on LibChan - [link]

Explore our concepts and influences


Our Projects

  • graft: the library that ties everything together.
  • jschan: our 'standard carrier'. A port of libchan.
  • aetherboard: our 'hello world' demo. A collaborative whiteboard.

Our Process

  • discover how to connect tools through microservices.
  • explore the tools that are already available.
  • adapt those that could be integrated.
  • innovate to build those that don't exist yet.

Our Principles

  • favor small tools that serve only one purpose, but do so well.
  • eschew state, because it only leads to trouble.
  • focus on javascript, because it is universal.
  • evaluate and document, not prescribe.
  • educate.

Our Goals

  • be the premier javascript implementation of libchan.
  • be completely supported for node.js as soon as possible.
  • use Node.JS streams to replicate the semantics of Go Channels.
  • be functional and usable on the browser as we test the waters.
  • use virtual stream objects to provide an api similar to Gulp.
  • attempt control flow abstractions similar to HighlandJS.
  • experiment, document and learn.

API

  • graft()
  • graft.ReadChannel()
  • graft.WriteChanel()
  • graft.branch()
  • graft.where()
  • Request Interface
  • spdy.client()
  • spdy.server()
  • ws.client()
  • ws.server()

graft()

The main object of this library. A Graft instance is a Transform stream with objectMode: true. The objects on the output of a Graft instance are Requests. On the input side, you can write just normal JS objects, and everything else you can write to a jsChan channel. These objects will be automatically wrapped up in a Request.

Internally, each Graft instance is backed by jschan.memorySession()`.

In order to process the requests, you can just:

var graft = require('graft')();
var through = require('through2');

graft.pipe(through.obj(function(msg, enc, cb) {
  console.log(msg); // prints { hello: 'world' }
  // process your request
  cb();
}));

graft.write({ hello: 'world' });

graft.ReadChannel()

Returns a nested read channel, this channel will wait for data from the other party.

graft.WriteChannel()

Returns a nested write channel, this channel will buffer data up until is received by the other party.

graft.branch(function(req), stream)

Passes the request to the first argument, and if that returns a truthy value, it calls write(req) on the associated stream. It respect backpressure.

graft.where(obj, stream)

Shortcut for the most common usage of graft.branch(), it allows to rewrite:

graft.branch(function(msg) {
  return msg.hello === 'world'
}, stream)

into:

graft.where({ hello: 'world' }, stream)

Request Interface

Each Graft request is the first message sent on a top-level channel, and it is composed of:

  • all the properties of the message
  • _channel, the associated channel
  • _session, the associated session

Each request will have its own channel, but the session is generic for every client.

The _channel and _session properties will not be enumerable.


spdy.client()

Creates a new spdy client to pipe to:

var graft = require('graft')();
var spdy = require('graft/spdy');

graft.pipe(spdy.client({ port: 12345 }));

graft.write({ hello: 'world' });

spdy.server()

Creates a new spdy server that you can pipe to a graft instance:

var graft = require('graft')();
var spdy = require('graft/spdy');
var through = require('through2');

spdy
  .server({ port: 12345 })
  .pipe(graft)
  .pipe(through.obj(function(msg, enc, cb) {
    console.log(msg); // prints { hello: 'world' }
    // process your request
    cb();
  }));

ws.client()

Creates a new ws client to pipe to:

var graft = require('graft')();
var ws = require('graft/ws');

graft.pipe(ws.client({ port: 12345 }));

graft.write({ hello: 'world' });

It works even from a Browser, using WebPack or Browserify.


ws.server()

Creates a new ws server that you can pipe to a graft instance:

var graft = require('graft')();
var ws = require('graft/ws');
var through = require('through2');

ws
  .server({ port: 12345 })
  .pipe(graft)
  .pipe(through.obj(function(msg, enc, cb) {
    console.log(msg); // prints { hello: 'world' }
    // process your request
    cb();
  }));

You can even pass an existing http server that will be hooked up, like so:

var graft   = require('graft');
var ws      = require('graft/ws');
var http    = require('http');
var server  = http.createServer();

ws
  .server({ server: server })
  .pipe(graft())

About LibChan

Libchan is the connective tissue to all our endeavours. It is a microservices library announced by the Docker project, and it is going to form the basis of all of the tools they build in the future.

It's most unique characteristic is that it replicates the semantics of go channels across network connections, while allowing for nested channels to be transferred in messages. This would let you to do things like attach a reference to a remote file on an HTTP response, that could be opened on the remote end for reading or writing.

The protocol uses SPDY as it's default transport with MSGPACK as it's default serialization format. Both are able to be switched out, with http1+websockets and protobuf fallbacks planned.

While the RequestResponse pattern is the primary focus, Asynchronous Message Passing is still possible, due to the low level nature of the protocol.

Contributors

Adrian Rossouw

Peter Elgers

Matteo Collina

License

MIT