README.md (7645B)
1 <!-- 2 3 @license Apache-2.0 4 5 Copyright (c) 2018 The Stdlib Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 --> 20 21 # Transform Stream 22 23 > [Transform stream][transform-stream]. 24 25 <section class="usage"> 26 27 ## Usage 28 29 ```javascript 30 var transformStream = require( '@stdlib/streams/node/transform' ); 31 ``` 32 33 <a name="transform-stream"></a> 34 35 #### transformStream( \[options] ) 36 37 Creates a [transform stream][transform-stream]. 38 39 ```javascript 40 var stdout = require( '@stdlib/streams/node/stdout' ); 41 42 function transform( chunk, enc, clbk ) { 43 clbk( null, chunk.toString()+'\n' ); 44 } 45 46 var stream = transformStream({ 47 'transform': transform 48 }); 49 50 stream.pipe( stdout ); 51 52 stream.write( '1' ); 53 stream.write( '2' ); 54 stream.write( '3' ); 55 56 stream.end(); 57 // e.g., => '1\n2\n3\n' 58 ``` 59 60 The function accepts the following `options`: 61 62 - **transform**: callback to invoke upon receiving a new chunk. 63 - **flush**: callback to invoke after receiving all chunks and prior to a stream closing. 64 - **objectMode**: specifies whether a [stream][stream] should operate in [objectMode][object-mode]. Default: `false`. 65 - **encoding**: specifies how `Buffer` objects should be decoded to `strings`. Default: `null`. 66 - **highWaterMark**: specifies the `Buffer` level at which `write()` calls start returning `false`. 67 - **allowHalfOpen**: specifies whether a [stream][stream] should remain open even if one side ends. Default: `false`. 68 - **decodeStrings**: specifies whether to decode `strings` into `Buffer` objects when writing. Default: `true`. 69 70 To set [stream][stream] `options`, 71 72 ```javascript 73 var opts = { 74 'objectMode': true, 75 'encoding': 'utf8', 76 'highWaterMark': 64, 77 'allowHalfOpen': true, 78 'decodeStrings': false 79 }; 80 81 var stream = transformStream( opts ); 82 ``` 83 84 The `transform` option should be a `function` having the following signature: 85 86 ```javascript 87 function transform( chunk, enc, clbk ) { 88 var multipleData; 89 var err; 90 91 if ( multipleData ) { 92 // Push as many chunks as required... 93 this.push( chunk ); 94 this.push( chunk ); 95 96 // ... 97 98 if ( err ) { 99 return clbk( err ); 100 } 101 return clbk(); 102 } 103 if ( err ) { 104 return clbk( err ); 105 } 106 clbk( null, chunk ); 107 } 108 ``` 109 110 The `flush` option should be a `function` which performs any remaining tasks before the stream closes, such as unfinished data processing. 111 112 ```javascript 113 function flush( clbk ) { 114 var err; 115 116 // Push any remaining chunks... 117 this.push( '...' ); 118 this.push( '...' ); 119 120 // ... 121 122 if ( err ) { 123 return clbk( err ); 124 } 125 clbk(); 126 } 127 ``` 128 129 If no `transform` is provided, the returned `stream` will be a simple pass through stream. 130 131 #### transformStream.factory( \[options] ) 132 133 Returns a `function` for creating [streams][transform-stream] which are identically configured according to provided `options`. 134 135 ```javascript 136 var opts = { 137 'objectMode': true, 138 'encoding': 'utf8', 139 'highWaterMark': 64 140 }; 141 142 var factory = transformStream.factory( opts ); 143 ``` 144 145 This method accepts the same `options` as [`transformStream()`](#transform-stream), **except** for the `transform` and `flush` options which must be provided **explicitly**, as shown below. 146 147 ##### factory( transform\[, flush] ) 148 149 Creates a [transform stream][transform-stream]. 150 151 ```javascript 152 function transform1( chunk, enc, clbk ) { 153 clbk( null, chunk.toString()+'\n' ); 154 } 155 156 function transform2( chunk, enc, clbk ) { 157 clbk( null, chunk.toString()+'\t' ); 158 } 159 160 function flush( clbk ) { 161 clbk(); 162 } 163 164 var factory = transformStream.factory(); 165 166 var s1 = factory( transform1 ); 167 var s2 = factory( transform2, flush ); 168 ``` 169 170 #### transformStream.objectMode( \[options] ) 171 172 This method is a convenience function to create [streams][stream] which always operate in [objectMode][object-mode]. 173 174 <!-- eslint-disable object-curly-newline --> 175 176 ```javascript 177 var stdout = require( '@stdlib/streams/node/stdout' ); 178 179 function stringify( chunk, enc, clbk ) { 180 clbk( null, JSON.stringify( chunk ) ); 181 } 182 183 function newline( chunk, enc, clbk ) { 184 clbk( null, chunk+'\n' ); 185 } 186 187 var s1 = transformStream.objectMode({ 188 'transform': stringify 189 }); 190 191 var s2 = transformStream.objectMode({ 192 'transform': newline 193 }); 194 195 s1.pipe( s2 ).pipe( stdout ); 196 197 s1.write( { 'value': 'a' } ); 198 s1.write( { 'value': 'b' } ); 199 s1.write( { 'value': 'c' } ); 200 201 s1.end(); 202 // e.g., => '{"value":"a"}\n{"value":"b"}\n{"value":"c"}\n' 203 ``` 204 205 This method accepts the same `options` as [`transformStream()`](#transform-stream); however, the method will **always** override the [objectMode][object-mode] option in `options`. 206 207 #### transformStream.ctor( \[options] ) 208 209 Instead of returning a [transform stream][transform-stream] instance, this method returns a custom [transform stream][transform-stream] constructor. If provided `transform` and `flush` options, these methods are bound to the constructor prototype. If not provided a `transform`, the returned constructor creates simple pass through streams. 210 211 <!-- eslint-disable no-underscore-dangle --> 212 213 ```javascript 214 function transform( chunk, enc, clbk ) { 215 clbk( null, chunk.toString()+'\n' ); 216 } 217 218 function flush( clbk ) { 219 this.push( 'beep' ); 220 clbk(); 221 } 222 223 var opts = { 224 'transform': transform, 225 'flush': flush 226 }; 227 228 var TransformStream = transformStream.ctor( opts ); 229 230 var bool = ( TransformStream.prototype._transform === transform ); 231 // returns true 232 233 bool = ( TransformStream.prototype._flush === flush ); 234 // returns true 235 ``` 236 237 The returned constructor accepts the same `options` as documented above, **except** for the `transform` and `flush` options, which are not supported. Any `options` provided to the constructor **override** `options` provided to the constructor factory. 238 239 </section> 240 241 <!-- /.usage --> 242 243 <section class="examples"> 244 245 ## Examples 246 247 <!-- eslint no-undef: "error" --> 248 249 ```javascript 250 var stdout = require( '@stdlib/streams/node/stdout' ); 251 var factory = require( '@stdlib/streams/node/transform' ).factory; 252 253 function parse( chunk, enc, clbk ) { 254 clbk( null, JSON.parse( chunk ) ); 255 } 256 257 function pluck( chunk, enc, clbk ) { 258 clbk( null, chunk.value ); 259 } 260 261 function square( chunk, enc, clbk ) { 262 var v = +chunk; 263 clbk( null, v*v ); 264 } 265 266 function toStr( chunk, enc, clbk ) { 267 clbk( null, chunk.toString() ); 268 } 269 270 function join( chunk, enc, clbk ) { 271 clbk( null, chunk+'\n' ); 272 } 273 274 // Create a factory which generates streams running in `objectMode`: 275 var tStream = factory({ 276 'objectMode': true 277 }); 278 279 // Create streams for each transform: 280 var s1 = tStream( parse ); 281 var s2 = tStream( pluck ); 282 var s3 = tStream( square ); 283 var s4 = tStream( toStr ); 284 var s5 = tStream( join ); 285 286 // Create the pipeline: 287 s1.pipe( s2 ) 288 .pipe( s3 ) 289 .pipe( s4 ) 290 .pipe( s5 ) 291 .pipe( stdout ); 292 293 // Write data to the pipeline... 294 var v; 295 var i; 296 for ( i = 0; i < 100; i++ ) { 297 v = '{"value":'+i+'}'; 298 s1.write( v, 'utf8' ); 299 } 300 s1.end(); 301 ``` 302 303 </section> 304 305 <!-- /.examples --> 306 307 <section class="links"> 308 309 [stream]: https://nodejs.org/api/stream.html 310 311 [object-mode]: https://nodejs.org/api/stream.html#stream_object_mode 312 313 [transform-stream]: https://nodejs.org/api/stream.html 314 315 </section> 316 317 <!-- /.links -->