├── .eslintignore ├── .eslintrc ├── .gitignore ├── History.md ├── index.js ├── .travis.yml ├── appveyor.yml ├── .autod.conf.js ├── package.json ├── LICENSE ├── lib └── await.js ├── test ├── write.test.js ├── read.test.js └── fixtures │ └── file.svg └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-egg" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | node_modules/ 4 | coverage/ 5 | .idea/ 6 | run/ 7 | .DS_Store 8 | *.swp 9 | 10 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 1.0.1 / 2017-03-27 3 | ================== 4 | 5 | * fix: don't check stream state (#3) 6 | 7 | 1.0.0 / 2017-03-26 8 | ================== 9 | 10 | * init version 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const awaitStream = require('./lib/await'); 4 | 5 | exports.read = stream => awaitStream(stream, 'read'); 6 | exports.write = stream => awaitStream(stream, 'write'); 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '4' 5 | - '6' 6 | - '7' 7 | install: 8 | - npm i npminstall && npminstall 9 | script: 10 | - npm run ci 11 | after_script: 12 | - npminstall codecov && codecov 13 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '4' 4 | - nodejs_version: '6' 5 | - nodejs_version: '7' 6 | 7 | install: 8 | - ps: Install-Product node $env:nodejs_version 9 | - npm i npminstall && node_modules\.bin\npminstall 10 | 11 | test_script: 12 | - node --version 13 | - npm --version 14 | - npm run ci 15 | 16 | build: off 17 | -------------------------------------------------------------------------------- /.autod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | write: true, 5 | prefix: '^', 6 | test: [ 7 | 'test', 8 | ], 9 | dep: [ 10 | ], 11 | devdep: [ 12 | 'egg-ci', 13 | 'egg-bin', 14 | 'autod', 15 | 'eslint', 16 | 'eslint-config-egg', 17 | ], 18 | exclude: [ 19 | './test/fixtures', 20 | ], 21 | semver: [ 22 | 'egg-bin@1', 23 | ], 24 | }; 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "await-stream-ready", 3 | "version": "1.0.1", 4 | "description": "A promise waiting stream ready", 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "autod": "^2.8.0", 8 | "egg-bin": "^1.10.3", 9 | "egg-ci": "^1.6.0", 10 | "eslint": "^3.18.0", 11 | "eslint-config-egg": "^3.2.0", 12 | "mz": "^2.6.0", 13 | "spy": "^1.0.0" 14 | }, 15 | "engines": { 16 | "node": ">=4.0.0" 17 | }, 18 | "scripts": { 19 | "autod": "autod", 20 | "test": "npm run lint -- --fix && npm run test-local", 21 | "test-local": "egg-bin test", 22 | "cov": "egg-bin cov", 23 | "lint": "eslint .", 24 | "ci": "npm run lint && npm run cov" 25 | }, 26 | "ci": { 27 | "version": "4, 6, 7", 28 | "license": { 29 | "fullname": "node-modules", 30 | "year": "2017" 31 | } 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "git@github.com:node-modules/await-stream-ready.git" 36 | }, 37 | "author": "popomore", 38 | "license": "MIT", 39 | "files": [ 40 | "index.js", 41 | "lib" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 node-modules 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/await.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Stream = require('stream').Stream; 4 | 5 | module.exports = (stream, type) => { 6 | return new Promise((resolve, reject) => { 7 | if (type === 'read' && !isReadable(stream)) return reject(new Error('Only support readable stream')); 8 | if (type === 'write' && !isWritable(stream)) return reject(new Error('Only support writable stream')); 9 | 10 | const event = type === 'read' ? 'end' : 'finish'; 11 | 12 | stream.once(event, success); 13 | stream.once('error', fail); 14 | 15 | if (isReadable(stream)) stream.resume(); 16 | 17 | function success() { 18 | clean(); 19 | resolve(); 20 | } 21 | function fail(err) { 22 | clean(); 23 | reject(err); 24 | } 25 | function clean() { 26 | stream.removeListener(event, success); 27 | stream.removeListener('error', fail); 28 | } 29 | }); 30 | }; 31 | 32 | function isReadable(stream) { 33 | return isStream(stream) && typeof stream._read === 'function'; 34 | } 35 | 36 | function isWritable(stream) { 37 | return isStream(stream) && typeof stream._write === 'function'; 38 | } 39 | 40 | function isStream(stream) { 41 | return stream instanceof Stream; 42 | } 43 | -------------------------------------------------------------------------------- /test/write.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const assert = require('assert'); 5 | const fs = require('mz/fs'); 6 | const awaitWriteStream = require('..').write; 7 | const fixtures = path.join(__dirname, 'fixtures'); 8 | 9 | describe('test/write.test.js', () => { 10 | const file = path.join(fixtures, 'write.svg'); 11 | 12 | after(function* () { 13 | if (yield fs.exists(file)) { 14 | yield fs.unlink(file); 15 | } 16 | }); 17 | 18 | it('should wait writing stream', function* () { 19 | const stream = fs.createWriteStream(file); 20 | process.nextTick(() => { 21 | writeBuffer(stream); 22 | stream.end(); 23 | }); 24 | yield awaitWriteStream(stream); 25 | const stat = yield fs.stat(file); 26 | assert(stat.size === 1000); 27 | }); 28 | 29 | it('should throw it is not a writable stream', function* () { 30 | try { 31 | yield awaitWriteStream(); 32 | throw new Error('should not run'); 33 | } catch (err) { 34 | assert(err.message === 'Only support writable stream'); 35 | } 36 | }); 37 | 38 | it('should throw when error emit', function* () { 39 | const stream = fs.createWriteStream(file); 40 | process.nextTick(() => { 41 | stream.emit('error', new Error('error')); 42 | }); 43 | try { 44 | yield awaitWriteStream(stream); 45 | throw new Error('should not run'); 46 | } catch (err) { 47 | assert(err.message === 'error'); 48 | } 49 | }); 50 | }); 51 | 52 | function writeBuffer(stream) { 53 | let len = 1000; 54 | while (len > 0) { 55 | stream.write(new Buffer('1')); 56 | len--; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/read.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const assert = require('assert'); 5 | const fs = require('mz/fs'); 6 | const Transform = require('stream').Transform; 7 | const awaitReadStream = require('..').read; 8 | const fixtures = path.join(__dirname, 'fixtures'); 9 | 10 | describe('test/read.test.js', () => { 11 | it('should wait consuming read stream', function* () { 12 | const stream = fs.createReadStream(path.join(fixtures, 'file.svg')); 13 | let size = 0; 14 | stream.on('data', buf => { 15 | size += buf.length; 16 | }); 17 | yield awaitReadStream(stream); 18 | assert(size === 14193); 19 | }); 20 | 21 | it('should throw it is not a readable stream', function* () { 22 | try { 23 | yield awaitReadStream(); 24 | throw new Error('should not run'); 25 | } catch (err) { 26 | assert(err.message === 'Only support readable stream'); 27 | } 28 | }); 29 | 30 | it('should throw when error emit', function* () { 31 | const stream = fs.createReadStream(path.join(fixtures, 'file.svg')); 32 | process.nextTick(() => { 33 | stream.emit('error', new Error('error')); 34 | }); 35 | try { 36 | yield awaitReadStream(stream); 37 | throw new Error('should not run'); 38 | } catch (err) { 39 | assert(err.message === 'error'); 40 | } 41 | }); 42 | 43 | it('should auto resume readable stream', function* () { 44 | const stream = new Transform({ 45 | transform(chunk, encoding, callback) { 46 | callback(null, chunk); 47 | }, 48 | }); 49 | process.nextTick(() => { 50 | stream.write('1'); 51 | stream.write('2'); 52 | stream.end(); 53 | }); 54 | yield awaitReadStream(stream); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # await-stream-ready 2 | 3 | A promise waiting stream ready 4 | 5 | [![NPM version][npm-image]][npm-url] 6 | [![build status][travis-image]][travis-url] 7 | [![Test coverage][codecov-image]][codecov-url] 8 | [![David deps][david-image]][david-url] 9 | [![Known Vulnerabilities][snyk-image]][snyk-url] 10 | [![NPM download][download-image]][download-url] 11 | 12 | [npm-image]: https://img.shields.io/npm/v/await-stream-ready.svg?style=flat-square 13 | [npm-url]: https://npmjs.org/package/await-stream-ready 14 | [travis-image]: https://img.shields.io/travis/node-modules/await-stream-ready.svg?style=flat-square 15 | [travis-url]: https://travis-ci.org/node-modules/await-stream-ready 16 | [codecov-image]: https://codecov.io/gh/node-modules/await-stream-ready/branch/master/graph/badge.svg 17 | [codecov-url]: https://codecov.io/gh/node-modules/await-stream-ready 18 | [david-image]: https://img.shields.io/david/node-modules/await-stream-ready.svg?style=flat-square 19 | [david-url]: https://david-dm.org/node-modules/await-stream-ready 20 | [snyk-image]: https://snyk.io/test/npm/await-stream-ready/badge.svg?style=flat-square 21 | [snyk-url]: https://snyk.io/test/npm/await-stream-ready 22 | [download-image]: https://img.shields.io/npm/dm/await-stream-ready.svg?style=flat-square 23 | [download-url]: https://npmjs.org/package/await-stream-ready 24 | 25 | --- 26 | 27 | ## Usage 28 | 29 | ```bash 30 | npm i await-stream-ready --save 31 | ``` 32 | 33 | Wait a read stream 34 | 35 | ```js 36 | const fs = require('fs'); 37 | const awaitReadStream = require('await-stream-ready').read; 38 | 39 | async function read(file) { 40 | const stream = fs.createReadStream(file); 41 | stream.on('data', buf => { 42 | // consume buf 43 | }); 44 | await awaitReadStream(stream); 45 | } 46 | ``` 47 | 48 | Or wait a write stream 49 | 50 | ```js 51 | const fs = require('fs'); 52 | const awaitWriteStream = require('await-stream-ready').write; 53 | 54 | async function write(srcStream, file) { 55 | const stream = srcStream.pipe(fs.createWriteStream(file)); 56 | await awaitWriteStream(stream); 57 | } 58 | ``` 59 | 60 | **It will switch the readable stream to flowing mode automatically.** 61 | 62 | ## License 63 | 64 | [MIT](LICENSE) 65 | -------------------------------------------------------------------------------- /test/fixtures/file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 8 5 | Created with Sketch Beta. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | --------------------------------------------------------------------------------