From 41097c4e4aeb7649d1d10671f0ef555031fdac10 Mon Sep 17 00:00:00 2001 From: Dimitri Benin Date: Sun, 3 Mar 2019 21:44:16 +0100 Subject: [PATCH 1/3] Update dependencies --- fs.js | 74 +++++++++++++++++++-------------------- index.js | 12 +++---- package.json | 16 ++++----- test/async.js | 47 +++++++++++++------------ test/helpers/fs-errors.js | 2 +- test/progress.js | 12 +++---- test/sync.js | 54 ++++++++++++++-------------- 7 files changed, 109 insertions(+), 108 deletions(-) diff --git a/fs.js b/fs.js index 66e8f20..646a51e 100644 --- a/fs.js +++ b/fs.js @@ -12,8 +12,8 @@ exports.createWriteStream = fs.createWriteStream.bind(fs); exports.createReadStream = (path, options) => new Promise((resolve, reject) => { const read = fs.createReadStream(path, options); - read.once('error', err => { - reject(new CpFileError(`Cannot read from \`${path}\`: ${err.message}`, err)); + read.once('error', error => { + reject(new CpFileError(`Cannot read from \`${path}\`: ${error.message}`, error)); }); read.once('readable', () => { @@ -25,35 +25,35 @@ exports.createReadStream = (path, options) => new Promise((resolve, reject) => { }); }); -exports.stat = path => fsP.stat(path).catch(err => { - throw new CpFileError(`Cannot stat path \`${path}\`: ${err.message}`, err); +exports.stat = path => fsP.stat(path).catch(error => { + throw new CpFileError(`Cannot stat path \`${path}\`: ${error.message}`, error); }); -exports.lstat = path => fsP.lstat(path).catch(err => { - throw new CpFileError(`lstat \`${path}\` failed: ${err.message}`, err); +exports.lstat = path => fsP.lstat(path).catch(error => { + throw new CpFileError(`lstat \`${path}\` failed: ${error.message}`, error); }); -exports.utimes = (path, atime, mtime) => fsP.utimes(path, atime, mtime).catch(err => { - throw new CpFileError(`utimes \`${path}\` failed: ${err.message}`, err); +exports.utimes = (path, atime, mtime) => fsP.utimes(path, atime, mtime).catch(error => { + throw new CpFileError(`utimes \`${path}\` failed: ${error.message}`, error); }); -exports.chmod = (path, mode) => fsP.chmod(path, mode).catch(err => { - throw new CpFileError(`chmod \`${path}\` failed: ${err.message}`, err); +exports.chmod = (path, mode) => fsP.chmod(path, mode).catch(error => { + throw new CpFileError(`chmod \`${path}\` failed: ${error.message}`, error); }); -exports.chown = (path, uid, gid) => fsP.chown(path, uid, gid).catch(err => { - throw new CpFileError(`chown \`${path}\` failed: ${err.message}`, err); +exports.chown = (path, uid, gid) => fsP.chown(path, uid, gid).catch(error => { + throw new CpFileError(`chown \`${path}\` failed: ${error.message}`, error); }); exports.openSync = (path, flags, mode) => { try { return fs.openSync(path, flags, mode); - } catch (err) { + } catch (error) { if (flags.includes('w')) { - throw new CpFileError(`Cannot write to \`${path}\`: ${err.message}`, err); + throw new CpFileError(`Cannot write to \`${path}\`: ${error.message}`, error); } - throw new CpFileError(`Cannot open \`${path}\`: ${err.message}`, err); + throw new CpFileError(`Cannot open \`${path}\`: ${error.message}`, error); } }; @@ -61,8 +61,8 @@ exports.openSync = (path, flags, mode) => { exports.readSync = (fd, buffer, offset, length, position, path) => { try { return fs.readSync(fd, buffer, offset, length, position); - } catch (err) { - throw new CpFileError(`Cannot read from \`${path}\`: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`Cannot read from \`${path}\`: ${error.message}`, error); } }; @@ -70,68 +70,68 @@ exports.readSync = (fd, buffer, offset, length, position, path) => { exports.writeSync = (fd, buffer, offset, length, position, path) => { try { return fs.writeSync(fd, buffer, offset, length, position); - } catch (err) { - throw new CpFileError(`Cannot write to \`${path}\`: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`Cannot write to \`${path}\`: ${error.message}`, error); } }; exports.statSync = path => { try { return fs.statSync(path); - } catch (err) { - throw new CpFileError(`stat \`${path}\` failed: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`stat \`${path}\` failed: ${error.message}`, error); } }; exports.fstatSync = (fd, path) => { try { return fs.fstatSync(fd); - } catch (err) { - throw new CpFileError(`fstat \`${path}\` failed: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`fstat \`${path}\` failed: ${error.message}`, error); } }; exports.futimesSync = (fd, atime, mtime, path) => { try { return fs.futimesSync(fd, atime, mtime, path); - } catch (err) { - throw new CpFileError(`futimes \`${path}\` failed: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`futimes \`${path}\` failed: ${error.message}`, error); } }; exports.utimesSync = (path, atime, mtime) => { try { return fs.utimesSync(path, atime, mtime); - } catch (err) { - throw new CpFileError(`utimes \`${path}\` failed: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`utimes \`${path}\` failed: ${error.message}`, error); } }; exports.chmodSync = (path, mode) => { try { return fs.chmodSync(path, mode); - } catch (err) { - throw new CpFileError(`chmod \`${path}\` failed: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`chmod \`${path}\` failed: ${error.message}`, error); } }; exports.chownSync = (path, uid, gid) => { try { return fs.chownSync(path, uid, gid); - } catch (err) { - throw new CpFileError(`chown \`${path}\` failed: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`chown \`${path}\` failed: ${error.message}`, error); } }; -exports.makeDir = path => makeDir(path, {fs}).catch(err => { - throw new CpFileError(`Cannot create directory \`${path}\`: ${err.message}`, err); +exports.makeDir = path => makeDir(path, {fs}).catch(error => { + throw new CpFileError(`Cannot create directory \`${path}\`: ${error.message}`, error); }); exports.makeDirSync = path => { try { makeDir.sync(path, {fs}); - } catch (err) { - throw new CpFileError(`Cannot create directory \`${path}\`: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`Cannot create directory \`${path}\`: ${error.message}`, error); } }; @@ -139,8 +139,8 @@ if (fs.copyFileSync) { exports.copyFileSync = (src, dest, flags) => { try { fs.copyFileSync(src, dest, flags); - } catch (err) { - throw new CpFileError(`Cannot copy from \`${src}\` to \`${dest}\`: ${err.message}`, err); + } catch (error) { + throw new CpFileError(`Cannot copy from \`${src}\` to \`${dest}\`: ${error.message}`, error); } }; } diff --git a/index.js b/index.js index 181f9b1..5e5c5be 100644 --- a/index.js +++ b/index.js @@ -86,12 +86,12 @@ const copySyncNative = (src, dest, opts) => { const flags = opts.overwrite ? null : fsConstants.COPYFILE_EXCL; try { fs.copyFileSync(src, dest, flags); - } catch (err) { - if (!opts.overwrite && err.code === 'EEXIST') { + } catch (error) { + if (!opts.overwrite && error.code === 'EEXIST') { return; } - throw err; + throw error; } fs.utimesSync(dest, stat.atime, stat.mtime); @@ -115,12 +115,12 @@ const copySyncFallback = (src, dest, opts) => { try { write = fs.openSync(dest, opts.overwrite ? 'w' : 'wx'); - } catch (err) { - if (!opts.overwrite && err.code === 'EEXIST') { + } catch (error) { + if (!opts.overwrite && error.code === 'EEXIST') { return; } - throw err; + throw error; } writeSync(); diff --git a/package.json b/package.json index 89ad29e..a1627fa 100644 --- a/package.json +++ b/package.json @@ -45,20 +45,20 @@ ], "dependencies": { "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", + "make-dir": "^2.0.0", "nested-error-stacks": "^2.0.0", - "pify": "^3.0.0", + "pify": "^4.0.1", "safe-buffer": "^5.0.1" }, "devDependencies": { - "ava": "*", - "clear-module": "^2.1.0", + "ava": "^1.2.1", + "clear-module": "^3.1.0", "coveralls": "^3.0.0", "del": "^3.0.0", - "import-fresh": "^2.0.0", - "nyc": "^11.2.1", - "sinon": "^5.0.0", + "import-fresh": "^3.0.0", + "nyc": "^13.3.0", + "sinon": "^7.2.6", "uuid": "^3.0.0", - "xo": "*" + "xo": "^0.24.0" } } diff --git a/test/async.js b/test/async.js index 36dbb83..f22d17f 100644 --- a/test/async.js +++ b/test/async.js @@ -7,7 +7,7 @@ import del from 'del'; import test from 'ava'; import uuid from 'uuid'; import sinon from 'sinon'; -import m from '..'; +import cpFile from '..'; import assertDateEqual from './helpers/assert'; import {buildEACCES, buildENOSPC, buildENOENT, buildEPERM} from './helpers/fs-errors'; @@ -28,71 +28,71 @@ test.afterEach.always(t => { }); test('reject an Error on missing `src`', async t => { - await t.throws(m(), /`src`/); + await t.throwsAsync(() => cpFile(), /`src`/); }); test('reject an Error on missing `dest`', async t => { - await t.throws(m('TARGET'), /`dest`/); + await t.throwsAsync(() => cpFile('TARGET'), /`dest`/); }); test('copy a file', async t => { - await m('license', t.context.dest); + await cpFile('license', t.context.dest); t.is(fs.readFileSync(t.context.dest, 'utf8'), fs.readFileSync('license', 'utf8')); }); test('copy an empty file', async t => { fs.writeFileSync(t.context.src, ''); - await m(t.context.src, t.context.dest); + await cpFile(t.context.src, t.context.dest); t.is(fs.readFileSync(t.context.dest, 'utf8'), ''); }); test('copy big files', async t => { - const buf = crypto.pseudoRandomBytes(THREE_HUNDRED_KILO); + const buf = crypto.randomBytes(THREE_HUNDRED_KILO); fs.writeFileSync(t.context.src, buf); - await m(t.context.src, t.context.dest); + await cpFile(t.context.src, t.context.dest); t.true(buf.equals(fs.readFileSync(t.context.dest))); }); test('do not alter overwrite option', async t => { const opts = {}; - await m('license', t.context.dest, opts); + await cpFile('license', t.context.dest, opts); t.false('overwrite' in opts); }); test('overwrite when enabled', async t => { fs.writeFileSync(t.context.dest, ''); - await m('license', t.context.dest, {overwrite: true}); + await cpFile('license', t.context.dest, {overwrite: true}); t.is(fs.readFileSync(t.context.dest, 'utf8'), fs.readFileSync('license', 'utf8')); }); test('overwrite when options are undefined', async t => { fs.writeFileSync(t.context.dest, ''); - await m('license', t.context.dest); + await cpFile('license', t.context.dest); t.is(fs.readFileSync(t.context.dest, 'utf8'), fs.readFileSync('license', 'utf8')); }); test('do not overwrite when disabled', async t => { fs.writeFileSync(t.context.dest, ''); - await m('license', t.context.dest, {overwrite: false}); + await cpFile('license', t.context.dest, {overwrite: false}); t.is(fs.readFileSync(t.context.dest, 'utf8'), ''); }); test('do not create dest on unreadable src', async t => { - const err = await t.throws(m('node_modules', t.context.dest)); + const err = await t.throwsAsync(() => cpFile('node_modules', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, 'EISDIR', err); t.throws(() => fs.statSync(t.context.dest), /ENOENT/); }); test('do not create dest directory on unreadable src', async t => { - const err = await t.throws(m('node_modules', 'subdir/' + uuid.v4())); + const err = await t.throwsAsync(() => cpFile('node_modules', 'subdir/' + uuid.v4())); t.is(err.name, 'CpFileError', err); t.is(err.code, 'EISDIR', err); t.throws(() => fs.statSync('subdir'), /ENOENT/); }); test('preserve timestamps', async t => { - await m('license', t.context.dest); + await cpFile('license', t.context.dest); const licenseStats = fs.lstatSync('license'); const tmpStats = fs.lstatSync(t.context.dest); assertDateEqual(t, licenseStats.atime, tmpStats.atime); @@ -100,14 +100,14 @@ test('preserve timestamps', async t => { }); test('preserve mode', async t => { - await m('license', t.context.dest); + await cpFile('license', t.context.dest); const licenseStats = fs.lstatSync('license'); const tmpStats = fs.lstatSync(t.context.dest); t.is(licenseStats.mode, tmpStats.mode); }); test('preserve ownership', async t => { - await m('license', t.context.dest); + await cpFile('license', t.context.dest); const licenseStats = fs.lstatSync('license'); const tmpStats = fs.lstatSync(t.context.dest); t.is(licenseStats.gid, tmpStats.gid); @@ -115,7 +115,7 @@ test('preserve ownership', async t => { }); test('throw an Error if `src` does not exists', async t => { - const err = await t.throws(m('NO_ENTRY', t.context.dest)); + const err = await t.throwsAsync(() => cpFile('NO_ENTRY', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, 'ENOENT', err); t.regex(err.message, /`NO_ENTRY`/, err); @@ -129,7 +129,7 @@ test.serial('rethrow mkdir EACCES errors', async t => { fs.mkdir = sinon.stub(fs, 'mkdir').throws(mkdirError); - const err = await t.throws(m('license', dest)); + const err = await t.throwsAsync(() => cpFile('license', dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, mkdirError.errno, err); t.is(err.code, mkdirError.code, err); @@ -154,12 +154,13 @@ test.serial('rethrow ENOSPC errors', async t => { } }); } + return stream; }; clearModule('../fs'); const uncached = importFresh('..'); - const err = await t.throws(uncached('license', t.context.dest)); + const err = await t.throwsAsync(() => uncached('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, noSpaceError.errno, err); t.is(err.code, noSpaceError.code, err); @@ -174,7 +175,7 @@ test.serial('rethrow stat errors', async t => { clearModule('../fs'); const uncached = importFresh('..'); - const err = await t.throws(uncached(t.context.src, t.context.dest)); + const err = await t.throwsAsync(() => uncached(t.context.src, t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, fstatError.errno, err); t.is(err.code, fstatError.code, err); @@ -190,7 +191,7 @@ test.serial('rethrow utimes errors', async t => { clearModule('../fs'); const uncached = importFresh('..'); - const err = await t.throws(uncached('license', t.context.dest)); + const err = await t.throwsAsync(() => uncached('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, 'ENOENT', err); t.true(fs.utimes.called); @@ -205,7 +206,7 @@ test.serial('rethrow chmod errors', async t => { clearModule('../fs'); const uncached = importFresh('..'); - const err = await t.throws(uncached('license', t.context.dest)); + const err = await t.throwsAsync(() => uncached('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, chmodError.code, err); t.is(err.path, chmodError.path, err); @@ -221,7 +222,7 @@ test.serial('rethrow chown errors', async t => { clearModule('../fs'); const uncached = importFresh('..'); - const err = await t.throws(uncached('license', t.context.dest)); + const err = await t.throwsAsync(() => uncached('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, chownError.code, err); t.is(err.path, chownError.path, err); diff --git a/test/helpers/fs-errors.js b/test/helpers/fs-errors.js index 2f58854..ff99117 100644 --- a/test/helpers/fs-errors.js +++ b/test/helpers/fs-errors.js @@ -17,7 +17,7 @@ exports.buildENOENT = path => Object.assign(new Error(`ENOENT: no such file or d path }); -exports.buildEBADF = () => Object.assign(new Error(`EBADF: bad file descriptor`), { +exports.buildEBADF = () => Object.assign(new Error('EBADF: bad file descriptor'), { errno: -9, code: 'EBADF' }); diff --git a/test/progress.js b/test/progress.js index ff07e40..2ce9440 100644 --- a/test/progress.js +++ b/test/progress.js @@ -4,7 +4,7 @@ import fs from 'graceful-fs'; import del from 'del'; import test from 'ava'; import uuid from 'uuid'; -import m from '..'; +import cpFile from '..'; const THREE_HUNDRED_KILO = (100 * 3 * 1024) + 1; @@ -23,11 +23,11 @@ test.afterEach.always(t => { }); test('report progress', async t => { - const buf = crypto.pseudoRandomBytes(THREE_HUNDRED_KILO); + const buf = crypto.randomBytes(THREE_HUNDRED_KILO); fs.writeFileSync(t.context.src, buf); let calls = 0; - await m(t.context.src, t.context.dest).on('progress', progress => { + await cpFile(t.context.src, t.context.dest).on('progress', progress => { calls++; t.is(typeof progress.src, 'string'); t.is(typeof progress.dest, 'string'); @@ -41,11 +41,11 @@ test('report progress', async t => { }); test('report progress of 100% on end', async t => { - const buf = crypto.pseudoRandomBytes(THREE_HUNDRED_KILO); + const buf = crypto.randomBytes(THREE_HUNDRED_KILO); fs.writeFileSync(t.context.src, buf); let lastEvent; - await m(t.context.src, t.context.dest).on('progress', progress => { + await cpFile(t.context.src, t.context.dest).on('progress', progress => { lastEvent = progress; }); @@ -57,7 +57,7 @@ test('report progress for empty files once', async t => { fs.writeFileSync(t.context.src, ''); let calls = 0; - await m(t.context.src, t.context.dest).on('progress', progress => { + await cpFile(t.context.src, t.context.dest).on('progress', progress => { calls++; t.is(progress.size, 0); t.is(progress.written, 0); diff --git a/test/sync.js b/test/sync.js index a421dbc..79c2bbe 100644 --- a/test/sync.js +++ b/test/sync.js @@ -5,7 +5,7 @@ import del from 'del'; import test from 'ava'; import uuid from 'uuid'; import sinon from 'sinon'; -import m from '..'; +import cpFile from '..'; import assertDateEqual from './helpers/assert'; import {buildEACCES, buildENOSPC, buildEBADF, buildEPERM} from './helpers/fs-errors'; @@ -26,71 +26,71 @@ test.afterEach.always(t => { }); test('throw an Error on missing `src`', t => { - t.throws(() => m.sync(), /`src`/); + t.throws(() => cpFile.sync(), /`src`/); }); test('throw an Error on missing `dest`', t => { - t.throws(() => m.sync('TARGET'), /`dest`/); + t.throws(() => cpFile.sync('TARGET'), /`dest`/); }); test('copy a file', t => { - m.sync('license', t.context.dest); + cpFile.sync('license', t.context.dest); t.is(fs.readFileSync(t.context.dest, 'utf8'), fs.readFileSync('license', 'utf8')); }); test('copy an empty file', t => { fs.writeFileSync(t.context.src, ''); - m.sync(t.context.src, t.context.dest); + cpFile.sync(t.context.src, t.context.dest); t.is(fs.readFileSync(t.context.dest, 'utf8'), ''); }); test('copy big files', t => { - const buf = crypto.pseudoRandomBytes(THREE_HUNDRED_KILO); + const buf = crypto.randomBytes(THREE_HUNDRED_KILO); fs.writeFileSync(t.context.src, buf); - m.sync(t.context.src, t.context.dest); + cpFile.sync(t.context.src, t.context.dest); t.true(buf.equals(fs.readFileSync(t.context.dest))); }); test('do not alter overwrite option', t => { const opts = {}; - m.sync('license', t.context.dest, opts); + cpFile.sync('license', t.context.dest, opts); t.false('overwrite' in opts); }); test('overwrite when enabled', t => { fs.writeFileSync(t.context.dest, ''); - m.sync('license', t.context.dest, {overwrite: true}); + cpFile.sync('license', t.context.dest, {overwrite: true}); t.is(fs.readFileSync(t.context.dest, 'utf8'), fs.readFileSync('license', 'utf8')); }); test('overwrite when options are undefined', t => { fs.writeFileSync(t.context.dest, ''); - m.sync('license', t.context.dest); + cpFile.sync('license', t.context.dest); t.is(fs.readFileSync(t.context.dest, 'utf8'), fs.readFileSync('license', 'utf8')); }); test('do not overwrite when disabled', t => { fs.writeFileSync(t.context.dest, ''); - m.sync('license', t.context.dest, {overwrite: false}); + cpFile.sync('license', t.context.dest, {overwrite: false}); t.is(fs.readFileSync(t.context.dest, 'utf8'), ''); }); test('do not create dest on unreadable src', t => { - const err = t.throws(() => m.sync('node_modules', t.context.dest)); + const err = t.throws(() => cpFile.sync('node_modules', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, 'EISDIR', err); t.throws(() => fs.statSync(t.context.dest), /ENOENT/); }); test('do not create dest directory on unreadable src', t => { - const err = t.throws(() => m.sync('node_modules', 'subdir/' + uuid.v4())); + const err = t.throws(() => cpFile.sync('node_modules', 'subdir/' + uuid.v4())); t.is(err.name, 'CpFileError', err); t.is(err.code, 'EISDIR', err); t.throws(() => fs.statSync('subdir'), /ENOENT/); }); test('preserve timestamps', t => { - m.sync('license', t.context.dest); + cpFile.sync('license', t.context.dest); const licenseStats = fs.lstatSync('license'); const tmpStats = fs.lstatSync(t.context.dest); assertDateEqual(t, licenseStats.atime, tmpStats.atime); @@ -98,14 +98,14 @@ test('preserve timestamps', t => { }); test('preserve mode', t => { - m.sync('license', t.context.dest); + cpFile.sync('license', t.context.dest); const licenseStats = fs.lstatSync('license'); const tmpStats = fs.lstatSync(t.context.dest); t.is(licenseStats.mode, tmpStats.mode); }); test('preserve ownership', t => { - m.sync('license', t.context.dest); + cpFile.sync('license', t.context.dest); const licenseStats = fs.lstatSync('license'); const tmpStats = fs.lstatSync(t.context.dest); t.is(licenseStats.gid, tmpStats.gid); @@ -113,7 +113,7 @@ test('preserve ownership', t => { }); test('throw an Error if `src` does not exists', t => { - const err = t.throws(() => m.sync('NO_ENTRY', t.context.dest)); + const err = t.throws(() => cpFile.sync('NO_ENTRY', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.code, 'ENOENT', err); t.regex(err.message, /`NO_ENTRY`/, err); @@ -127,7 +127,7 @@ test('rethrow mkdir EACCES errors', t => { fs.mkdirSync = sinon.stub(fs, 'mkdirSync').throws(mkdirError); - const err = t.throws(() => m.sync('license', dest)); + const err = t.throws(() => cpFile.sync('license', dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, mkdirError.errno, err); t.is(err.code, mkdirError.code, err); @@ -149,7 +149,7 @@ test('rethrow ENOSPC errors in fallback mode', t => { fs.writeFileSync(t.context.src, ''); fs.writeSync = sinon.stub(fs, 'writeSync').throws(noSpaceError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, noSpaceError.errno, err); t.is(err.code, noSpaceError.code, err); @@ -170,7 +170,7 @@ test('rethrow ENOSPC errors in native mode', t => { fs.writeFileSync(t.context.src, ''); fs.copyFileSync = sinon.stub(fs, 'copyFileSync').throws(noSpaceError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, noSpaceError.errno, err); t.is(err.code, noSpaceError.code, err); @@ -191,7 +191,7 @@ test('rethrow fstat errors', t => { fs.writeFileSync(t.context.src, ''); fs.fstatSync = sinon.stub(fs, 'fstatSync').throws(fstatError); - const err = t.throws(() => m.sync(t.context.src, t.context.dest)); + const err = t.throws(() => cpFile.sync(t.context.src, t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, fstatError.errno, err); t.is(err.code, fstatError.code, err); @@ -213,7 +213,7 @@ test('rethrow stat errors', t => { fs.statSync = sinon.stub(fs, 'statSync').throws(statError); - const err = t.throws(() => m.sync(t.context.src, t.context.dest)); + const err = t.throws(() => cpFile.sync(t.context.src, t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, statError.errno, err); t.is(err.code, statError.code, err); @@ -233,7 +233,7 @@ test('rethrow utimes errors in fallback mode', t => { fs.futimesSync = sinon.stub(fs, 'futimesSync').throws(futimesError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, futimesError.errno, err); t.is(err.code, futimesError.code, err); @@ -253,7 +253,7 @@ test('rethrow utimes errors in native mode', t => { fs.utimesSync = sinon.stub(fs, 'utimesSync').throws(futimesError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, futimesError.errno, err); t.is(err.code, futimesError.code, err); @@ -273,7 +273,7 @@ test('rethrow EACCES errors of dest in fallback mode', t => { fs.openSync = sinon.stub(fs, 'openSync').throws(openError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, openError.errno, err); t.is(err.code, openError.code, err); @@ -288,7 +288,7 @@ test('rethrow chmod errors', t => { fs.chmodSync = sinon.stub(fs, 'chmodSync').throws(chmodError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, chmodError.errno, err); t.is(err.code, chmodError.code, err); @@ -302,7 +302,7 @@ test('rethrow chown errors', t => { fs.chownSync = sinon.stub(fs, 'chownSync').throws(chownError); - const err = t.throws(() => m.sync('license', t.context.dest)); + const err = t.throws(() => cpFile.sync('license', t.context.dest)); t.is(err.name, 'CpFileError', err); t.is(err.errno, chownError.errno, err); t.is(err.code, chownError.code, err); From 9bfb207c96ba9810ff5f1dcdabe38fe3a29f1d08 Mon Sep 17 00:00:00 2001 From: Dimitri Benin Date: Sun, 3 Mar 2019 22:11:40 +0100 Subject: [PATCH 2/3] Add TypeScript definition --- index.d.ts | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ index.js | 5 +++- index.test-d.ts | 27 ++++++++++++++++++++ package.json | 4 ++- 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 index.d.ts create mode 100644 index.test-d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..af8c06c --- /dev/null +++ b/index.d.ts @@ -0,0 +1,67 @@ +export interface Options { + /** + * Overwrite existing file. + * + * @default true + */ + readonly overwrite?: boolean; +} + +export interface ProgressData { + /** + * Absolute path to source. + */ + src: string; + + /** + * Absolute path to destination. + */ + dest: string; + + /** + * File size in bytes. + */ + size: number; + + /** + * Copied size in bytes. + */ + written: number; + + /** + * Copied percentage, a value between `0` and `1`. + */ + percent: number; +} + +export interface ProgressEmitter { + /** + * For empty files, the `progress` event is emitted only once. + */ + on(event: 'progress', handler: (data: ProgressData) => void): Promise; +} + +/** + * Copy a file. + * + * @param source File you want to copy. + * @param destination Where you want the file copied. + * @returns A `Promise`. + */ +export default function cpFile( + source: string, + destination: string, + options?: Options +): Promise & ProgressEmitter; + +/** + * Copy a file synchronously. + * + * @param source File you want to copy. + * @param destination Where you want the file copied. + */ +export function sync( + source: string, + destination: string, + options?: Options +): void; diff --git a/index.js b/index.js index 5e5c5be..5b47be0 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ const CpFileError = require('./cp-file-error'); const fs = require('./fs'); const ProgressEmitter = require('./progress-emitter'); -module.exports = (src, dest, opts) => { +const cpFile = (src, dest, opts) => { if (!src || !dest) { return Promise.reject(new CpFileError('`src` and `dest` required')); } @@ -63,6 +63,9 @@ module.exports = (src, dest, opts) => { return promise; }; +module.exports = cpFile; +module.exports.default = cpFile; + const checkSrcIsFile = (stat, src) => { if (stat.isDirectory()) { throw Object.assign(new CpFileError(`EISDIR: illegal operation on a directory '${src}'`), { diff --git a/index.test-d.ts b/index.test-d.ts new file mode 100644 index 0000000..0159759 --- /dev/null +++ b/index.test-d.ts @@ -0,0 +1,27 @@ +import {expectType} from 'tsd-check'; +import cpFile, {sync as cpFileSync, ProgressEmitter, ProgressData} from '.'; + +// CpFile +expectType & ProgressEmitter>( + cpFile('src/unicorn.png', 'dist/unicorn.png') +); +expectType & ProgressEmitter>( + cpFile('src/unicorn.png', 'dist/unicorn.png', {overwrite: false}) +); +expectType>( + cpFile('src/unicorn.png', 'dist/unicorn.png').on('progress', data => { + expectType(data); + + expectType(data.src); + expectType(data.dest); + expectType(data.size); + expectType(data.written); + expectType(data.percent); + }) +); + +// CpFile (sync) +expectType(cpFileSync('src/unicorn.png', 'dist/unicorn.png')); +expectType( + cpFileSync('src/unicorn.png', 'dist/unicorn.png', {overwrite: false}) +); diff --git a/package.json b/package.json index a1627fa..88da4a2 100644 --- a/package.json +++ b/package.json @@ -20,12 +20,13 @@ "node": ">=6" }, "scripts": { - "test": "xo && nyc ava" + "test": "xo && nyc ava && tsd-check" }, "files": [ "cp-file-error.js", "fs.js", "index.js", + "index.d.ts", "progress-emitter.js" ], "keywords": [ @@ -58,6 +59,7 @@ "import-fresh": "^3.0.0", "nyc": "^13.3.0", "sinon": "^7.2.6", + "tsd-check": "^0.3.0", "uuid": "^3.0.0", "xo": "^0.24.0" } From cead0439d61988de43a1add0556e2c23238c306b Mon Sep 17 00:00:00 2001 From: Dimitri Benin Date: Sun, 3 Mar 2019 22:29:17 +0100 Subject: [PATCH 3/3] Add hyphens to param docs --- index.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index af8c06c..be7bff5 100644 --- a/index.d.ts +++ b/index.d.ts @@ -44,8 +44,8 @@ export interface ProgressEmitter { /** * Copy a file. * - * @param source File you want to copy. - * @param destination Where you want the file copied. + * @param source - File you want to copy. + * @param destination - Where you want the file copied. * @returns A `Promise`. */ export default function cpFile( @@ -57,8 +57,8 @@ export default function cpFile( /** * Copy a file synchronously. * - * @param source File you want to copy. - * @param destination Where you want the file copied. + * @param source - File you want to copy. + * @param destination - Where you want the file copied. */ export function sync( source: string,