{"_id":"pipette","_rev":"46-3ff98c701f399bd8953240d95d220fca","name":"pipette","description":"Stream and pipe utilities for Node","dist-tags":{"latest":"0.9.3"},"versions":{"0.2.0":{"name":"pipette","version":"0.2.0","keywords":["stream","pipe","buffer","valve","data","event"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.2.0","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.23","_nodeVersion":"v0.6.18","_defaultsLoaded":true,"dist":{"shasum":"b598f9902454cb0c914cdfd921be97d8662b0cf0","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.2.0.tgz","integrity":"sha512-QwrrMslrRSNX0xQ59t34GsalZKm9d8Ef0337eYiPzRROj1ESOnq65Ca+0GT5srTE0KHWi2X+M5QBiRmDMrzdrA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjW4JoDUU1iB+SuQ57D9INUyADkb7lvH9RbQnB6GuJWAIgZ8zoVFtuMK4/P05Ed8HsWcPOJbp+S5ERBCStKcawMN4="}]}},"0.3.0":{"name":"pipette","version":"0.3.0","keywords":["stream","pipe","buffer","valve","data","event"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.3.0","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"5c007084bdda29aada0ab4f4bfa0478bce56d1f6","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.3.0.tgz","integrity":"sha512-mr9eiijzJtqf+M+WzvL/RCuY8Fm/tu9n+Y1HJGApuQgkdT6lBkcz4vmQPS3JZEq2/kazbNBCzUqo9vZqynl/0w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAGKC6F/xYW72PRgeSegeTCs9GHn9nNEYpV0fcJKtnmhAiAIdZ9+u7oxY7ASPTDkDTbdo1JXLiT5bIpQYavr/t9jsg=="}]}},"0.3.1":{"name":"pipette","version":"0.3.1","keywords":["stream","pipe","buffer","valve","data","event"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.3.1","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"96de4f158d8c3ccbbb239a6432b77b726a757522","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.3.1.tgz","integrity":"sha512-vq52OmZGrYNegQky4hp7pI+HzQEE3FD2DzR8GZcR5YSqYY9KOqX97t5P61pBym2FrldgqtcoMIUMEM8puh9G5Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDw/RDoUXjFtD+oy7Z28VYxge/iYCbgHNbyBM61GtQquwIgH/ppvNKwd58v5KOEuA2bUIJ/1YqZnroA8ixmbElpMRg="}]}},"0.4.0":{"name":"pipette","version":"0.4.0","keywords":["stream","pipe","buffer","valve","data","event","blip","cat"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.4.0","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"73c785a7c5734f663a60afd7196c4ad4e60a799d","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.4.0.tgz","integrity":"sha512-JyseKW2nv6ph8QMKpBXDYTs4LD8xsrQoMA+EFTmxovgSLgKSNR9JIqbrbVuAWn3CpK7vGeyeO1RVQP4KbpchFQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEDcylcbjLutVA8OmZFQZmGjeoG5YM6mSihPd1u2po8LAiAmRiAgvcw9y2/fUM/r5ARo5eAwhEP0uQgvR41D0Y30pg=="}]}},"0.4.1":{"name":"pipette","version":"0.4.1","keywords":["stream","pipe","buffer","valve","data","event","blip","cat"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.4.1","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"e8daf298af5c087bbb5a0e6fb69adca9a5f203ec","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.4.1.tgz","integrity":"sha512-mwLey7BXYOhWVFLi1tdhzSp+UoDIp5M9Zq6kB1m0i1/CPu8UKTPFFY3pLRO6XeNaRDORmkSEjGVLFawIpBf31Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH77sv7PYYFAMa9J9CQOgY+wWAoM9TEKJpnXzCD8/4HkAiBp50QstJSuT7+L6U77hAedbEAIDJuNXuR4oZr8tKPuGQ=="}]}},"0.5.0":{"name":"pipette","version":"0.5.0","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.5.0","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"ab861fba1d241f6d462d2943b80dd6e90f09cb23","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.5.0.tgz","integrity":"sha512-1Lu691PL1xMymcwAn4vvRs0KjWAt45URs9x0JxSxrVmR+Gsu23J3N6TX6xU06d75oYR5JZBzvA2RhQ5rgEHMBA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDaSzp9nUekh8CykJfloDHrJr7wgeXG4VOAcvl/BBiBvAIhAPPPcbwnMCDsjoZ0vZC1bMMI4tZw/U4SFqBVJtqacYdN"}]}},"0.5.1":{"name":"pipette","version":"0.5.1","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.5.1","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"31f12d6d31daa9d42e9ff013c95d622fa4df0ad0","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.5.1.tgz","integrity":"sha512-1Ozwe6VLfcha2HCKuKSMm8M9+Hkb/IEDvsEog8t9T/Bo/KRYAn6WJ0eWKErAt12HN7kXq0q/bgfRPOBCkcESVg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHrTUnbntS7qwOomHb+Tv5Sa0E1OvpQOPHZnOjzFmN3RAiBn0kCSEC7I/M8ZjVVFJQeixxq6QIHvLv7RCJ4Dsk7ZgA=="}]}},"0.6.0":{"name":"pipette","version":"0.6.0","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink"],"description":"Pipe-like utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.6.0","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"3d376fc158ab77fe71c8bd8b95fd8fdf5f0eb0c1","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.6.0.tgz","integrity":"sha512-yy86jtpxAe+jQBkHN/wWtnicdSSweEBWy6U9SgecHv5CqRcXImdNT9wajxb/qqv6RKCo70AMwWa5Msz8zXvkjA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHApmQYnWpnf1IydskPhaFQMk/Vzrmd+3lvZFeVGWG+bAiEA5OQhTcnS4Wnjqxii2PL8gi1z+NHYLNLfIQFbIrHFBk4="}]}},"0.6.1":{"name":"pipette","version":"0.6.1","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.6.1","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"87647e8d0822cdaed112a9466feff5579a9660cc","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.6.1.tgz","integrity":"sha512-p2CbtRZaNUbCJzPrwywTetfu6ljt3kY1efM7IsNwlK9Wm/VXfwhXVcF2OJEBjIgR+1JK+CuX15iemFwzix4Iww==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDBf/Q8KUzsuUuaAu1eoH4FwSNclbZjhgMpev7RAP/TXwIgb3iljIWmFdQArxYY1SlEFT55QglULTpIexilCxT7WPA="}]}},"0.7.2":{"name":"pipette","version":"0.7.2","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.7.2","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"0c5c6f93eacf4bf034fb06136f066431f71e18aa","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.7.2.tgz","integrity":"sha512-BCgebC2j22PEvk8bOySQr+6TLT0OjCQkcx8aRBo9rT0qx5CjFjS6+0k9eaXuSIJ8OnXGQFbY8OigcBmVOXjFOw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICWBkqW/5cCv9ZzG5tLZzBO9OHUokIOTI15C6Igut+qqAiArap5MSzwcZlAix/swZuER/qINANa9gvnLfPe4m/rtng=="}]}},"0.8.0":{"name":"pipette","version":"0.8.0","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.8.0","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"190b9e2d0b856dbbec536321ae0563eecf23872b","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.8.0.tgz","integrity":"sha512-+Q0FNOpCMC4t0Fzxq8zzIrd48x417sKQIAjwlB/9BDZDGnLTaAdzeQj7miokiKUo2V+Nrypo61ZUkVzSVPbKag==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC/e4Ndn7PXYG3uSibVXOIwQgzC8b6duW35MvGBsEfPJgIgdXmRI3f6uE4yv0w5dXB7X9h+tc4QL2G7bfZVRUr1AFM="}]}},"0.8.1":{"name":"pipette","version":"0.8.1","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.8.1","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"f66daa4b71bef15d4654efc5fd583a012104b4fc","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.8.1.tgz","integrity":"sha512-DJIudiuP6BqoCXRul4D4kLWYjvVS+CsUL/W2xc0y9yFmB68zoE3WNO4kqhxNDYwCXfRAhikTvbM/z/SVum9Ztg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG4bA7OGeq2qMneanbuixwrmbvaa+DrRyWpoarupZmKiAiEAoDuXQrexs0Qt6k4eE2ervfy0jUVkOAS4R8/6PFm6wjw="}]}},"0.8.2":{"name":"pipette","version":"0.8.2","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.8.2","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"a48527aa4b65f6680931c4d8852fa25c72fad12f","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.8.2.tgz","integrity":"sha512-0heA4sU8SNraiLRCYqO1ZkmOpjFwVDeEn5FpgSgWrFxZPwDGYrkSynBT/ICqoctqLz3kVLZmVQZXvkhCDPj65A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAurE/o5t8mVh44yigycGgyxg8Z4Imj5TslR9YdkiaCIAiEA+jEMoozyddYlSKBrLBRrBWjRp6+ppt2RPxoBNydmfaU="}]}},"0.8.3":{"name":"pipette","version":"0.8.3","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.8.3","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"2b84cdc18385c877d2f253dc4b3b2e91c338fea3","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.8.3.tgz","integrity":"sha512-1qr1DkfyortAn2Ro5sdXozZNTGmrwyOlwMg23bA23Ys0w7rpdyE7ZsFg+oHiOF3ko9aVV8R2L/CT9r722EWU3w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDJHbtIAjvahI+wTX0Om6nRG2Yg4fC6XJTUMwmFPYLGKAiAnZC3Dq5+X5aL/A4s0LTfdk8a00UnBavhcJGgbVK3Xrg=="}]}},"0.8.4":{"name":"pipette","version":"0.8.4","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read","dropper"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.8.4","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"3b2a9056772683a9b3af645b0dc231fd1ca9600b","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.8.4.tgz","integrity":"sha512-n0hhN6NrKVFrKY/F5mlLVZJnwhCJ1YM9XSQ+LI5IC2BdYl9Ts9KE6Hy4eoKoVnQuHVLR5eWc9UD/73ewxVdOog==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBugSy0mmSEHgljGd9AhKbilZDLKe7LEw1/Df0tG89pTAiBIEBat50sDOmE8a1N5xMRVNg386aGECFvGYmESCXcGNw=="}]}},"0.8.5":{"name":"pipette","version":"0.8.5","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read","dropper"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.8.5","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"e0d84d0c58ef5d21758aaafbfe6830ba96af882e","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.8.5.tgz","integrity":"sha512-m15PD9FhtkBKFLB9UY3sFZqoO45N6aPz4N4S1VJH4QnWG2xxiv/uqboogqYDPWke5tYcgHy2ipE4e2lLydR7Pw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD6zQSSdqN8+TBsxwEvpoWvEjQC00/+VnYtMH4AuG7+GAIhAPpYfAQWqoXc+Nz9HgOnEqj8E1zYKQU5P0guN4/LNxZF"}]}},"0.9.0":{"name":"pipette","version":"0.9.0","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read","dropper"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"git://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"},"_id":"pipette@0.9.0","devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.1.24","_nodeVersion":"v0.6.19","_defaultsLoaded":true,"dist":{"shasum":"82a505baa4c391d10b5c89543e5dc9615962dacb","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.9.0.tgz","integrity":"sha512-nS8F+6KJSWacaW2sEsZsmensyIRAIJ1M0WCyC2RTONXrYxvNhZ8UD9CMRHDdOt9XgIMEwi8GHHyE+Me7tsc/pA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCUPBNcENAWOgYTi0HfWD1hm2QtOv024juMXjmXU9WEqAIhAJYjGCrkSISG/TS+H+mxUxtq2+hImTdF0/e91fXlGXTm"}]}},"0.9.1":{"name":"pipette","version":"0.9.1","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read","dropper"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"https://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"readme":"pipette: Stream and pipe utilities for Node\n===========================================\n\nThis Node module provides several utility classes that offer\npipe and stream-related functionality. It particularly emphasizes\nproviding a consistent event packaging and ordering for streams.\n\n\nBuilding and Installing\n-----------------------\n\n```shell\nnpm install pipette\n```\n\nOr grab the source and\n\n```shell\nnpm install\n```\n\n\nTesting\n-------\n\n```shell\nnpm test\n```\n\nOr\n\n```shell\nnode ./test/test.js\n```\n\n\nEvent Sequence Philosophy\n-------------------------\n\nAll of the classes in this module provide a consistently ordered\nsequence of events, which is meant to be a sensible synthesis of the\n(somewhat inconsistent) Node specification for the various core\nstream classes.\n\nIn particular, a stream will emit some number of `data` events\n(possibly zero), each with a single payload argument. This will be\nfollowed by *either* an `end` event with no payload or an `error`\nevent with an arbitrary payload. This is followed by a `close` event\nwith no payload. After that, a stream will not emit any further\nevents, and it is furthermore guaranteed to be detached from its\nupstream source(s), if any.\n\nMore schematically, as a \"railroad\" diagram:\n\n```\n        +--------------------+      +-------+\n        |                    |   +->| end() |----------+\n        v  +---------------+ |   |  +-------+          |  +---------+\n(start)-+->| data(payload) |-+-+-+                     +->| close() |->(finish)\n        |  +---------------+   ^ |  +----------------+ |  +---------+\n        |                      | +->| error(payload) |-+\n        +----------------------+    +----------------+\n```\n\nOf particular note are the cases of inconsistently-defined `close`\nevents. Some streams (core Node stream classes, for example) will emit\na `close` event with a non-empty payload value to indicate an\nunexpected termination. The classes in this module consistently\ntranslate such cases to an `error` event with the error payload\nfollowed by a no-payload `close` event. For the purposes of this\nmodule, a \"non-empty payload\" is one that is neither `undefined` nor\n`false`. This takes care of the quirky definitions of `net.Socket`\n(which includes a boolean error indicator in its `close` event) and\n`http.ClientResponse` (which may include an arbitrary error object in\nits `close` event).\n\nThe particularly nice thing about this arrangement is that if one\nwants to consistently do something after a stream has finished, one\ncan write the something in question as a `close` event handler, rather\nthan splaying the logic between both an `end` and an `error` handler.\n\nIn the rest of the documentation, it should be taken as implicit that\nall the classes' event sequences follow this order.\n\n\nLayering Philosophy\n-------------------\n\nFour of these classes (`Cat`, `Sink`, `Slicer`, and `Valve`) provide a\nlayer on top of other streams. The implementation philosophy is that\nthese listen for events from their \"upstream\" sources, but they do not\notherwise attempt to interact with those streams. In particular:\n\n* They do not make upstream calls to the flow-control methods\n  `pause()` and `resume()`.\n\n* They do not attempt to make upstream `setEncoding()` calls.\n\n* They do not call upstream `destroy()` even when they themselves are\n  being `destroy()`ed.\n\nIn addition, these layering classes check upon construction that their\nupstream sources are in fact streams that have not yet been ended\n(that is, that they are still capable of emitting events). If a stream\nsource argument fails this check, then the constructor call will throw\nan exception indicating that fact. The check is somewhat conservative\n(on the side of accepting) and meant to accept stream-like event\nemitters in addition to checking bona fide `Stream` instances.\nDetails: If a given source is a `Stream` per se, then the value of\n`source.readable` is taken at face value. Otherwise, a source is\nconsidered to be ended if and only if it (or a prototype in its chain)\ndefines a `readable` property and that property's value is falsey.\n\n### Constructing stacked readers\n\nMany Node stream classes are designed as an atomic unit that includes\nboth reader and writer methods intermingled in a single object. This\nmodule takes a different tack:\n\n* Any given object is either a reader or a writer, never both.\n\n* To pass one reader's event output to another, construct the destination\n  object passing it the source, e.g. `new Valve(new OtherStream(...))`.\n\n### Getting a writer\n\nIf you need to get a writer to write into one of the reader classes\n(or a stack of same), you can use a `Pipe`:\n\n```javascript\nvar pipe = new Pipe();\nvar readerStack = new OtherStream(pipe.reader);\nvar writer = pipe.writer;\n\nwriter.write(...); // What's written here will get read by the OtherStream.\n```\n\n\nA Note About Encodings\n----------------------\n\nNode 0.6.* and 0.8.* differ in their documentation about which encodings\nare allowed by `setEncoding()`. This module accepts the union of the\nencodings specified by those. This includes:\n\n* `ascii` &mdash; 7-bit ASCII\n* `base64` &mdash; standard Base-64 encoding for binary data\n* `hex` &mdash; hex encoding for binary data (two hexadecimal ASCII\n  characters per byte)\n* `ucs2` &mdash; alias for `utf16le` (below). This is not technically correct\n  (per Unicode spec), but it is how Node is defined.\n* `utf16le` &mdash; standard little-endian UTF-16 encoding for Unicode data\n* `utf8` &mdash; standard UTF-8 encoding for Unicode data\n\n\nCommon Options\n--------------\n\nAll of the classes in this module take an optional `options`\nconstructor parameter. If not `undefined`, this must be a map from\noption names to values as specified by the class.\n\nThe following are three commonly-accepted options. Classes all accept\nwhichever of these make sense.\n\n* `encoding` &mdash; A string representing the encoding to use when\n  emitting events. Passing this option is exactly like calling\n  `setEncoding()` on the constructed instance.\n\n* `incomingEncoding` &mdash; A string representing the incoming\n  encoding to use when interpreting incoming `data` events that arrive\n  as strings (as opposed to buffers). Passing this option is exactly\n  like calling `setIncomingEncoding()` on the constructed instance.\n\n* `paused` &mdash; A boolean value indicating whether the instance\n  should be immediately paused. For most classes, this is exactly like\n  calling `pause()` on the constructed instance.\n\n\n* * * * * * * * * *\n\nAPI Details\n===========\n\nBlip\n----\n\nThe `Blip` class exists to emit a single `data` event.\n\nThis class is useful if you have data that you need to re-emit.\n\n### var blip = new Blip([data], [options])\n\nConstructs and returns a new blip which is to emit the given `data`\n(a string or buffer) once unpaused. After emitting the `data` event,\nblips always also emit an `end` and a `close` event (in that order).\n\nOf the common options, Blip recognizes `encoding` and\n`incomingEncoding`, though the latter is with a twist: The\n`incomingEncoding` (either as specified or with the default behavior)\napplies immediately to the given `data`, in order to transform it into\na buffer. That is, if `data` is passed as a string, it will always get\nimmediately transformed into a buffer, when an instance is\nconstructed.\n\nIf `data` is omitted, then the resulting blip will *just* emit the\nending events, without a `data` event first.\n\nBlips start out paused, since there is not much point in them\nimmediately emitting their contents upon construction (as there\nwill necessarily be no listeners at that moment).\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n\nCat\n---\n\nThe `Cat` class (short for \"concatenate\" and by analogy with the\ntraditional Unix command with the same name) emits the events from\na sequence of streams, in the order of the given sequence (i.e.\nnot interspersed).\n\nThis can be used, for example, to produce a stream that is prefixed\nor suffixed with a given bit of data (when used in combination with\n`Blip`, above).\n\n### var cat = new Cat(streams, [options])\n\nConstructs and returns a new cat which is to emit the events from\nthe given streams (each of which must be an `EventEmitter` and is\nassumed to emit the standard Node readable stream events).\n\nThe data events from each stream (in order) are in turn emitted by\nthis instance, switching to the next stream when the current stream\nemits either an `end` or `close` event. After all the streams have\nbeen \"consumed\" in this fashion, this instance emits an `end` and then\na `close` event.\n\nIf a stream should emit an `error` event, then that event is in turn\nemitted by this instance, after which this instance emits a `close`\nevent. It will then become closed (emitting no further events, and\nproducing `false` for `cat.readable`).\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n### cat.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nDropper\n-------\n\nThe `Dropper` class is a bufferer of readable stream events, which\nrelays those events in fixed size blocks (or multiples thereof),\na.k.a. \"drops\" (hence the name). It handles pause/resume semantics,\nand it will always translate incoming values that aren't buffers into\nbuffers, using a specified and settable incoming encoding.\n\nThe only exception to the block size is that the last `data` event\nfrom a Dropper may have a smaller size, if the last data it received\n(before an `end` or `error`) would not end up filling up a block of\nthe specified size. In this case, the behavior is specified by\nthe `ifPartial` option (see below).\n\nOther than the fixed-size block part, the semantics of this class are\nbasically the same as the simpler `Valve` class (see below).\n\n### var dropper = new Dropper(source, [options])\n\nConstructs and returns a new dropper, which listens to the given source.\nThis takes an optional `options` argument, which if present must be\na map of options, including any of the common options (see above)\nas well as any of the following:\n\n* `size` &mdash; block (aka drop) size in bytes. Must be a positive\n  integer. Defaults to `1`.\n\n* `allowMultiple` &mdash; whether emitted data events are to be the\n   exact block size (`false`) or may be an even multiple of the block\n   size (`true`). Must be a boolean. Defaults to `false`.\n\n* `ifPartial` &mdash; what to do with a partial block at the\n   end of the stream; one of `emit` (emit it as-is),\n   `ignore` (drop it entirely), `pad` (zero-pad), `error` (emit\n   an error). Defaults to `emit`.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n(Note: As of this writing, this is the only one of the classes in this\nmodule that takes an options object on construction. It is likely that\nthe rest of the classes will migrate to this form.)\n\n### dropper.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nPipe\n----\n\nThe `Pipe` class is a simple in-memory pipe, which provides writer and\nreader ends. Pipes handle data encoding and obey pause/resume semantics.\n\nThis class is useful if you have code that wants to call writable stream\nstyle methods, and you want it to be directly attached to some other code\nthat expects to be listening for events. For example:\n\n```javascript\nvar listeningThingy = ...;\nvar writingThingy = ...;\n\nvar pipe = new Pipe();\nlisteningThingy.listenTo(pipe.reader);\nwritingThingy.writeTo(pipe.writer);\n```\n\n### var pipe = new Pipe([options])\n\nConstructs and returns a new pipe pair. The result is an object with\nmappings for `{ reader, writer }` for the two ends of the pipe.\n\nThe reader and writer side each implement the standard Node stream\nprotocol for readable and writable streams (respectively).\n\nThe specified protocol allows writers to ignore the `fd` argument\nto `stream.write()`, and this implementation in fact ignores it.\n\nOf the common options, the constructor accepts `encoding` and `paused`,\nwhich both apply to the reader end of the pipe.\n\n\nSink\n----\n\nThe `Sink` class is an in-memory collector of all the data read from a\ngiven stream. It is in turn itself a stream that emits no more than a\nsingle `data` event consisting of all of the data it received, once\nits upstream source has ended. It also has direct accessors method to\nget at the data or a stream-ending error, to provide a bit of\nflexibility in how the class is used.\n\nThis class is useful for cases where you don't care about incremental\nprocessing and just want to deal with the whole enchilada (as it\nwere). This can be used to collect an entire post body from an HTTP\nrequest, for example:\n\n```javascript\nvar httpServer = http.createServer(onRequest);\n\nfunction onRequest(request, response) {\n  var postData = new Sink(request);\n  postData.on(\"data\", onPostData);\n\n  function onPostData(data) {\n    console.log(\"Got post:\", data.toString());\n  }\n}\n```\n\n### var sink = new Sink(source, [options])\n\nConstructs and returns a new sink, which listens to the given source\nstream. Once the stream has ended (via either an `end` or `close`\nevent), this instance emits a single `data` event containing all\nof the data received from the source (if there was any data at all),\nfollowed by an `end` and then a `close` event.\n\nIf the source should ever emit an `error` event, then this will cause\nthe sink instance to first emit any data it received (as a single\n`data` event), followed by an `error` event that corresponds to the\none it received, and finally followed by a `close` event. After that,\nit will emit no further events.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\nIn addition to being readable streams, sinks have a few more methods.\n\n### sink.getData() => buffer || string || undefined\n\nGets the final complete data for the sink, if available.\n\nIf the sink's source has not yet ended, or if it ended without\never emitting any data, this returns `undefined`.\n\nIf the sink received any data and has a specified encoding (via\n`setEncoding()`), this returns the string form of the data, as decoded\nusing the named encoding.\n\nIf the sink received any data but has no specified encoding, this\nreturns the straight buffer of data.\n\nNote that this method can return a defined (that is, not `undefined`)\nvalue before the corresponding `data` event is emitted, particularly\nif the sink happens to be paused at the time the upstream stream is\nended.\n\nAlso note that there is a bit of ambiguity with this method, in terms of\ndifferentiating a stream that got ended with no data ever received\nwith one that simply hasn't yet ended. Instead of using this method\nfor that purpose, use `sink.readable` (part of the standard readable\nstream protocol).\n\n### sink.getError() => any\n\nGets the error that terminated the upstream source, if available.\n\nIf the sink's source has not yet ended, or if it ended normally, this\nreturns `undefined`.\n\nIf the sink's source ended with an `error` event, then this returns the\nsame value that was received in that error event.\n\nNote that this method can return a defined (not `undefined`) value\nbefore the corresponding `error` event is emitted, particularly if the\nsink happens to be paused at the time the upstream stream reports its\nerror.\n\nAlso note that there is a bit of ambiguity in terms of interpreting a\nstream that got ended with an `error` event whose payload is\n`undefined`. If you need to account for this possibility, use\n`sink.gotError()`.\n\n### sink.gotError() => boolean\n\nGets whether or not the upstream source was ended with an error.\n\nThis returns `false` if the source has not yet ended, or if it ended\nnormally.\n\nThis returns `true` if and only if the upstream source emitted an\n`error` event that this sink instance received.\n\nNote that this method can return `true` before the corresponding\n`error` event is emitted, particularly if the sink happens to be\npaused at the time the upstream stream reports its error.\n\n### sink.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nSlicer\n------\n\nThe `Slicer` class (like `Sink`) is an in-memory bufferer of data\nread from a given stream. In turn, it provides a `fs.read()` style\ninterface to get at the data so-read.\n\nAs the name implies, this class is useful for slicing up a stream\ninto chunks that aren't (necessarily) the same shape as the ones\nthat came in as `data` events.\n\nMost of the \"interesting\" methods on the class take a callback\nargument to receive data back from the instance. These are all\nconsistently called as `callback(error, length, buffer, offset)` with\nno `this` and with arguments defined as follows:\n\n* `error` &mdash; a boolean flag indicating whether the read was cut short\n  due to an error *or* because there was insufficient data to fully\n  comply with the request. (Note: This is different than `fs.read()`\n  which passes an error object here. See `slicer.gotError()` below for\n  an explanation of why.)\n\n* `length` &mdash; the number of bytes read.\n\n* `buffer` &mdash; the buffer that was read into.\n\n* `offset` &mdash; the offset into `buffer` where the reading was done.\n\nThe ordering and meaning of the callback arguments are meant to be (a)\ncompatible with callbacks used with `fs.read()` and (b) somewhat more\ninformative and unambiguous.\n\n### var slicer = new Slicer(source, [options])\n\nConstructs a new slicer, which listens to the given source.\n\nOf the common options, the only one recognized by this class is\n`incomingEncoding`. The class accepts no other options.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\n\n### slicer.readable => boolean\n\nThis indicates whether there is any data left to be read in the stream\nor whether there *could* be any day left to be read.\n\nIn particular, this only becomes `false` when it is both the case that\nthe buffer of pending data is empty *and* the upstream source has ended.\n\nThis field is meant to be reasonably analogous to the readable stream\nfield of the same name.\n\n### slicer.destroy()\n\nCauses the instance to be cleaned up and become closed. In particular,\nit includes detaching from the upstream source. After this method is\ncalled, other methods on this class will behave as if the upstream\nsource ended with no error.\n\nThis method is meant to be reasonably analogous to the readable stream\nfield of the same name.\n\n### slicer.setIncomingEncoding(name)\n\nSets the incoming encoding of the source stream. This is the encoding\nto use when interpreting strings that arrive in `data` events.\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n### slicer.gotError() => boolean\n\nIndicates whether the upstream source has indicated an error condition.\nThis is out-of-band with respect to the data, in that there may still\nbe data that can be successfully read even if this method returns `true`.\n\nThis method exists to help disambiguate the case of not\nhaving gotten an error indicator from the case of having gotten an\nerror indicator but without any error instance payload.\n\n### slicer.getError() => any\n\nGets the error payload that was reported from upstream, if any.\nThis is out-of-band with respect to the data, in that there may still\nbe data that can be successfully read even if this method returns a\ndefined value.\n\nThis will always return `undefined`, unless the upstream source\nreported an error with a defined payload.\n\n### slicer.readAll(callback)\n\nReads as much data as possible from the stream, blocking the callback\n*only* in order to make it to the head of the read queue.\n\nTo be clear, if there is no data available in the slicer at the time\nthis read becomes potentially-serviced, then it will in fact get\nserviced, with the callback indicating that zero bytes were read\nwithout error.\n\nThe `buffer` in the callback will always be a freshly-allocated buffer\nthat does not share its data with any other instance.\n\n### slicer.read(length, callback)\n\nReads exactly `length` bytes of data from the stream if at all\npossible, blocking the callback until either `length` bytes are\navailable or the stream has ended (either normally or with an error).\n\nIf `length` is passed as `0` it means \"read zero bytes\". This can be\nuseful as a way to insert a no-data \"sentinal\" callback into the\nsequence of callbacks coming from this instance.\n\nTo be clear, the callback will only ever indicate a shorter `length`\nthan requested if the upstream source ends without at least `length`\nbytes being available. If a short read ends up happening, then the\ncallback will get passed `true` for the error flag.\n\nThe `buffer` in the callback will always be a freshly-allocated buffer\nthat does not share its data with any other instance.\n\n### slicer.readInto(buffer, offset, length, callback)\n\nReads some amount of data from the stream into the indicated `buffer`\n(which must be a `Buffer` instance), starting at the indicated\n`offset` and reading exactly `length` bytes if at all possible.\n\nIf `offset` is passed as `undefined` it defaults to `0`.\n\nIf `length` is passed as `undefined` it means \"read as much as\npossible without blocking\". This is different than passing `0` which\nmeans simply \"read zero bytes\". (This latter case can actually be\nuseful. See `slicer.read(length, callback)` above.)\n\nAs with `read()`, the only time the length will be shorter than what\nwas requested will be if the stream ends without there being at least\n`length` bytes to read. If a short read ends up happening, then the\ncallback will get passed `true` for the error flag.\n\n\nValve\n-----\n\nThe `Valve` class is a bufferer of readable stream events, which\nrelays those events consistently. It handles pause/resume semantics,\nand it will always translate incoming values that aren't buffers into\nbuffers, using a specified and settable incoming encoding.\n\nOne of the major use cases of this class is to use it to capture the\ndata coming from a network stream that's already in the middle of\nproducing data, particularly when you don't immediately know where\nthat data needs to go to. The author has run into this on multiple\noccasions when trying hand off reading from an HTTP connection\nacross a tick boundary, along these lines for example (obviously\nsimplified here):\n\n```javascript\nvar thingThatWantsToRead = {\n  startReading: function (stream) {\n    stream.on(\"data\", ...);\n    stream.resume();\n    ...\n  },\n  ...\n}\n\nfunction httpRequestCallback(request, response) {\n  var valve = new Valve(request, true);\n\n  process.nextTick(function () {\n    thingThatWantsToRead.startReading(valve);\n  });\n}\n```\n\nAnother handy use for Valve is *just* to provide consistent data\npayloads (always buffers, or always properly encoded strings) and the\nconsistent event ordering generally guaranteed by this module. In\nparticular on the event type front, the standard Node HTTP and HTTPS\nstreams are inconsistent with the core `Stream` in that they can emit\n`close` events that contain either a boolean error flag or a full-on\n`Error` instance. By layering a `Valve` on top of them, these get\ntranslated into a consistent `error`-then-`close` sequence.\n\nSimilarly, if you want to implement a `Stream` as part of your own API\nbut don't want to deal with all the fiddly bits, you can write a\nstraightforward `EventEmitter`, and then expose it via a Valve, as in:\n\n```javascript\nfunction MyEventEmitter() {\n  events.EventEmitter.call(this);\n  ...\n}\n\nutil.inherits(this, events.EventEmitter);\n\nfunction createMyStream() {\n  var coreEmitter = new MyEventEmitter();\n  return new pipette.Valve(coreEmitter);\n}\n```\n\nThe Valve will \"sanitize\" the events coming from your class, while\nalso providing the rest of the core readable Stream API.\n\n### var valve = new Valve(source, [options])\n\nConstructs and returns a new valve, which listens to the given source.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n### valve.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\n* * * * * * * * * *\n\nTo Do\n-----\n\n* Consider adding a common option of `pressure: boolean` to indicate\n  whether `pause()` and `resume()` should recurse upstream.\n\n\nContributing\n------------\n\nQuestions, comments, bug reports, and pull requests are all welcome.\nSubmit them at [the project on GitHub](https://github.com/Obvious/pipette/).\n\nBug reports that include steps-to-reproduce (including code) are the\nbest. Even better, make them in the form of pull requests that update\nthe test suite. Thanks!\n\n\nAuthor\n------\n\n[Dan Bornstein](https://github.com/danfuzz)\n([personal website](http://www.milk.com/)), supported by\n[The Obvious Corporation](http://obvious.com/).\n\nThanks to <https://github.com/rootslab/dropper> for the name of the\n`Dropper` class.\n\n\nLicense\n-------\n\nCopyright 2012 [The Obvious Corporation](http://obvious.com/).\n\nLicensed under the Apache License, Version 2.0.\nSee the top-level file `LICENSE.txt` and\n(http://www.apache.org/licenses/LICENSE-2.0).\n\n\n","_id":"pipette@0.9.1","dist":{"shasum":"8ffee7d16173a12eb074332c37d6b1acd732a617","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.9.1.tgz","integrity":"sha512-rPgYcnG11zTaq4+kiBgDyVhWYgMXmsT7L43sRM3FwcHnuMvS/mkwTCckdu3GTGDLNotRPf+eqAIewytYfsvmJw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF+DvupQadA+cOmvv+IeWJnOTGvKOz15WGUSkjVIW4PkAiEAwdpeuD2NTeZmRympUbPqRxwGKhEy/ck0m+aETerBkhM="}]},"_npmVersion":"1.1.59","_npmUser":{"name":"danfuzz","email":"danfuzz@milk.com"}},"0.9.2":{"name":"pipette","version":"0.9.2","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read","dropper"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"https://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"},{"name":"dpup","email":"dan@pupi.us"},{"name":"nicks","email":"nicholas.j.santos@gmail.com"},{"name":"azulus","email":"jeremy@obvious.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"readme":"pipette: Stream and pipe utilities for Node\n===========================================\n\nThis Node module provides several utility classes that offer\npipe and stream-related functionality. It particularly emphasizes\nproviding a consistent event packaging and ordering for streams.\n\n\nBuilding and Installing\n-----------------------\n\n```shell\nnpm install pipette\n```\n\nOr grab the source and\n\n```shell\nnpm install\n```\n\n\nTesting\n-------\n\n```shell\nnpm test\n```\n\nOr\n\n```shell\nnode ./test/test.js\n```\n\n\nEvent Sequence Philosophy\n-------------------------\n\nAll of the classes in this module provide a consistently ordered\nsequence of events, which is meant to be a sensible synthesis of the\n(somewhat inconsistent) Node specification for the various core\nstream classes.\n\nIn particular, a stream will emit some number of `data` events\n(possibly zero), each with a single payload argument. This will be\nfollowed by *either* an `end` event with no payload or an `error`\nevent with an arbitrary payload. This is followed by a `close` event\nwith no payload. After that, a stream will not emit any further\nevents, and it is furthermore guaranteed to be detached from its\nupstream source(s), if any.\n\nMore schematically, as a \"railroad\" diagram:\n\n```\n        +--------------------+      +-------+\n        |                    |   +->| end() |----------+\n        v  +---------------+ |   |  +-------+          |  +---------+\n(start)-+->| data(payload) |-+-+-+                     +->| close() |->(finish)\n        |  +---------------+   ^ |  +----------------+ |  +---------+\n        |                      | +->| error(payload) |-+\n        +----------------------+    +----------------+\n```\n\nOf particular note are the cases of inconsistently-defined `close`\nevents. Some streams (core Node stream classes, for example) will emit\na `close` event with a non-empty payload value to indicate an\nunexpected termination. The classes in this module consistently\ntranslate such cases to an `error` event with the error payload\nfollowed by a no-payload `close` event. For the purposes of this\nmodule, a \"non-empty payload\" is one that is neither `undefined` nor\n`false`. This takes care of the quirky definitions of `net.Socket`\n(which includes a boolean error indicator in its `close` event) and\n`http.ClientResponse` (which may include an arbitrary error object in\nits `close` event).\n\nThe particularly nice thing about this arrangement is that if one\nwants to consistently do something after a stream has finished, one\ncan write the something in question as a `close` event handler, rather\nthan splaying the logic between both an `end` and an `error` handler.\n\nIn the rest of the documentation, it should be taken as implicit that\nall the classes' event sequences follow this order.\n\n\nLayering Philosophy\n-------------------\n\nFour of these classes (`Cat`, `Sink`, `Slicer`, and `Valve`) provide a\nlayer on top of other streams. The implementation philosophy is that\nthese listen for events from their \"upstream\" sources, but they do not\notherwise attempt to interact with those streams. In particular:\n\n* They do not make upstream calls to the flow-control methods\n  `pause()` and `resume()`.\n\n* They do not attempt to make upstream `setEncoding()` calls.\n\n* They do not call upstream `destroy()` even when they themselves are\n  being `destroy()`ed.\n\nIn addition, these layering classes check upon construction that their\nupstream sources are in fact streams that have not yet been ended\n(that is, that they are still capable of emitting events). If a stream\nsource argument fails this check, then the constructor call will throw\nan exception indicating that fact. The check is somewhat conservative\n(on the side of accepting) and meant to accept stream-like event\nemitters in addition to checking bona fide `Stream` instances.\nDetails: If a given source is a `Stream` per se, then the value of\n`source.readable` is taken at face value. Otherwise, a source is\nconsidered to be ended if and only if it (or a prototype in its chain)\ndefines a `readable` property and that property's value is falsey.\n\n### Constructing stacked readers\n\nMany Node stream classes are designed as an atomic unit that includes\nboth reader and writer methods intermingled in a single object. This\nmodule takes a different tack:\n\n* Any given object is either a reader or a writer, never both.\n\n* To pass one reader's event output to another, construct the destination\n  object passing it the source, e.g. `new Valve(new OtherStream(...))`.\n\n### Getting a writer\n\nIf you need to get a writer to write into one of the reader classes\n(or a stack of same), you can use a `Pipe`:\n\n```javascript\nvar pipe = new Pipe();\nvar readerStack = new OtherStream(pipe.reader);\nvar writer = pipe.writer;\n\nwriter.write(...); // What's written here will get read by the OtherStream.\n```\n\n\nA Note About Encodings\n----------------------\n\nNode 0.6.* and 0.8.* differ in their documentation about which encodings\nare allowed by `setEncoding()`. This module accepts the union of the\nencodings specified by those. This includes:\n\n* `ascii` &mdash; 7-bit ASCII\n* `base64` &mdash; standard Base-64 encoding for binary data\n* `hex` &mdash; hex encoding for binary data (two hexadecimal ASCII\n  characters per byte)\n* `ucs2` &mdash; alias for `utf16le` (below). This is not technically correct\n  (per Unicode spec), but it is how Node is defined.\n* `utf16le` &mdash; standard little-endian UTF-16 encoding for Unicode data\n* `utf8` &mdash; standard UTF-8 encoding for Unicode data\n\n\nCommon Options\n--------------\n\nAll of the classes in this module take an optional `options`\nconstructor parameter. If not `undefined`, this must be a map from\noption names to values as specified by the class.\n\nThe following are three commonly-accepted options. Classes all accept\nwhichever of these make sense.\n\n* `encoding` &mdash; A string representing the encoding to use when\n  emitting events. Passing this option is exactly like calling\n  `setEncoding()` on the constructed instance.\n\n* `incomingEncoding` &mdash; A string representing the incoming\n  encoding to use when interpreting incoming `data` events that arrive\n  as strings (as opposed to buffers). Passing this option is exactly\n  like calling `setIncomingEncoding()` on the constructed instance.\n\n* `paused` &mdash; A boolean value indicating whether the instance\n  should be immediately paused. For most classes, this is exactly like\n  calling `pause()` on the constructed instance.\n\n\n* * * * * * * * * *\n\nAPI Details\n===========\n\nBlip\n----\n\nThe `Blip` class exists to emit a single `data` event.\n\nThis class is useful if you have data that you need to re-emit.\n\n### var blip = new Blip([data], [options])\n\nConstructs and returns a new blip which is to emit the given `data`\n(a string or buffer) once unpaused. After emitting the `data` event,\nblips always also emit an `end` and a `close` event (in that order).\n\nOf the common options, Blip recognizes `encoding` and\n`incomingEncoding`, though the latter is with a twist: The\n`incomingEncoding` (either as specified or with the default behavior)\napplies immediately to the given `data`, in order to transform it into\na buffer. That is, if `data` is passed as a string, it will always get\nimmediately transformed into a buffer, when an instance is\nconstructed.\n\nIf `data` is omitted, then the resulting blip will *just* emit the\nending events, without a `data` event first.\n\nBlips start out paused, since there is not much point in them\nimmediately emitting their contents upon construction (as there\nwill necessarily be no listeners at that moment).\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n\nCat\n---\n\nThe `Cat` class (short for \"concatenate\" and by analogy with the\ntraditional Unix command with the same name) emits the events from\na sequence of streams, in the order of the given sequence (i.e.\nnot interspersed).\n\nThis can be used, for example, to produce a stream that is prefixed\nor suffixed with a given bit of data (when used in combination with\n`Blip`, above).\n\n### var cat = new Cat(streams, [options])\n\nConstructs and returns a new cat which is to emit the events from\nthe given streams (each of which must be an `EventEmitter` and is\nassumed to emit the standard Node readable stream events).\n\nThe data events from each stream (in order) are in turn emitted by\nthis instance, switching to the next stream when the current stream\nemits either an `end` or `close` event. After all the streams have\nbeen \"consumed\" in this fashion, this instance emits an `end` and then\na `close` event.\n\nIf a stream should emit an `error` event, then that event is in turn\nemitted by this instance, after which this instance emits a `close`\nevent. It will then become closed (emitting no further events, and\nproducing `false` for `cat.readable`).\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n### cat.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nDropper\n-------\n\nThe `Dropper` class is a bufferer of readable stream events, which\nrelays those events in fixed size blocks (or multiples thereof),\na.k.a. \"drops\" (hence the name). It handles pause/resume semantics,\nand it will always translate incoming values that aren't buffers into\nbuffers, using a specified and settable incoming encoding.\n\nThe only exception to the block size is that the last `data` event\nfrom a Dropper may have a smaller size, if the last data it received\n(before an `end` or `error`) would not end up filling up a block of\nthe specified size. In this case, the behavior is specified by\nthe `ifPartial` option (see below).\n\nOther than the fixed-size block part, the semantics of this class are\nbasically the same as the simpler `Valve` class (see below).\n\n### var dropper = new Dropper(source, [options])\n\nConstructs and returns a new dropper, which listens to the given source.\nThis takes an optional `options` argument, which if present must be\na map of options, including any of the common options (see above)\nas well as any of the following:\n\n* `size` &mdash; block (aka drop) size in bytes. Must be a positive\n  integer. Defaults to `1`.\n\n* `allowMultiple` &mdash; whether emitted data events are to be the\n   exact block size (`false`) or may be an even multiple of the block\n   size (`true`). Must be a boolean. Defaults to `false`.\n\n* `ifPartial` &mdash; what to do with a partial block at the\n   end of the stream; one of `emit` (emit it as-is),\n   `ignore` (drop it entirely), `pad` (zero-pad), `error` (emit\n   an error). Defaults to `emit`.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n(Note: As of this writing, this is the only one of the classes in this\nmodule that takes an options object on construction. It is likely that\nthe rest of the classes will migrate to this form.)\n\n### dropper.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nPipe\n----\n\nThe `Pipe` class is a simple in-memory pipe, which provides writer and\nreader ends. Pipes handle data encoding and obey pause/resume semantics.\n\nThis class is useful if you have code that wants to call writable stream\nstyle methods, and you want it to be directly attached to some other code\nthat expects to be listening for events. For example:\n\n```javascript\nvar listeningThingy = ...;\nvar writingThingy = ...;\n\nvar pipe = new Pipe();\nlisteningThingy.listenTo(pipe.reader);\nwritingThingy.writeTo(pipe.writer);\n```\n\n### var pipe = new Pipe([options])\n\nConstructs and returns a new pipe pair. The result is an object with\nmappings for `{ reader, writer }` for the two ends of the pipe.\n\nThe reader and writer side each implement the standard Node stream\nprotocol for readable and writable streams (respectively).\n\nThe specified protocol allows writers to ignore the `fd` argument\nto `stream.write()`, and this implementation in fact ignores it.\n\nOf the common options, the constructor accepts `encoding` and `paused`,\nwhich both apply to the reader end of the pipe.\n\n\nSink\n----\n\nThe `Sink` class is an in-memory collector of all the data read from a\ngiven stream. It is in turn itself a stream that emits no more than a\nsingle `data` event consisting of all of the data it received, once\nits upstream source has ended. It also has direct accessors method to\nget at the data or a stream-ending error, to provide a bit of\nflexibility in how the class is used.\n\nThis class is useful for cases where you don't care about incremental\nprocessing and just want to deal with the whole enchilada (as it\nwere). This can be used to collect an entire post body from an HTTP\nrequest, for example:\n\n```javascript\nvar httpServer = http.createServer(onRequest);\n\nfunction onRequest(request, response) {\n  var postData = new Sink(request);\n  postData.on(\"data\", onPostData);\n\n  function onPostData(data) {\n    console.log(\"Got post:\", data.toString());\n  }\n}\n```\n\n### var sink = new Sink(source, [options])\n\nConstructs and returns a new sink, which listens to the given source\nstream. Once the stream has ended (via either an `end` or `close`\nevent), this instance emits a single `data` event containing all\nof the data received from the source (if there was any data at all),\nfollowed by an `end` and then a `close` event.\n\nIf the source should ever emit an `error` event, then this will cause\nthe sink instance to first emit any data it received (as a single\n`data` event), followed by an `error` event that corresponds to the\none it received, and finally followed by a `close` event. After that,\nit will emit no further events.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\nIn addition to being readable streams, sinks have a few more methods.\n\n### sink.getData() => buffer || string || undefined\n\nGets the final complete data for the sink, if available.\n\nIf the sink's source has not yet ended, or if it ended without\never emitting any data, this returns `undefined`.\n\nIf the sink received any data and has a specified encoding (via\n`setEncoding()`), this returns the string form of the data, as decoded\nusing the named encoding.\n\nIf the sink received any data but has no specified encoding, this\nreturns the straight buffer of data.\n\nNote that this method can return a defined (that is, not `undefined`)\nvalue before the corresponding `data` event is emitted, particularly\nif the sink happens to be paused at the time the upstream stream is\nended.\n\nAlso note that there is a bit of ambiguity with this method, in terms of\ndifferentiating a stream that got ended with no data ever received\nwith one that simply hasn't yet ended. Instead of using this method\nfor that purpose, use `sink.readable` (part of the standard readable\nstream protocol).\n\n### sink.getError() => any\n\nGets the error that terminated the upstream source, if available.\n\nIf the sink's source has not yet ended, or if it ended normally, this\nreturns `undefined`.\n\nIf the sink's source ended with an `error` event, then this returns the\nsame value that was received in that error event.\n\nNote that this method can return a defined (not `undefined`) value\nbefore the corresponding `error` event is emitted, particularly if the\nsink happens to be paused at the time the upstream stream reports its\nerror.\n\nAlso note that there is a bit of ambiguity in terms of interpreting a\nstream that got ended with an `error` event whose payload is\n`undefined`. If you need to account for this possibility, use\n`sink.gotError()`.\n\n### sink.gotError() => boolean\n\nGets whether or not the upstream source was ended with an error.\n\nThis returns `false` if the source has not yet ended, or if it ended\nnormally.\n\nThis returns `true` if and only if the upstream source emitted an\n`error` event that this sink instance received.\n\nNote that this method can return `true` before the corresponding\n`error` event is emitted, particularly if the sink happens to be\npaused at the time the upstream stream reports its error.\n\n### sink.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nSlicer\n------\n\nThe `Slicer` class (like `Sink`) is an in-memory bufferer of data\nread from a given stream. In turn, it provides a `fs.read()` style\ninterface to get at the data so-read.\n\nAs the name implies, this class is useful for slicing up a stream\ninto chunks that aren't (necessarily) the same shape as the ones\nthat came in as `data` events.\n\nMost of the \"interesting\" methods on the class take a callback\nargument to receive data back from the instance. These are all\nconsistently called as `callback(error, length, buffer, offset)` with\nno `this` and with arguments defined as follows:\n\n* `error` &mdash; a boolean flag indicating whether the read was cut short\n  due to an error *or* because there was insufficient data to fully\n  comply with the request. (Note: This is different than `fs.read()`\n  which passes an error object here. See `slicer.gotError()` below for\n  an explanation of why.)\n\n* `length` &mdash; the number of bytes read.\n\n* `buffer` &mdash; the buffer that was read into.\n\n* `offset` &mdash; the offset into `buffer` where the reading was done.\n\nThe ordering and meaning of the callback arguments are meant to be (a)\ncompatible with callbacks used with `fs.read()` and (b) somewhat more\ninformative and unambiguous.\n\n### var slicer = new Slicer(source, [options])\n\nConstructs a new slicer, which listens to the given source.\n\nOf the common options, the only one recognized by this class is\n`incomingEncoding`. The class accepts no other options.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\n\n### slicer.readable => boolean\n\nThis indicates whether there is any data left to be read in the stream\nor whether there *could* be any day left to be read.\n\nIn particular, this only becomes `false` when it is both the case that\nthe buffer of pending data is empty *and* the upstream source has ended.\n\nThis field is meant to be reasonably analogous to the readable stream\nfield of the same name.\n\n### slicer.destroy()\n\nCauses the instance to be cleaned up and become closed. In particular,\nit includes detaching from the upstream source. After this method is\ncalled, other methods on this class will behave as if the upstream\nsource ended with no error.\n\nThis method is meant to be reasonably analogous to the readable stream\nfield of the same name.\n\n### slicer.setIncomingEncoding(name)\n\nSets the incoming encoding of the source stream. This is the encoding\nto use when interpreting strings that arrive in `data` events.\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n### slicer.gotError() => boolean\n\nIndicates whether the upstream source has indicated an error condition.\nThis is out-of-band with respect to the data, in that there may still\nbe data that can be successfully read even if this method returns `true`.\n\nThis method exists to help disambiguate the case of not\nhaving gotten an error indicator from the case of having gotten an\nerror indicator but without any error instance payload.\n\n### slicer.getError() => any\n\nGets the error payload that was reported from upstream, if any.\nThis is out-of-band with respect to the data, in that there may still\nbe data that can be successfully read even if this method returns a\ndefined value.\n\nThis will always return `undefined`, unless the upstream source\nreported an error with a defined payload.\n\n### slicer.readAll(callback)\n\nReads as much data as possible from the stream, blocking the callback\n*only* in order to make it to the head of the read queue.\n\nTo be clear, if there is no data available in the slicer at the time\nthis read becomes potentially-serviced, then it will in fact get\nserviced, with the callback indicating that zero bytes were read\nwithout error.\n\nThe `buffer` in the callback will always be a freshly-allocated buffer\nthat does not share its data with any other instance.\n\n### slicer.read(length, callback)\n\nReads exactly `length` bytes of data from the stream if at all\npossible, blocking the callback until either `length` bytes are\navailable or the stream has ended (either normally or with an error).\n\nIf `length` is passed as `0` it means \"read zero bytes\". This can be\nuseful as a way to insert a no-data \"sentinal\" callback into the\nsequence of callbacks coming from this instance.\n\nTo be clear, the callback will only ever indicate a shorter `length`\nthan requested if the upstream source ends without at least `length`\nbytes being available. If a short read ends up happening, then the\ncallback will get passed `true` for the error flag.\n\nThe `buffer` in the callback will always be a freshly-allocated buffer\nthat does not share its data with any other instance.\n\n### slicer.readInto(buffer, offset, length, callback)\n\nReads some amount of data from the stream into the indicated `buffer`\n(which must be a `Buffer` instance), starting at the indicated\n`offset` and reading exactly `length` bytes if at all possible.\n\nIf `offset` is passed as `undefined` it defaults to `0`.\n\nIf `length` is passed as `undefined` it means \"read as much as\npossible without blocking\". This is different than passing `0` which\nmeans simply \"read zero bytes\". (This latter case can actually be\nuseful. See `slicer.read(length, callback)` above.)\n\nAs with `read()`, the only time the length will be shorter than what\nwas requested will be if the stream ends without there being at least\n`length` bytes to read. If a short read ends up happening, then the\ncallback will get passed `true` for the error flag.\n\n\nValve\n-----\n\nThe `Valve` class is a bufferer of readable stream events, which\nrelays those events consistently. It handles pause/resume semantics,\nand it will always translate incoming values that aren't buffers into\nbuffers, using a specified and settable incoming encoding.\n\nOne of the major use cases of this class is to use it to capture the\ndata coming from a network stream that's already in the middle of\nproducing data, particularly when you don't immediately know where\nthat data needs to go to. The author has run into this on multiple\noccasions when trying hand off reading from an HTTP connection\nacross a tick boundary, along these lines for example (obviously\nsimplified here):\n\n```javascript\nvar thingThatWantsToRead = {\n  startReading: function (stream) {\n    stream.on(\"data\", ...);\n    stream.resume();\n    ...\n  },\n  ...\n}\n\nfunction httpRequestCallback(request, response) {\n  var valve = new Valve(request, true);\n\n  process.nextTick(function () {\n    thingThatWantsToRead.startReading(valve);\n  });\n}\n```\n\nAnother handy use for Valve is *just* to provide consistent data\npayloads (always buffers, or always properly encoded strings) and the\nconsistent event ordering generally guaranteed by this module. In\nparticular on the event type front, the standard Node HTTP and HTTPS\nstreams are inconsistent with the core `Stream` in that they can emit\n`close` events that contain either a boolean error flag or a full-on\n`Error` instance. By layering a `Valve` on top of them, these get\ntranslated into a consistent `error`-then-`close` sequence.\n\nSimilarly, if you want to implement a `Stream` as part of your own API\nbut don't want to deal with all the fiddly bits, you can write a\nstraightforward `EventEmitter`, and then expose it via a Valve, as in:\n\n```javascript\nfunction MyEventEmitter() {\n  events.EventEmitter.call(this);\n  ...\n}\n\nutil.inherits(this, events.EventEmitter);\n\nfunction createMyStream() {\n  var coreEmitter = new MyEventEmitter();\n  return new pipette.Valve(coreEmitter);\n}\n```\n\nThe Valve will \"sanitize\" the events coming from your class, while\nalso providing the rest of the core readable Stream API.\n\n### var valve = new Valve(source, [options])\n\nConstructs and returns a new valve, which listens to the given source.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n### valve.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\n* * * * * * * * * *\n\nTo Do\n-----\n\n* Consider adding a common option of `pressure: boolean` to indicate\n  whether `pause()` and `resume()` should recurse upstream.\n\n\nContributing\n------------\n\nQuestions, comments, bug reports, and pull requests are all welcome.\nSubmit them at [the project on GitHub](https://github.com/Obvious/pipette/).\n\nBug reports that include steps-to-reproduce (including code) are the\nbest. Even better, make them in the form of pull requests that update\nthe test suite. Thanks!\n\n\nAuthor\n------\n\n[Dan Bornstein](https://github.com/danfuzz)\n([personal website](http://www.milk.com/)), supported by\n[The Obvious Corporation](http://obvious.com/).\n\nThanks to <https://github.com/rootslab/dropper> for the name of the\n`Dropper` class.\n\n\nLicense\n-------\n\nCopyright 2012 [The Obvious Corporation](http://obvious.com/).\n\nLicensed under the Apache License, Version 2.0.\nSee the top-level file `LICENSE.txt` and\n(http://www.apache.org/licenses/LICENSE-2.0).\n\n\n","readmeFilename":"README.md","_id":"pipette@0.9.2","dist":{"shasum":"7c34b878390a48c21942c2a904fb7d5a1de537b3","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.9.2.tgz","integrity":"sha512-rlVegEQpZpvnIdtTpIA8K0bhPw5lkeRIuC+FKNUP1IB4Lb+MnPU7hjqb+FnA05UvNMxeV+XarZF+mTAC0DfjYA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2E0oB9y4BqLIZgKQUl5AgSGOdsPXimJv+p+BIlVw6zwIgEk2mf6V/SgWBCZeWAGDjUCeZqVzjJVCSWy2dJk3NL9I="}]},"_from":".","_npmVersion":"1.2.14","_npmUser":{"name":"dpup","email":"dan@pupi.us"}},"0.9.3":{"name":"pipette","version":"0.9.3","keywords":["stream","pipe","buffer","valve","data","event","blip","cat","sink","slicer","reader","read","dropper"],"description":"Stream and pipe utilities for Node","homepage":"https://github.com/Obvious/pipette","repository":{"type":"git","url":"https://github.com/Obvious/pipette.git"},"licenses":[{"type":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}],"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"},{"name":"dpup","email":"dan@pupi.us"},{"name":"nicks","email":"nicholas.j.santos@gmail.com"},{"name":"azulus","email":"jeremy@obvious.com"}],"dependencies":{"typ":"~0.6.1"},"main":"lib/pipette.js","engine":{"node":">=0.6.0"},"scripts":{"test":"node test/test.js"},"readme":"pipette: Stream and pipe utilities for Node\n===========================================\n\nThis Node module provides several utility classes that offer\npipe and stream-related functionality. It particularly emphasizes\nproviding a consistent event packaging and ordering for streams.\n\n\nBuilding and Installing\n-----------------------\n\n```shell\nnpm install pipette\n```\n\nOr grab the source and\n\n```shell\nnpm install\n```\n\n\nTesting\n-------\n\n```shell\nnpm test\n```\n\nOr\n\n```shell\nnode ./test/test.js\n```\n\n\nEvent Sequence Philosophy\n-------------------------\n\nAll of the classes in this module provide a consistently ordered\nsequence of events, which is meant to be a sensible synthesis of the\n(somewhat inconsistent) Node specification for the various core\nstream classes.\n\nIn particular, a stream will emit some number of `data` events\n(possibly zero), each with a single payload argument. This will be\nfollowed by *either* an `end` event with no payload or an `error`\nevent with an arbitrary payload. This is followed by a `close` event\nwith no payload. After that, a stream will not emit any further\nevents, and it is furthermore guaranteed to be detached from its\nupstream source(s), if any.\n\nMore schematically, as a \"railroad\" diagram:\n\n```\n        +--------------------+      +-------+\n        |                    |   +->| end() |----------+\n        v  +---------------+ |   |  +-------+          |  +---------+\n(start)-+->| data(payload) |-+-+-+                     +->| close() |->(finish)\n        |  +---------------+   ^ |  +----------------+ |  +---------+\n        |                      | +->| error(payload) |-+\n        +----------------------+    +----------------+\n```\n\nOf particular note are the cases of inconsistently-defined `close`\nevents. Some streams (core Node stream classes, for example) will emit\na `close` event with a non-empty payload value to indicate an\nunexpected termination. The classes in this module consistently\ntranslate such cases to an `error` event with the error payload\nfollowed by a no-payload `close` event. For the purposes of this\nmodule, a \"non-empty payload\" is one that is neither `undefined` nor\n`false`. This takes care of the quirky definitions of `net.Socket`\n(which includes a boolean error indicator in its `close` event) and\n`http.ClientResponse` (which may include an arbitrary error object in\nits `close` event).\n\nThe particularly nice thing about this arrangement is that if one\nwants to consistently do something after a stream has finished, one\ncan write the something in question as a `close` event handler, rather\nthan splaying the logic between both an `end` and an `error` handler.\n\nIn the rest of the documentation, it should be taken as implicit that\nall the classes' event sequences follow this order.\n\n\nLayering Philosophy\n-------------------\n\nFour of these classes (`Cat`, `Sink`, `Slicer`, and `Valve`) provide a\nlayer on top of other streams. The implementation philosophy is that\nthese listen for events from their \"upstream\" sources, but they do not\notherwise attempt to interact with those streams. In particular:\n\n* They do not make upstream calls to the flow-control methods\n  `pause()` and `resume()`.\n\n* They do not attempt to make upstream `setEncoding()` calls.\n\n* They do not call upstream `destroy()` even when they themselves are\n  being `destroy()`ed.\n\nIn addition, these layering classes check upon construction that their\nupstream sources are in fact streams that have not yet been ended\n(that is, that they are still capable of emitting events). If a stream\nsource argument fails this check, then the constructor call will throw\nan exception indicating that fact. The check is somewhat conservative\n(on the side of accepting) and meant to accept stream-like event\nemitters in addition to checking bona fide `Stream` instances.\nDetails: If a given source is a `Stream` per se, then the value of\n`source.readable` is taken at face value. Otherwise, a source is\nconsidered to be ended if and only if it (or a prototype in its chain)\ndefines a `readable` property and that property's value is falsey.\n\n### Constructing stacked readers\n\nMany Node stream classes are designed as an atomic unit that includes\nboth reader and writer methods intermingled in a single object. This\nmodule takes a different tack:\n\n* Any given object is either a reader or a writer, never both.\n\n* To pass one reader's event output to another, construct the destination\n  object passing it the source, e.g. `new Valve(new OtherStream(...))`.\n\n### Getting a writer\n\nIf you need to get a writer to write into one of the reader classes\n(or a stack of same), you can use a `Pipe`:\n\n```javascript\nvar pipe = new Pipe();\nvar readerStack = new OtherStream(pipe.reader);\nvar writer = pipe.writer;\n\nwriter.write(...); // What's written here will get read by the OtherStream.\n```\n\n\nA Note About Encodings\n----------------------\n\nNode 0.6.* and 0.8.* differ in their documentation about which encodings\nare allowed by `setEncoding()`. This module accepts the union of the\nencodings specified by those. This includes:\n\n* `ascii` &mdash; 7-bit ASCII\n* `base64` &mdash; standard Base-64 encoding for binary data\n* `hex` &mdash; hex encoding for binary data (two hexadecimal ASCII\n  characters per byte)\n* `ucs2` &mdash; alias for `utf16le` (below). This is not technically correct\n  (per Unicode spec), but it is how Node is defined.\n* `utf16le` &mdash; standard little-endian UTF-16 encoding for Unicode data\n* `utf8` &mdash; standard UTF-8 encoding for Unicode data\n\n\nCommon Options\n--------------\n\nAll of the classes in this module take an optional `options`\nconstructor parameter. If not `undefined`, this must be a map from\noption names to values as specified by the class.\n\nThe following are three commonly-accepted options. Classes all accept\nwhichever of these make sense.\n\n* `encoding` &mdash; A string representing the encoding to use when\n  emitting events. Passing this option is exactly like calling\n  `setEncoding()` on the constructed instance.\n\n* `incomingEncoding` &mdash; A string representing the incoming\n  encoding to use when interpreting incoming `data` events that arrive\n  as strings (as opposed to buffers). Passing this option is exactly\n  like calling `setIncomingEncoding()` on the constructed instance.\n\n* `paused` &mdash; A boolean value indicating whether the instance\n  should be immediately paused. For most classes, this is exactly like\n  calling `pause()` on the constructed instance.\n\n\n* * * * * * * * * *\n\nAPI Details\n===========\n\nBlip\n----\n\nThe `Blip` class exists to emit a single `data` event.\n\nThis class is useful if you have data that you need to re-emit.\n\n### var blip = new Blip([data], [options])\n\nConstructs and returns a new blip which is to emit the given `data`\n(a string or buffer) once unpaused. After emitting the `data` event,\nblips always also emit an `end` and a `close` event (in that order).\n\nOf the common options, Blip recognizes `encoding` and\n`incomingEncoding`, though the latter is with a twist: The\n`incomingEncoding` (either as specified or with the default behavior)\napplies immediately to the given `data`, in order to transform it into\na buffer. That is, if `data` is passed as a string, it will always get\nimmediately transformed into a buffer, when an instance is\nconstructed.\n\nIf `data` is omitted, then the resulting blip will *just* emit the\nending events, without a `data` event first.\n\nBlips start out paused, since there is not much point in them\nimmediately emitting their contents upon construction (as there\nwill necessarily be no listeners at that moment).\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n\nCat\n---\n\nThe `Cat` class (short for \"concatenate\" and by analogy with the\ntraditional Unix command with the same name) emits the events from\na sequence of streams, in the order of the given sequence (i.e.\nnot interspersed).\n\nThis can be used, for example, to produce a stream that is prefixed\nor suffixed with a given bit of data (when used in combination with\n`Blip`, above).\n\n### var cat = new Cat(streams, [options])\n\nConstructs and returns a new cat which is to emit the events from\nthe given streams (each of which must be an `EventEmitter` and is\nassumed to emit the standard Node readable stream events).\n\nThe data events from each stream (in order) are in turn emitted by\nthis instance, switching to the next stream when the current stream\nemits either an `end` or `close` event. After all the streams have\nbeen \"consumed\" in this fashion, this instance emits an `end` and then\na `close` event.\n\nIf a stream should emit an `error` event, then that event is in turn\nemitted by this instance, after which this instance emits a `close`\nevent. It will then become closed (emitting no further events, and\nproducing `false` for `cat.readable`).\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n### cat.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nDropper\n-------\n\nThe `Dropper` class is a bufferer of readable stream events, which\nrelays those events in fixed size blocks (or multiples thereof),\na.k.a. \"drops\" (hence the name). It handles pause/resume semantics,\nand it will always translate incoming values that aren't buffers into\nbuffers, using a specified and settable incoming encoding.\n\nThe only exception to the block size is that the last `data` event\nfrom a Dropper may have a smaller size, if the last data it received\n(before an `end` or `error`) would not end up filling up a block of\nthe specified size. In this case, the behavior is specified by\nthe `ifPartial` option (see below).\n\nOther than the fixed-size block part, the semantics of this class are\nbasically the same as the simpler `Valve` class (see below).\n\n### var dropper = new Dropper(source, [options])\n\nConstructs and returns a new dropper, which listens to the given source.\nThis takes an optional `options` argument, which if present must be\na map of options, including any of the common options (see above)\nas well as any of the following:\n\n* `size` &mdash; block (aka drop) size in bytes. Must be a positive\n  integer. Defaults to `1`.\n\n* `allowMultiple` &mdash; whether emitted data events are to be the\n   exact block size (`false`) or may be an even multiple of the block\n   size (`true`). Must be a boolean. Defaults to `false`.\n\n* `ifPartial` &mdash; what to do with a partial block at the\n   end of the stream; one of `emit` (emit it as-is),\n   `ignore` (drop it entirely), `pad` (zero-pad), `error` (emit\n   an error). Defaults to `emit`.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n(Note: As of this writing, this is the only one of the classes in this\nmodule that takes an options object on construction. It is likely that\nthe rest of the classes will migrate to this form.)\n\n### dropper.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nPipe\n----\n\nThe `Pipe` class is a simple in-memory pipe, which provides writer and\nreader ends. Pipes handle data encoding and obey pause/resume semantics.\n\nThis class is useful if you have code that wants to call writable stream\nstyle methods, and you want it to be directly attached to some other code\nthat expects to be listening for events. For example:\n\n```javascript\nvar listeningThingy = ...;\nvar writingThingy = ...;\n\nvar pipe = new Pipe();\nlisteningThingy.listenTo(pipe.reader);\nwritingThingy.writeTo(pipe.writer);\n```\n\n### var pipe = new Pipe([options])\n\nConstructs and returns a new pipe pair. The result is an object with\nmappings for `{ reader, writer }` for the two ends of the pipe.\n\nThe reader and writer side each implement the standard Node stream\nprotocol for readable and writable streams (respectively).\n\nThe specified protocol allows writers to ignore the `fd` argument\nto `stream.write()`, and this implementation in fact ignores it.\n\nOf the common options, the constructor accepts `encoding` and `paused`,\nwhich both apply to the reader end of the pipe.\n\n\nSink\n----\n\nThe `Sink` class is an in-memory collector of all the data read from a\ngiven stream. It is in turn itself a stream that emits no more than a\nsingle `data` event consisting of all of the data it received, once\nits upstream source has ended. It also has direct accessors method to\nget at the data or a stream-ending error, to provide a bit of\nflexibility in how the class is used.\n\nThis class is useful for cases where you don't care about incremental\nprocessing and just want to deal with the whole enchilada (as it\nwere). This can be used to collect an entire post body from an HTTP\nrequest, for example:\n\n```javascript\nvar httpServer = http.createServer(onRequest);\n\nfunction onRequest(request, response) {\n  var postData = new Sink(request);\n  postData.on(\"data\", onPostData);\n\n  function onPostData(data) {\n    console.log(\"Got post:\", data.toString());\n  }\n}\n```\n\n### var sink = new Sink(source, [options])\n\nConstructs and returns a new sink, which listens to the given source\nstream. Once the stream has ended (via either an `end` or `close`\nevent), this instance emits a single `data` event containing all\nof the data received from the source (if there was any data at all),\nfollowed by an `end` and then a `close` event.\n\nIf the source should ever emit an `error` event, then this will cause\nthe sink instance to first emit any data it received (as a single\n`data` event), followed by an `error` event that corresponds to the\none it received, and finally followed by a `close` event. After that,\nit will emit no further events.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\nIn addition to being readable streams, sinks have a few more methods.\n\n### sink.getData() => buffer || string || undefined\n\nGets the final complete data for the sink, if available.\n\nIf the sink's source has not yet ended, or if it ended without\never emitting any data, this returns `undefined`.\n\nIf the sink received any data and has a specified encoding (via\n`setEncoding()`), this returns the string form of the data, as decoded\nusing the named encoding.\n\nIf the sink received any data but has no specified encoding, this\nreturns the straight buffer of data.\n\nNote that this method can return a defined (that is, not `undefined`)\nvalue before the corresponding `data` event is emitted, particularly\nif the sink happens to be paused at the time the upstream stream is\nended.\n\nAlso note that there is a bit of ambiguity with this method, in terms of\ndifferentiating a stream that got ended with no data ever received\nwith one that simply hasn't yet ended. Instead of using this method\nfor that purpose, use `sink.readable` (part of the standard readable\nstream protocol).\n\n### sink.getError() => any\n\nGets the error that terminated the upstream source, if available.\n\nIf the sink's source has not yet ended, or if it ended normally, this\nreturns `undefined`.\n\nIf the sink's source ended with an `error` event, then this returns the\nsame value that was received in that error event.\n\nNote that this method can return a defined (not `undefined`) value\nbefore the corresponding `error` event is emitted, particularly if the\nsink happens to be paused at the time the upstream stream reports its\nerror.\n\nAlso note that there is a bit of ambiguity in terms of interpreting a\nstream that got ended with an `error` event whose payload is\n`undefined`. If you need to account for this possibility, use\n`sink.gotError()`.\n\n### sink.gotError() => boolean\n\nGets whether or not the upstream source was ended with an error.\n\nThis returns `false` if the source has not yet ended, or if it ended\nnormally.\n\nThis returns `true` if and only if the upstream source emitted an\n`error` event that this sink instance received.\n\nNote that this method can return `true` before the corresponding\n`error` event is emitted, particularly if the sink happens to be\npaused at the time the upstream stream reports its error.\n\n### sink.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\nSlicer\n------\n\nThe `Slicer` class (like `Sink`) is an in-memory bufferer of data\nread from a given stream. In turn, it provides a `fs.read()` style\ninterface to get at the data so-read.\n\nAs the name implies, this class is useful for slicing up a stream\ninto chunks that aren't (necessarily) the same shape as the ones\nthat came in as `data` events.\n\nMost of the \"interesting\" methods on the class take a callback\nargument to receive data back from the instance. These are all\nconsistently called as `callback(error, length, buffer, offset)` with\nno `this` and with arguments defined as follows:\n\n* `error` &mdash; a boolean flag indicating whether the read was cut short\n  due to an error *or* because there was insufficient data to fully\n  comply with the request. (Note: This is different than `fs.read()`\n  which passes an error object here. See `slicer.gotError()` below for\n  an explanation of why.)\n\n* `length` &mdash; the number of bytes read.\n\n* `buffer` &mdash; the buffer that was read into.\n\n* `offset` &mdash; the offset into `buffer` where the reading was done.\n\nThe ordering and meaning of the callback arguments are meant to be (a)\ncompatible with callbacks used with `fs.read()` and (b) somewhat more\ninformative and unambiguous.\n\n### var slicer = new Slicer(source, [options])\n\nConstructs a new slicer, which listens to the given source.\n\nOf the common options, the only one recognized by this class is\n`incomingEncoding`. The class accepts no other options.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\n\n### slicer.readable => boolean\n\nThis indicates whether there is any data left to be read in the stream\nor whether there *could* be any day left to be read.\n\nIn particular, this only becomes `false` when it is both the case that\nthe buffer of pending data is empty *and* the upstream source has ended.\n\nThis field is meant to be reasonably analogous to the readable stream\nfield of the same name.\n\n### slicer.destroy()\n\nCauses the instance to be cleaned up and become closed. In particular,\nit includes detaching from the upstream source. After this method is\ncalled, other methods on this class will behave as if the upstream\nsource ended with no error.\n\nThis method is meant to be reasonably analogous to the readable stream\nfield of the same name.\n\n### slicer.setIncomingEncoding(name)\n\nSets the incoming encoding of the source stream. This is the encoding\nto use when interpreting strings that arrive in `data` events.\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n### slicer.gotError() => boolean\n\nIndicates whether the upstream source has indicated an error condition.\nThis is out-of-band with respect to the data, in that there may still\nbe data that can be successfully read even if this method returns `true`.\n\nThis method exists to help disambiguate the case of not\nhaving gotten an error indicator from the case of having gotten an\nerror indicator but without any error instance payload.\n\n### slicer.getError() => any\n\nGets the error payload that was reported from upstream, if any.\nThis is out-of-band with respect to the data, in that there may still\nbe data that can be successfully read even if this method returns a\ndefined value.\n\nThis will always return `undefined`, unless the upstream source\nreported an error with a defined payload.\n\n### slicer.readAll(callback)\n\nReads as much data as possible from the stream, blocking the callback\n*only* in order to make it to the head of the read queue.\n\nTo be clear, if there is no data available in the slicer at the time\nthis read becomes potentially-serviced, then it will in fact get\nserviced, with the callback indicating that zero bytes were read\nwithout error.\n\nThe `buffer` in the callback will always be a freshly-allocated buffer\nthat does not share its data with any other instance.\n\n### slicer.read(length, callback)\n\nReads exactly `length` bytes of data from the stream if at all\npossible, blocking the callback until either `length` bytes are\navailable or the stream has ended (either normally or with an error).\n\nIf `length` is passed as `0` it means \"read zero bytes\". This can be\nuseful as a way to insert a no-data \"sentinal\" callback into the\nsequence of callbacks coming from this instance.\n\nTo be clear, the callback will only ever indicate a shorter `length`\nthan requested if the upstream source ends without at least `length`\nbytes being available. If a short read ends up happening, then the\ncallback will get passed `true` for the error flag.\n\nThe `buffer` in the callback will always be a freshly-allocated buffer\nthat does not share its data with any other instance.\n\n### slicer.readInto(buffer, offset, length, callback)\n\nReads some amount of data from the stream into the indicated `buffer`\n(which must be a `Buffer` instance), starting at the indicated\n`offset` and reading exactly `length` bytes if at all possible.\n\nIf `offset` is passed as `undefined` it defaults to `0`.\n\nIf `length` is passed as `undefined` it means \"read as much as\npossible without blocking\". This is different than passing `0` which\nmeans simply \"read zero bytes\". (This latter case can actually be\nuseful. See `slicer.read(length, callback)` above.)\n\nAs with `read()`, the only time the length will be shorter than what\nwas requested will be if the stream ends without there being at least\n`length` bytes to read. If a short read ends up happening, then the\ncallback will get passed `true` for the error flag.\n\n\nValve\n-----\n\nThe `Valve` class is a bufferer of readable stream events, which\nrelays those events consistently. It handles pause/resume semantics,\nand it will always translate incoming values that aren't buffers into\nbuffers, using a specified and settable incoming encoding.\n\nOne of the major use cases of this class is to use it to capture the\ndata coming from a network stream that's already in the middle of\nproducing data, particularly when you don't immediately know where\nthat data needs to go to. The author has run into this on multiple\noccasions when trying hand off reading from an HTTP connection\nacross a tick boundary, along these lines for example (obviously\nsimplified here):\n\n```javascript\nvar thingThatWantsToRead = {\n  startReading: function (stream) {\n    stream.on(\"data\", ...);\n    stream.resume();\n    ...\n  },\n  ...\n}\n\nfunction httpRequestCallback(request, response) {\n  var valve = new Valve(request, true);\n\n  process.nextTick(function () {\n    thingThatWantsToRead.startReading(valve);\n  });\n}\n```\n\nAnother handy use for Valve is *just* to provide consistent data\npayloads (always buffers, or always properly encoded strings) and the\nconsistent event ordering generally guaranteed by this module. In\nparticular on the event type front, the standard Node HTTP and HTTPS\nstreams are inconsistent with the core `Stream` in that they can emit\n`close` events that contain either a boolean error flag or a full-on\n`Error` instance. By layering a `Valve` on top of them, these get\ntranslated into a consistent `error`-then-`close` sequence.\n\nSimilarly, if you want to implement a `Stream` as part of your own API\nbut don't want to deal with all the fiddly bits, you can write a\nstraightforward `EventEmitter`, and then expose it via a Valve, as in:\n\n```javascript\nfunction MyEventEmitter() {\n  events.EventEmitter.call(this);\n  ...\n}\n\nutil.inherits(this, events.EventEmitter);\n\nfunction createMyStream() {\n  var coreEmitter = new MyEventEmitter();\n  return new pipette.Valve(coreEmitter);\n}\n```\n\nThe Valve will \"sanitize\" the events coming from your class, while\nalso providing the rest of the core readable Stream API.\n\n### var valve = new Valve(source, [options])\n\nConstructs and returns a new valve, which listens to the given source.\n\nThis class recognizes all three of the common options (see above), and\nno others.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers.\n\n### valve.setIncomingEncoding(name)\n\nSets the incoming encoding of the stream. This is the encoding to use\nwhen interpreting strings that arrive in `data` events. (This is as\nopposed to the encoding set by `setEncoding()` which determines how\nthe collected data is transformed as it gets emitted from an\ninstance.)\n\nThe `name` must be one of the unified allowed encoding names for\n`Stream.setEncoding()`.\n\nThe incoming encoding starts out as `undefined`, which is taken to\nbe synonymous with `\"utf8\"` should a `data` event be received\ncontaining a string payload.\n\n\n* * * * * * * * * *\n\nTo Do\n-----\n\n* Consider adding a common option of `pressure: boolean` to indicate\n  whether `pause()` and `resume()` should recurse upstream.\n\n\nContributing\n------------\n\nQuestions, comments, bug reports, and pull requests are all welcome.\nSubmit them at [the project on GitHub](https://github.com/Obvious/pipette/).\n\nBug reports that include steps-to-reproduce (including code) are the\nbest. Even better, make them in the form of pull requests that update\nthe test suite. Thanks!\n\n\nAuthor\n------\n\n[Dan Bornstein](https://github.com/danfuzz)\n([personal website](http://www.milk.com/)), supported by\n[The Obvious Corporation](http://obvious.com/).\n\nThanks to <https://github.com/rootslab/dropper> for the name of the\n`Dropper` class.\n\n\nLicense\n-------\n\nCopyright 2012 [The Obvious Corporation](http://obvious.com/).\n\nLicensed under the Apache License, Version 2.0.\nSee the top-level file `LICENSE.txt` and\n(http://www.apache.org/licenses/LICENSE-2.0).\n\n\n","readmeFilename":"README.md","_id":"pipette@0.9.3","dist":{"shasum":"80c048e08629dd13b1bb0f01ef4532ee85b6a2a7","tarball":"https://registry.npmjs.org/pipette/-/pipette-0.9.3.tgz","integrity":"sha512-v3r0wA2fMYslCMK4NMJxbrNb3x5M7utKTMIl1P2v2QVAtBKSzz/22EWaTjs6WblpoYAiBkcdSQ1mP4tbBWOhTQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF3OiePr2cKPWDvkrerHGok3uvu68P0itMAhKaaAwzRqAiEA5rGx0te3hfe3fd2SC1t8CjmpuZh/yR4mXsMNpziL0M8="}]},"_from":".","_npmVersion":"1.2.14","_npmUser":{"name":"dpup","email":"dan@pupi.us"}}},"readme":"pipette: Pipe-like utilities for Node\n=====================================\n\nThis Node module provides a couple utility classes that offer\npipe-like functionality.\n\n### Pipe\n\nThe `Pipe` class is a simple in-memory pipe, which provides writer and\nreader ends, which both obey the standard Node stream protocols, including\nevent emission, encoding handling, and pause/resume semantics.\n\nThis class is useful if you have code that wants to call writable stream\nstyle methods, and you want it to be directly attached to some other code\nthat expects to be listening for events. For example:\n\n```javascript\nvar listeningThingy = ...;\nvar writingThingy = ...;\n\nvar pipe = new Pipe();\nlisteningThingy.listenTo(pipe.reader);\nwritingThingy.writeTo(pipe.writer);\n```\n\n### Valve\n\nThe `Valve` class is a bufferer of readable stream events, which in turn\nprovides the standard Node readable stream protocol, including event\nemission and pause/resume semantics. (It doesn't do any data re-encoding,\nthough; it's just a pass-through on that front.)\n\nOne of the major use cases of this class is to use it to capture the\ndata coming from a network stream that's already in the middle of\nproducing data, particularly when you don't immediately know where\nthat data needs to go to. The author has run into this on multiple\noccasions when trying hand off reading from an HTTP connection\nacross a tick boundary, along these lines for example (obviously\nsimplified here):\n\n```javascript\nvar thingThatWantsToRead = {\n    startReading: function (stream) {\n        stream.on(\"data\", ...);\n        stream.resume();\n        ...\n    },\n    ...\n}\n\nfunction httpRequestCallback(request, response) {\n    var valve = new Valve(request);\n\n    process.nextTick(function () {\n        thingThatWantsToRead.startReading(valve);\n    });\n}\n```\n\n\nBuilding and Installing\n-----------------------\n\n```shell\nnpm install pipette\n```\n\nOr grab the source. As of this writing, this module has no\ndependencies, so once you have the source, there's nothing more to do\nto \"build\" it.\n\n\nTesting\n-------\n\n```shell\nnpm test\n```\n\nOr\n\n```shell\nnode ./test/test.js\n```\n\n\nAPI Details\n-----------\n\nPipe\n----\n\n### var pipe = new Pipe([paused])\n\nConstruct and return a new pipe pair. The result is an object with\nmappings for `{ reader, writer }` for the two ends of the pipe.\n\nIf the optional `paused` argument is specified, it indicates whether\nor not the reader side should start out in the paused state. It defaults\nto `false`.\n\nThe reader and writer side each implement the standard Node stream\nprotocol for readable and writable streams (respectively).\n\nThe specified protocol allows writers to ignore the `fd` argument\nto `stream.write()`, and this implementation in fact ignores it.\n\n\nValve\n-----\n\n### var valve = new Valve(source, [paused])\n\nConstruct and return a new valve, which listens to the given source.\n\nIf the optional `paused` argument is specified, it indicates whether\nor not the new instance should start out in the paused state. It defaults\nto `true`, because that's the overwhelmingly most common use case.\n\nThe constructed instance obeys the full standard Node stream protocol\nfor readers, except that `setEncoding()` throws when called. This\nclass provides only pass-through of data, not translation.\n\n\nTo Do\n-----\n\n* Come up with something to do.\n\n\nContributing\n------------\n\nQuestions, comments, bug reports, and pull requests are all welcome.\nSubmit them at [the project on GitHub](https://github.com/Obvious/pipette/).\n\nBug reports that include steps-to-reproduce (including code) are the\nbest. Even better, make them in the form of pull requests that update\nthe test suite. Thanks!\n\n\nAuthor\n------\n\n[Dan Bornstein](https://github.com/danfuzz)\n([personal website](http://www.milk.com/)), supported by\n[The Obvious Corporation](http://obvious.com/).\n\n\nLicense\n-------\n\nCopyright 2012 [The Obvious Corporation](http://obvious.com/).\n\nLicensed under the Apache License, Version 2.0. \nSee the top-level file `LICENSE.txt` and\n(http://www.apache.org/licenses/LICENSE-2.0).\n\n\n","maintainers":[{"name":"danfuzz","email":"danfuzz@milk.com"},{"name":"dpup","email":"dan@pupi.us"},{"name":"nicks","email":"nicholas.j.santos@gmail.com"},{"name":"azulus","email":"jeremy@obvious.com"}],"time":{"modified":"2022-06-24T00:45:59.879Z","created":"2012-06-08T19:15:01.733Z","0.2.0":"2012-06-08T19:15:03.867Z","0.3.0":"2012-06-15T17:15:16.297Z","0.3.1":"2012-06-15T22:30:54.461Z","0.4.0":"2012-06-16T00:34:33.079Z","0.4.1":"2012-06-18T19:56:15.924Z","0.5.0":"2012-06-21T20:42:00.342Z","0.5.1":"2012-06-22T00:31:31.928Z","0.6.0":"2012-06-28T20:04:38.291Z","0.6.1":"2012-06-28T22:49:19.655Z","0.7.2":"2012-07-02T17:32:34.313Z","0.8.0":"2012-07-02T17:54:08.693Z","0.8.1":"2012-07-05T23:24:58.311Z","0.8.2":"2012-07-06T20:12:14.262Z","0.8.3":"2012-07-12T01:32:04.342Z","0.8.4":"2012-07-14T00:56:01.573Z","0.8.5":"2012-07-15T20:48:17.437Z","0.9.0":"2012-07-15T21:37:23.109Z","0.9.1":"2012-10-10T17:30:13.298Z","0.9.2":"2013-04-01T22:55:18.774Z","0.9.3":"2013-04-02T15:19:26.953Z"},"author":{"name":"Dan Bornstein","email":"danfuzz@milk.com","url":"http://www.milk.com/"},"repository":{"type":"git","url":"https://github.com/Obvious/pipette.git"}}