@cio/transformer

Easily use a Transform pipeline to handle communication.

Usage no npm install needed!

<script type="module">
  import cioTransformer from 'https://cdn.skypack.dev/@cio/transformer';
</script>

README

@cio/transformer

Build Status Dependency Status npm version

Easily use a Transform pipeline to handle communication.

Install

npm install @cio/transformer --save

Usage

Uses specified transforms in a pipeline from socket input back to socket output.

Accepts a single transform or an array of transforms.

Accepts the actual transform instance, a function to build the transform, or a string it can provide to require() to get a builder function.

Note: A server should (very likely) use builder functions to make a new transform for each connection.

What to do:

  1. add the listener to the cio instance
  2. provide the transformer option property to cio.client() or cio.server()
  3. specify one of the allowed types as its value, or, an array of values
  4. for options to builder functions put the above info in the transform sub-property and builder options as sibling keys to it.
// get the `cio` module's builder function and build one
var buildCio = require('cio')
  , cio = buildCio();

// provide the module name to load it for the specific type of socket
cio.onClient('@cio/transformer');
cio.onServerClient('@cio/transformer');

// OR: provide the function
var fn = require('@cio/transformer');
cio.onClient(fn);
cio.onServerClient(fn);


// shows 3 different ways to provide a transform to use.
// shows specifying a single transform and an array of them
var transformModule = 'some-module'
  , buildTransform = require(transformModule)
  , someTransform = buildTransform()
  , optionsAsInstance = { transformer: someTransform }
  , optionsAsBuilder = { transformer: buildTransform }
  , optionsAsString = { transformer: transformModule }
  , optionsWithMultiple = {
      // can mix any of the types
      transformer: [
        someTransform    // uses instance (not good for server)
        buildTransform,  // calls buildTransform()
        transformModule, // does a require(), then calls function
      ]
  };

// then create a client. these all produce the same thing:
var client = cio.client(optionsAsInstance)
  , client = cio.client(optionsAsBuilder)
  , client = cio.client(optionsAsString);
// does:
//   client.pipe(someTransform).pipe(client)

// the string and function type will be used to get a new transform
// and then all three are piped in sequence.
var client = cio.client(optionsWithMultiple);
// final result is:
//   client.pipe(someTransform).pipe(someTransform2).pipe(someTransform3).pipe(client)

Usage: Provide Options for Builder Functions

It's possible to put options in the call to cio.client() or cio.server() which will be provided to the builder functions creating the transforms for you.

To do so, move the usual options into a sub-property transform and the top transformer object will be provided to the builder functions.

var usualOptions = { transformer: someBuilderFunction }
  , newOptions   = {
    transformer: {
      transform: someBuilderFunction,
      some: 'other option values'
    }
  };

// for the `usualOptions` the `someBuilderFunction` will receive itself as the options.

// for the `newOptions` it will receive the `transformer` key's value which has
// the `some` key, as well as the `transform` key.

Build Transform

There are multiple ways to build a Transform.

  1. Use the standard methods described in Node's stream documentation (Note, this link is for the latest Node, be sure to check for the version you're using).
  2. Use a helper module such as through or through2
  3. Use a builder module transforming (Note, I made this module...)
// standard Node way (newer versions):
// Note: this way requires splitting incoming string on newlines via another
//       transform piped to this one, or, done manually in your function.
var Transform = require('stream').Transform;
function builder1(options) {
  return new Transform({
    transform: function (data, encoding, next) {
      var string = data.toString('utf8')
        , object = null;

      try {
        object = JSON.parse(string);
        this.push(object);
        next();
      } catch(error) {
        next({
          error: 'Unable to parse string with JSON.parse()'
          Error: error
        });
      }
    }
  });
}

// the through2 way:
// Note: this way requires splitting incoming string on newlines via another
//       transform piped to this one, or, done manually in your function.
var thru = require('through2')
function builder2(options) {
  return thru(function (data, encoding, next) {
    // same processing as above in builder1.
  });
}

// the transforming way:
// Note: (module is a function which accepts build options)
var transform = require('transforming')()
var builder3 = function(options) {
  // simple case of transforming a newline delimited string into an object
  return transform.splitStringToObject(JSON.parse);
  // OR: long form without making use of defaults or convenience functions:
  return transform.split('\n').string('utf8').toObject(JSON.parse);
}

MIT License