ctor.js (5797B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var logger = require( 'debug' ); 24 var Transform = require( 'readable-stream' ).Transform; 25 var inherit = require( '@stdlib/utils/inherit' ); 26 var copy = require( '@stdlib/utils/copy' ); 27 var DEFAULTS = require( './defaults.json' ); 28 var validate = require( './validate.js' ); 29 var destroy = require( './destroy.js' ); 30 var _transform = require( './_transform.js' ); // eslint-disable-line no-underscore-dangle 31 32 33 // VARIABLES // 34 35 var debug = logger( 'transform-stream:ctor' ); 36 37 38 // MAIN // 39 40 /** 41 * Transform stream constructor factory. 42 * 43 * @param {Options} [options] - stream options 44 * @param {Function} [options.transform] - callback to invoke upon receiving a new chunk 45 * @param {Function} [options.flush] - callback to invoke after receiving all chunks and prior to the stream closing 46 * @param {boolean} [options.objectMode=false] - specifies whether a stream should operate in object mode 47 * @param {(string|null)} [options.encoding=null] - specifies how `Buffer` objects should be decoded to `strings` 48 * @param {NonNegativeNumber} [options.highWaterMark] - specifies the `Buffer` level for when `write()` starts returning `false` 49 * @param {boolean} [options.allowHalfOpen=false] - specifies whether the stream should remain open even if one side ends 50 * @param {boolean} [options.decodeStrings=true] - specifies whether to decode `strings` into `Buffer` objects when writing 51 * @throws {TypeError} options argument must be an object 52 * @throws {TypeError} must provide valid options 53 * @returns {Function} Transform stream constructor 54 * 55 * @example 56 * var stdout = require( '@stdlib/streams/node/stdout' ); 57 * 58 * function transform( chunk, enc, clbk ) { 59 * clbk( null, chunk.toString()+'\n' ); 60 * } 61 * 62 * var opts = { 63 * 'transform': transform 64 * }; 65 * 66 * var TransformStream = ctor( opts ); 67 * 68 * var stream = new TransformStream(); 69 * 70 * stream.pipe( stdout ); 71 * 72 * stream.write( '1' ); 73 * stream.write( '2' ); 74 * stream.write( '3' ); 75 * 76 * stream.end(); 77 * 78 * // prints: '1\n2\n3\n' 79 */ 80 function ctor( options ) { 81 var transform; 82 var copts; 83 var err; 84 85 copts = copy( DEFAULTS ); 86 if ( arguments.length ) { 87 err = validate( copts, options ); 88 if ( err ) { 89 throw err; 90 } 91 } 92 if ( copts.transform ) { 93 transform = copts.transform; 94 } else { 95 transform = _transform; 96 } 97 /** 98 * Transform stream constructor. 99 * 100 * @private 101 * @constructor 102 * @param {Options} [options] - stream options 103 * @param {boolean} [options.objectMode=false] - specifies whether a stream should operate in object mode 104 * @param {(string|null)} [options.encoding=null] - specifies how `Buffer` objects should be decoded to `strings` 105 * @param {NonNegativeNumber} [options.highWaterMark] - specifies the `Buffer` level for when `write()` starts returning `false` 106 * @param {boolean} [options.allowHalfOpen=false] - specifies whether the stream should remain open even if one side ends 107 * @param {boolean} [options.decodeStrings=true] - specifies whether to decode `strings` into `Buffer` objects when writing 108 * @throws {TypeError} options argument must be an object 109 * @throws {TypeError} must provide valid options 110 * @returns {TransformStream} transform stream 111 * 112 * @example 113 * var stdout = require( './../../../node/stdout' ); 114 * 115 * var stream = new TransformStream(); 116 * 117 * stream.pipe( stdout ); 118 * 119 * stream.write( '1' ); 120 * stream.write( '2' ); 121 * stream.write( '3' ); 122 * 123 * stream.end(); 124 * 125 * // prints: '1\n2\n3\n' 126 */ 127 function TransformStream( options ) { 128 var opts; 129 var err; 130 if ( !( this instanceof TransformStream ) ) { 131 if ( arguments.length ) { 132 return new TransformStream( options ); 133 } 134 return new TransformStream(); 135 } 136 opts = copy( copts ); 137 if ( arguments.length ) { 138 err = validate( opts, options ); 139 if ( err ) { 140 throw err; 141 } 142 } 143 debug( 'Creating a transform stream configured with the following options: %s.', JSON.stringify( opts ) ); 144 Transform.call( this, opts ); 145 this._destroyed = false; 146 return this; 147 } 148 149 /** 150 * Inherit from the `Transform` prototype. 151 */ 152 inherit( TransformStream, Transform ); 153 154 /** 155 * Implements the `_transform` method. 156 * 157 * @private 158 * @name _transform 159 * @memberof TransformStream.prototype 160 * @type {Function} 161 * @param {(Buffer|string)} chunk - streamed chunk 162 * @param {string} encoding - Buffer encoding 163 * @param {Callback} clbk - callback to invoke after transforming the streamed chunk 164 */ 165 TransformStream.prototype._transform = transform; // eslint-disable-line no-underscore-dangle 166 167 if ( copts.flush ) { 168 /** 169 * Implements the `_flush` method. 170 * 171 * @private 172 * @name _flush 173 * @memberof TransformStream.prototype 174 * @type {Function} 175 * @param {Callback} callback to invoke after performing flush tasks 176 */ 177 TransformStream.prototype._flush = copts.flush; // eslint-disable-line no-underscore-dangle 178 } 179 180 /** 181 * Gracefully destroys a stream, providing backward compatibility. 182 * 183 * @private 184 * @name destroy 185 * @memberof TransformStream.prototype 186 * @type {Function} 187 * @param {Object} [error] - optional error message 188 * @returns {TransformStream} stream instance 189 */ 190 TransformStream.prototype.destroy = destroy; 191 192 return TransformStream; 193 } 194 195 196 // EXPORTS // 197 198 module.exports = ctor;