├── .eslintrc.json ├── .gitignore ├── .madrun.mjs ├── .npmignore ├── .nycrc.json ├── .travis.yml ├── ChangeLog ├── LICENSE ├── README.md ├── lib └── files.js ├── package.json └── test └── files.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:node/recommended", 4 | "plugin:putout/recommended" 5 | ], 6 | "plugins": [ 7 | "putout", 8 | "node" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .nyc_output 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | .putoutcache 7 | *.swp 8 | -------------------------------------------------------------------------------- /.madrun.mjs: -------------------------------------------------------------------------------- 1 | import {run} from 'madrun'; 2 | 3 | export default { 4 | 'fix:lint': () => run('lint', '--fix'), 5 | 'lint': () => 'putout .', 6 | 'fresh:lint': () => run('lint', '--fresh'), 7 | 'lint:fresh': () => run('lint', '--fresh'), 8 | 'lint:test': () => 'putout -c .putoutrc.test test', 9 | 'test': () => 'tape test/*.js', 10 | 'coverage': () => 'nyc npm test', 11 | 'report': () => 'nyc report --reporter=text-lcov | coveralls', 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | test 3 | yarn-error.log 4 | 5 | -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "check-coverage": true, 3 | "all": true, 4 | "exclude": [ 5 | "**/*.spec.js", 6 | "**/fixture", 7 | "test", 8 | ".*.{js,mjs}" 9 | ], 10 | "branches": 100, 11 | "lines": 100, 12 | "functions": 100, 13 | "statements": 100 14 | } 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 15 4 | - 14 5 | script: 6 | - npm run lint 7 | - npm run coverage && npm run report 8 | notifications: 9 | email: 10 | on_success: never 11 | on_failure: change 12 | sudo: false 13 | cache: false 14 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2021.01.26, v4.0.1 2 | 3 | feature: 4 | - (package) eslint-plugin-putout v7.0.0 5 | - (package) putout v14.0.0 6 | 7 | 8 | 2021.01.25, v4.0.0 9 | 10 | feature: 11 | - (files-io) drop support of node < 14 12 | - (package) eslint v7.18.0 13 | - (package) supertape v4.8.1 14 | - (package) putout v13.9.1 15 | - (package) eslint-plugin-putout v6.13.1 16 | - (package) madrun v8.6.2 17 | 18 | 19 | 2020.03.21, v3.0.2 20 | 21 | feature: 22 | - (package) try-to-catch v3.0.0 23 | - (package) eslint-plugin-node v11.0.0 24 | - (package) nyc v15.0.0 25 | - (package) eslint-plugin-putout v3.4.0 26 | - (package) madrun v5.4.5 27 | 28 | 29 | 2019.09.18, v3.0.1 30 | 31 | feature: 32 | - (files) add madrun 33 | - (package) pipe-io v4.0.0 34 | - (package) nyc v14.1.1 35 | - (package) eslint v6.4.0 36 | - (package) eslint-plugin-node v10.0.0 37 | 38 | 39 | 2018.10.24, v3.0.0 40 | 41 | feature: 42 | - (files) callback -> promise 43 | - (package) eslint-plugin-node v7.0.1 44 | - (package) eslint v5.7.0 45 | - (package) pipe-io v3.0.9 46 | - (package) drop support of node < 8 47 | 48 | 49 | 2018.05.02, v2.0.0 50 | 51 | feature: 52 | - (package) pipe-io v3.0.0 53 | - (package) add eslint 54 | - (package) drop support of node < 4 55 | 56 | 57 | 2016.12.28, v1.2.8 58 | 59 | feature: 60 | - (package) itype v2.0.0 61 | 62 | 63 | 2016.11.08, v1.2.7 64 | 65 | feature: 66 | - (package) pipe-io v2.0.1 67 | 68 | 69 | 2015.08.17, v1.2.6 70 | 71 | feature: 72 | - feature(package) pipe-io v1.2.0 73 | 74 | 75 | 2015.02.09, v1.2.5 76 | 77 | fix: 78 | - (files) pipeFiles: crash when no gzip 79 | 80 | 81 | 2015.02.02, v1.2.4 82 | 83 | feature: 84 | - (files) checkup -> assert 85 | - (package) v1.2.3 86 | - (package) extend -> extendy 87 | 88 | 89 | 2015.01.16, v1.2.3 90 | 91 | feature: 92 | - (package) extend -> extendy 93 | 94 | 95 | 2014.12.22, v1.2.2 96 | 97 | feature: 98 | - (files) rm util-io, add checkup, extend, itype 99 | 100 | 101 | 2014.11.25, v1.2.1 102 | 103 | feature: 104 | - (files) Util.check -> check 105 | 106 | 107 | 2014.11.3, v1.2.0 108 | 109 | feature: 110 | - (files) add pipe 111 | 112 | 113 | 2014.10.31, v1.1.3 114 | 115 | feature: 116 | - (package) util-io v1.5.0 117 | - (package) pipe v1.0.0 118 | 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 coderaiser 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Files-io [![License][LicenseIMGURL]][LicenseURL] [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL] [![Coverage Status][CoverageIMGURL]][CoverageURL] 2 | 3 | [NPMIMGURL]: https://img.shields.io/npm/v/files-io.svg?style=flat 4 | [BuildStatusIMGURL]: https://img.shields.io/travis/coderaiser/files-io/master.svg?style=flat 5 | [DependencyStatusIMGURL]: https://img.shields.io/david/coderaiser/files-io.svg?style=flat 6 | [LicenseIMGURL]: https://img.shields.io/badge/license-MIT-317BF9.svg?style=flat 7 | [NPMURL]: https://npmjs.org/package/files-io "npm" 8 | [BuildStatusURL]: https://travis-ci.org/coderaiser/files-io "Build Status" 9 | [DependencyStatusURL]: https://david-dm.org/coderaiser/files-io "Dependency Status" 10 | [LicenseURL]: https://tldrlegal.com/license/mit-license "MIT License" 11 | [CoverageURL]: https://coveralls.io/github/coderaiser/readify?branch=master 12 | [CoverageIMGURL]: https://coveralls.io/repos/coderaiser/readify/badge.svg?branch=master&service=github 13 | 14 | Read many files with node. 15 | 16 | # Install 17 | 18 | `npm i files-io --save` 19 | 20 | # How to use? 21 | 22 | ```js 23 | const files = require('files-io'); 24 | 25 | const allData = await files.read(['README.md', 'package.json'], 'utf8'); 26 | console.log(allData); 27 | 28 | /* Easy way to create pipe which would handle all error events */ 29 | const NameFrom = 'README.md'; 30 | const NameTo = 'README_COPY.gz'; 31 | 32 | await files.pipe(NameFrom, NameTo, { 33 | gzip: true, 34 | }); 35 | /* join couple files and save them to new file with streams */ 36 | const fs = require('fs'); 37 | const NAME = 'Join'; 38 | const writeStream = fs.createWriteStream(NAME); 39 | 40 | await files.readPipe(['README.md', 'package.json'], writeStream); 41 | ``` 42 | 43 | # License 44 | 45 | MIT 46 | -------------------------------------------------------------------------------- /lib/files.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { 4 | createReadStream, 5 | createWriteStream, 6 | } = require('fs'); 7 | const {readFile} = require('fs/promises'); 8 | const zlib = require('zlib'); 9 | const assert = require('assert'); 10 | 11 | const pipe = require('pipe-io'); 12 | const {assign} = Object; 13 | 14 | module.exports.read = async (files, options) => { 15 | const filesData = {}; 16 | 17 | assert(files, 'files could not be empty!'); 18 | 19 | for (const name of files) { 20 | const data = await readFile(name, options); 21 | filesData[name] = data; 22 | } 23 | 24 | return filesData; 25 | }; 26 | 27 | module.exports.readPipe = async function readPipe(names, write, options = {gzip: false}) { 28 | const {length} = names; 29 | 30 | if (!length) 31 | return write.end(); 32 | 33 | const [name] = names; 34 | 35 | const opt = { 36 | ...options, 37 | end: false, 38 | }; 39 | 40 | await pipeFiles(name, write, opt); 41 | await readPipe(names.slice(1), write, opt); 42 | }; 43 | 44 | module.exports.pipe = pipeFiles; 45 | 46 | async function pipeFiles(read, write, options = {}) { 47 | const isStrRead = typeof read === 'string'; 48 | const isStrWrite = typeof write === 'string'; 49 | const optionsRead = { 50 | bufferSize: 4 * 1024, 51 | }; 52 | 53 | assert(read, 'read could not be empty!'); 54 | assert(write, 'write could not be empty!'); 55 | 56 | const { 57 | range, 58 | gzip, 59 | gunzip, 60 | } = options; 61 | 62 | if (range) 63 | assign(optionsRead, { 64 | start: range.start, 65 | end: range.end, 66 | }); 67 | 68 | if (isStrRead) 69 | read = createReadStream(read, optionsRead); 70 | 71 | if (isStrWrite) 72 | write = createWriteStream(write); 73 | 74 | let zip; 75 | let streams = []; 76 | 77 | if (!gzip && !gunzip) { 78 | streams = [read, write]; 79 | } else { 80 | if (gzip) 81 | zip = zlib.createGzip(); 82 | else 83 | zip = zlib.createGunzip(); 84 | 85 | streams = [read, zip, write]; 86 | } 87 | 88 | await pipe(streams, options); 89 | } 90 | 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "files-io", 3 | "version": "4.0.1", 4 | "author": "coderaiser (https://github.com/coderaiser)", 5 | "description": "Read many files in node", 6 | "homepage": "http://github.com/coderaiser/files-io", 7 | "main": "lib/files.js", 8 | "repository": { 9 | "type": "git", 10 | "url": "git://github.com/coderaiser/files-io.git" 11 | }, 12 | "scripts": { 13 | "fix:lint": "madrun fix:lint", 14 | "lint": "madrun lint", 15 | "lint:test": "madrun lint:test", 16 | "test": "madrun test", 17 | "coverage": "madrun coverage", 18 | "report": "madrun report" 19 | }, 20 | "keywords": [ 21 | "files", 22 | "read" 23 | ], 24 | "dependencies": { 25 | "pipe-io": "^4.0.0" 26 | }, 27 | "engines": { 28 | "node": ">=14" 29 | }, 30 | "license": "MIT", 31 | "devDependencies": { 32 | "coveralls": "^3.0.2", 33 | "eslint": "^7.18.0", 34 | "eslint-plugin-node": "^11.0.0", 35 | "eslint-plugin-putout": "^7.0.0", 36 | "madrun": "^8.6.2", 37 | "nyc": "^15.0.0", 38 | "putout": "^14.0.0", 39 | "supertape": "^4.8.1", 40 | "try-to-catch": "^3.0.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/files.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { 4 | createReadStream, 5 | createWriteStream, 6 | } = require('fs'); 7 | const {readFile, unlink} = require('fs/promises'); 8 | const os = require('os'); 9 | const {join} = require('path'); 10 | 11 | const tryToCatch = require('try-to-catch'); 12 | const test = require('supertape'); 13 | const files = require('..'); 14 | 15 | test('files: read', async (t) => { 16 | const dir = join(__dirname, '..'); 17 | const names = [ 18 | `${dir}/package.json`, 19 | `${dir}/README.md`, 20 | ]; 21 | 22 | const result = await files.read(names); 23 | 24 | const expected = { 25 | [`${dir}/package.json`]: await readFile(`${dir}/package.json`), 26 | [`${dir}/README.md`]: await readFile(`${dir}/README.md`), 27 | }; 28 | 29 | t.deepEqual(result, expected, 'should equal'); 30 | t.end(); 31 | }); 32 | 33 | test('files: pipe', async (t) => { 34 | const tmpDir = os.tmpdir(); 35 | const from = join(__dirname, '..', 'README.md'); 36 | const to = join(tmpDir, 'README_COPY.gz'); 37 | 38 | const [e] = await tryToCatch(files.pipe, from, to); 39 | 40 | await unlink(to); 41 | 42 | t.notOk(e, 'should not be error'); 43 | t.end(); 44 | }); 45 | 46 | test('files: pipe: gzip', async (t) => { 47 | const tmpDir = os.tmpdir(); 48 | const from = join(__dirname, '..', 'README.md'); 49 | const to = join(tmpDir, 'README_COPY.gz'); 50 | 51 | const [e] = await tryToCatch(files.pipe, from, to, { 52 | gzip: true, 53 | }); 54 | 55 | await unlink(to); 56 | 57 | t.notOk(e, 'should not be error'); 58 | t.end(); 59 | }); 60 | 61 | test('files: pipe: gunzip', async (t) => { 62 | const tmpDir = os.tmpdir(); 63 | const from = join(__dirname, '..', 'README.md'); 64 | const to = join(tmpDir, 'README_COPY.gz'); 65 | 66 | const [e] = await tryToCatch(files.pipe, from, to, { 67 | gunzip: true, 68 | }); 69 | 70 | t.ok(e, 'should be error'); 71 | t.end(); 72 | }); 73 | 74 | test('files: pipe: range', async (t) => { 75 | const tmpDir = os.tmpdir(); 76 | const from = join(__dirname, '..', 'README.md'); 77 | const to = join(tmpDir, 'README_COPY.gz'); 78 | 79 | const [e] = await tryToCatch(files.pipe, from, to, { 80 | gzip: true, 81 | range: { 82 | start: 0, 83 | end: 10, 84 | }, 85 | }); 86 | 87 | await unlink(to); 88 | 89 | t.notOk(e, 'should not be error'); 90 | t.end(); 91 | }); 92 | 93 | test('files: pipe: streams', async (t) => { 94 | const tmpDir = os.tmpdir(); 95 | const from = join(__dirname, '..', 'README.md'); 96 | const to = join(tmpDir, 'README_COPY.gz'); 97 | const fromStream = createReadStream(from); 98 | const toStream = createWriteStream(to); 99 | 100 | const [e] = await tryToCatch(files.pipe, fromStream, toStream); 101 | 102 | await unlink(to); 103 | 104 | t.notOk(e, 'should not be error'); 105 | t.end(); 106 | }); 107 | 108 | test('files: readPipe', async (t) => { 109 | const tmpDir = os.tmpdir(); 110 | const file1 = join(__dirname, '..', 'README.md'); 111 | const file2 = join(__dirname, '..', 'package.json'); 112 | const to = join(tmpDir, 'README_COPY.gz'); 113 | const stream = createWriteStream(to); 114 | 115 | const [e] = await tryToCatch(files.readPipe, [file1, file2], stream); 116 | 117 | await unlink(to); 118 | 119 | t.notOk(e, 'should not be error'); 120 | t.end(); 121 | }); 122 | 123 | --------------------------------------------------------------------------------