Clone a transform stream in NodeJS

I'm trying to reuse a couple of transform streams (gulp-like, ie. concat() or uglify()) across several readable streams. I only have access to the created instances and not the original subclasses.

It does not work out of the box, I get Error: stream.push() after EOF when I pipe at lease two distinct readable streams into my transforms. Somehow the events do appear to leak from one stream to the other.

I've tried to setup a cloneTransform function to somehow cleanly "fork" into two distincts transforms, however I can't get it to not share events:

function cloneTransform(transform) { var ts = new Transform({objectMode: true}); ts._transform = transform._transform.bind(ts); if(typeof transform._flush !== 'undefined') { ts._flush = transform._flush.bind(ts); } return ts; }

Any alternative idea, existing plugin or solution to address this?


Update: context

I'm working on a rewrite of the gulp-usemin package, it is hosted here: gulp-usemin-stream, example use here.

Basically you parse an index.html looking for comment blocks surrounding styles/scripts declarations, and you want to apply several configurable transformation to theses files (see grunt-usemin). So the problem I'm trying to solve is to reuse an array of transforms, [concat(), uglify()] that are passed as options to a gulp meta transform.

It looks like you're trying to use a Transform stream directly instead of subclassing it. What you should be doing is subclassing Transform and overriding the _tranform and, optionally, _flush methods. That way, you can just create a new instance of your transform stream for each readable stream that you need to use it with.

Example:

var util = require('util');
var Transform = require('stream').Transform;

function MyTransform(options) {
    Transform.call(this, options);
    // ... any setup you want to do ...
}
util.inherits(MyTransform, Transform);


MyTransform.protocol._transform = function(chunk, encoding, done) {
    // ... your _transform implementation ...
}

// Optional
MyTransform.protocol._flush = function(done) {
    // ... optional flush implementation ...
}

Once you have that setup, you can simply create new instances of MyTransform for each stream you want to use it with:

var readStream1 = ...
var readStream2 = ...

var transform1 = new MyTransform();
var transform2 = new MyTransform();

readStream1.pipe(transform1).pipe(...);
readStream2.pipe(transform2).pipe(...);

you're doing unnecessary work in your code. it should be as simple as:

function clone(transform) {
  var ts = new Transform({ objectMode: true})
  ts._transform = transform._transform
  ts._flush = transform._flush
  return ts
}

however, i'm not sure how you're trying to use it, so i'm not sure what error you're getting. there's also the issue of initialization where the initial transform stream might initialize the stream with .queue = [] or something, and you won't be initializing it in your clone.

the solution completely depends on the problem you're trying to solve, and i feel like you're approaching the problem incorrectly in the first place.