From 9d43c387ca2d0bb1c0d5d460b80eb3df74d511e4 Mon Sep 17 00:00:00 2001 From: Yanis Benson Date: Tue, 18 Jun 2019 13:04:19 +0300 Subject: [PATCH] add filter option, fixes #63 --- index.d.ts | 16 ++++++++++++++++ index.js | 6 ++++++ index.test-d.ts | 6 ++++++ package.json | 1 + readme.md | 15 +++++++++++++++ test.js | 14 ++++++++++++++ 6 files changed, 58 insertions(+) diff --git a/index.d.ts b/index.d.ts index 4abaa41..ec1210a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -46,6 +46,22 @@ declare namespace cpy { @default true */ readonly ignoreJunk?: boolean; + + /** + Function to filter copied files. Return true to include, false to exclude. Can also return a Promise that resolves to true or false. + + @example + ``` + import cpy = require('cpy'); + + (async () => { + await cpy('foo', 'destination', { + filter: name => !name.includes('NOCOPY') + }); + })(); + ``` + */ + readonly filter?: (basename: string) => (boolean | Promise); } interface ProgressData { diff --git a/index.js b/index.js index efb1273..94e41f1 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,7 @@ const arrify = require('arrify'); const globby = require('globby'); const cpFile = require('cp-file'); const junk = require('junk'); +const pFilter = require('p-filter'); const CpyError = require('./cpy-error'); const defaultOptions = { @@ -65,6 +66,11 @@ module.exports = (source, destination, { throw new CpyError(`Cannot glob \`${source}\`: ${error.message}`, error); } + if (options.filter !== undefined) { + const filteredFiles = await pFilter(files, options.filter, {concurrency: 1024}); + files = filteredFiles; + } + if (files.length === 0) { progressEmitter.emit('progress', { totalFiles: 0, diff --git a/index.test-d.ts b/index.test-d.ts index 39fec27..31a0993 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -27,6 +27,12 @@ expectType & ProgressEmitter>( cpy('foo.js', 'destination', {concurrency: 2}) ); +expectType & ProgressEmitter>( + cpy('foo.js', 'destination', {filter: () => true}) +); +expectType & ProgressEmitter>( + cpy('foo.js', 'destination', {filter: async () => true}) +); expectType>( cpy('foo.js', 'destination').on('progress', progress => { diff --git a/package.json b/package.json index 53a8afe..2f4745d 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "globby": "^9.2.0", "nested-error-stacks": "^2.1.0", "p-all": "^2.1.0", + "p-filter": "^2.1.0", "junk": "^3.1.0" }, "devDependencies": { diff --git a/readme.md b/readme.md index bf2a8c1..6f7ef46 100644 --- a/readme.md +++ b/readme.md @@ -108,6 +108,21 @@ Default: `true` Ignores [junk](https://github.com/sindresorhus/junk) files. +#### filter + +Type: `string | Function` + +Function to filter copied files. Return true to include, false to exclude. Can also return a Promise that resolves to true or false. + +```js +const cpy = require('cpy'); + +(async () => { + await cpy('foo.js', 'destination', { + filter: name => !name.includes('NOCOPY') + }); +})(); +``` ## Progress reporting ### cpy.on('progress', handler) diff --git a/test.js b/test.js index ea0d495..2cd9726 100644 --- a/test.js +++ b/test.js @@ -54,6 +54,20 @@ test('throws on invalid concurrency value', async t => { await t.throwsAsync(cpy(['license', 'package.json'], t.context.tmp, {concurrency: 'foo'})); }); +test('copy array of files with filter', async t => { + await cpy(['license', 'package.json'], t.context.tmp, {filter: name => name !== 'license'}); + + t.false(fs.existsSync(path.join(t.context.tmp, 'license'))); + t.is(read('package.json'), read(t.context.tmp, 'package.json')); +}); + +test('copy array of files with async filter', async t => { + await cpy(['license', 'package.json'], t.context.tmp, {filter: async name => name !== 'license'}); + + t.false(fs.existsSync(path.join(t.context.tmp, 'license'))); + t.is(read('package.json'), read(t.context.tmp, 'package.json')); +}); + test('cwd', async t => { fs.mkdirSync(t.context.tmp); fs.mkdirSync(path.join(t.context.tmp, 'cwd'));