Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cp-file

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cp-file - npm Package Compare versions

Comparing version 9.1.0 to 10.0.0

copy-file-error.js

67

fs.js

@@ -1,17 +0,16 @@

'use strict';
const {promisify} = require('util');
const fs = require('graceful-fs');
const makeDir = require('make-dir');
const pEvent = require('p-event');
const CpFileError = require('./cp-file-error');
import {promisify} from 'node:util';
import fs from 'graceful-fs';
import {pEvent} from 'p-event';
import CopyFileError from './copy-file-error.js';
const stat = promisify(fs.stat);
const lstat = promisify(fs.lstat);
const utimes = promisify(fs.utimes);
const chmod = promisify(fs.chmod);
const statP = promisify(fs.stat);
const lstatP = promisify(fs.lstat);
const utimesP = promisify(fs.utimes);
const chmodP = promisify(fs.chmod);
const makeDirectoryP = promisify(fs.mkdir);
exports.closeSync = fs.closeSync.bind(fs);
exports.createWriteStream = fs.createWriteStream.bind(fs);
export const closeSync = fs.closeSync.bind(fs);
export const createWriteStream = fs.createWriteStream.bind(fs);
exports.createReadStream = async (path, options) => {
export async function createReadStream(path, options) {
const read = fs.createReadStream(path, options);

@@ -22,58 +21,58 @@

} catch (error) {
throw new CpFileError(`Cannot read from \`${path}\`: ${error.message}`, error);
throw new CopyFileError(`Cannot read from \`${path}\`: ${error.message}`, error);
}
return read;
};
}
exports.stat = path => stat(path).catch(error => {
throw new CpFileError(`Cannot stat path \`${path}\`: ${error.message}`, error);
export const stat = path => statP(path).catch(error => {
throw new CopyFileError(`Cannot stat path \`${path}\`: ${error.message}`, error);
});
exports.lstat = path => lstat(path).catch(error => {
throw new CpFileError(`lstat \`${path}\` failed: ${error.message}`, error);
export const lstat = path => lstatP(path).catch(error => {
throw new CopyFileError(`lstat \`${path}\` failed: ${error.message}`, error);
});
exports.utimes = (path, atime, mtime) => utimes(path, atime, mtime).catch(error => {
throw new CpFileError(`utimes \`${path}\` failed: ${error.message}`, error);
export const utimes = (path, atime, mtime) => utimesP(path, atime, mtime).catch(error => {
throw new CopyFileError(`utimes \`${path}\` failed: ${error.message}`, error);
});
exports.chmod = (path, mode) => chmod(path, mode).catch(error => {
throw new CpFileError(`chmod \`${path}\` failed: ${error.message}`, error);
export const chmod = (path, mode) => chmodP(path, mode).catch(error => {
throw new CopyFileError(`chmod \`${path}\` failed: ${error.message}`, error);
});
exports.statSync = path => {
export const statSync = path => {
try {
return fs.statSync(path);
} catch (error) {
throw new CpFileError(`stat \`${path}\` failed: ${error.message}`, error);
throw new CopyFileError(`stat \`${path}\` failed: ${error.message}`, error);
}
};
exports.utimesSync = (path, atime, mtime) => {
export const utimesSync = (path, atime, mtime) => {
try {
return fs.utimesSync(path, atime, mtime);
} catch (error) {
throw new CpFileError(`utimes \`${path}\` failed: ${error.message}`, error);
throw new CopyFileError(`utimes \`${path}\` failed: ${error.message}`, error);
}
};
exports.makeDir = (path, options) => makeDir(path, {...options, fs}).catch(error => {
throw new CpFileError(`Cannot create directory \`${path}\`: ${error.message}`, error);
export const makeDirectory = (path, options) => makeDirectoryP(path, {...options, recursive: true}).catch(error => {
throw new CopyFileError(`Cannot create directory \`${path}\`: ${error.message}`, error);
});
exports.makeDirSync = (path, options) => {
export const makeDirectorySync = (path, options) => {
try {
makeDir.sync(path, {...options, fs});
fs.mkdirSync(path, {...options, recursive: true});
} catch (error) {
throw new CpFileError(`Cannot create directory \`${path}\`: ${error.message}`, error);
throw new CopyFileError(`Cannot create directory \`${path}\`: ${error.message}`, error);
}
};
exports.copyFileSync = (source, destination, flags) => {
export const copyFileSync = (source, destination, flags) => {
try {
fs.copyFileSync(source, destination, flags);
} catch (error) {
throw new CpFileError(`Cannot copy from \`${source}\` to \`${destination}\`: ${error.message}`, error);
throw new CopyFileError(`Cannot copy from \`${source}\` to \`${destination}\`: ${error.message}`, error);
}
};

@@ -1,91 +0,105 @@

declare namespace cpFile {
interface Options {
/**
Overwrite existing destination file.
export interface Options {
/**
Overwrite existing destination file.
@default true
*/
readonly overwrite?: boolean;
@default true
*/
readonly overwrite?: boolean;
/**
[Permissions](https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation) for created directories.
/**
[Permissions](https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation) for created directories.
It has no effect on Windows.
It has no effect on Windows.
@default 0o777
*/
readonly directoryMode?: number;
}
@default 0o777
*/
readonly directoryMode?: number;
interface ProgressData {
/**
Absolute path to source.
*/
sourcePath: string;
/**
The working directory to find source files.
/**
Absolute path to destination.
*/
destinationPath: string;
The source and destination path are relative to this.
/**
File size in bytes.
*/
size: number;
/**
Copied size in bytes.
*/
writtenBytes: number;
/**
Copied percentage, a value between `0` and `1`.
*/
percent: number;
}
interface ProgressEmitter {
/**
Note: For empty files, the `progress` event is emitted only once.
*/
on(event: 'progress', handler: (data: ProgressData) => void): Promise<void>;
}
@default process.cwd()
*/
readonly cwd?: string;
}
declare const cpFile: {
export interface AsyncOptions {
/**
Copy a file.
The given function is called whenever there is measurable progress.
@param source - The file you want to copy.
@param destination - Where you want the file copied.
@returns A `Promise` that resolves when the file is copied.
Note: For empty files, the `onProgress` event is emitted only once.
@example
```
import cpFile = require('cp-file');
import {copyFile} from 'cp-file';
(async () => {
await cpFile('source/unicorn.png', 'destination/unicorn.png');
console.log('File copied');
})();
await copyFile('source/unicorn.png', 'destination/unicorn.png', {
onProgress: progress => {
// …
}
});
```
*/
(source: string, destination: string, options?: cpFile.Options): Promise<void> & cpFile.ProgressEmitter;
readonly onProgress?: (progress: ProgressData) => void;
}
export interface ProgressData {
/**
Copy a file synchronously.
Absolute path to source.
*/
sourcePath: string;
@param source - The file you want to copy.
@param destination - Where you want the file copied.
/**
Absolute path to destination.
*/
destinationPath: string;
@example
```
import cpFile = require('cp-file');
/**
File size in bytes.
*/
size: number;
cpFile.sync('source/unicorn.png', 'destination/unicorn.png');
```
/**
Copied size in bytes.
*/
sync(source: string, destination: string, options?: cpFile.Options): void;
};
writtenBytes: number;
export = cpFile;
/**
Copied percentage, a value between `0` and `1`.
*/
percent: number;
}
/**
Copy a file.
@param source - The file you want to copy.
@param destination - Where you want the file copied.
@returns A `Promise` that resolves when the file is copied.
@example
```
import {copyFile} from 'cp-file';
await copyFile('source/unicorn.png', 'destination/unicorn.png');
console.log('File copied');
```
*/
export function copyFile(source: string, destination: string, options?: Options & AsyncOptions): Promise<void>;
/**
Copy a file synchronously.
@param source - The file you want to copy.
@param destination - Where you want the file copied.
@example
```
import {copyFileSync} from 'cp-file';
copyFileSync('source/unicorn.png', 'destination/unicorn.png');
```
*/
export function copyFileSync(source: string, destination: string, options?: Options): void;

@@ -1,25 +0,35 @@

'use strict';
const path = require('path');
const {constants: fsConstants} = require('fs');
const pEvent = require('p-event');
const CpFileError = require('./cp-file-error');
const fs = require('./fs');
const ProgressEmitter = require('./progress-emitter');
import path from 'node:path';
import {constants as fsConstants} from 'node:fs';
import {pEvent} from 'p-event';
import CopyFileError from './copy-file-error.js';
import * as fs from './fs.js';
const cpFileAsync = async (source, destination, options, progressEmitter) => {
const copyFileAsync = async (source, destination, options) => {
let readError;
const stat = await fs.stat(source);
progressEmitter.size = stat.size;
const {size} = await fs.stat(source);
const readStream = await fs.createReadStream(source);
await fs.makeDir(path.dirname(destination), {mode: options.directoryMode});
await fs.makeDirectory(path.dirname(destination), {mode: options.directoryMode});
const writeStream = fs.createWriteStream(destination, {flags: options.overwrite ? 'w' : 'wx'});
const emitProgress = writtenBytes => {
if (typeof options.onProgress !== 'function') {
return;
}
options.onProgress({
sourcePath: path.resolve(source),
destinationPath: path.resolve(destination),
size,
writtenBytes,
percent: writtenBytes === size ? 1 : writtenBytes / size,
});
};
readStream.on('data', () => {
progressEmitter.writtenBytes = writeStream.bytesWritten;
emitProgress(writeStream.bytesWritten);
});
readStream.once('error', error => {
readError = new CpFileError(`Cannot read from \`${source}\`: ${error.message}`, error);
writeStream.end();
readError = new CopyFileError(`Cannot read from \`${source}\`: ${error.message}`, error);
});

@@ -32,6 +42,6 @@

await writePromise;
progressEmitter.writtenBytes = progressEmitter.size;
emitProgress(size);
shouldUpdateStats = true;
} catch (error) {
throw new CpFileError(`Cannot write to \`${destination}\`: ${error.message}`, error);
throw new CopyFileError(`Cannot write to \`${destination}\`: ${error.message}`, error);
}

@@ -48,3 +58,3 @@

fs.utimes(destination, stats.atime, stats.mtime),
fs.chmod(destination, stats.mode)
fs.chmod(destination, stats.mode),
]);

@@ -54,31 +64,35 @@ }

const cpFile = (sourcePath, destinationPath, options) => {
const resolvePath = (cwd, sourcePath, destinationPath) => {
sourcePath = path.resolve(cwd, sourcePath);
destinationPath = path.resolve(cwd, destinationPath);
return {
sourcePath,
destinationPath,
};
};
export async function copyFile(sourcePath, destinationPath, options = {}) {
if (!sourcePath || !destinationPath) {
return Promise.reject(new CpFileError('`source` and `destination` required'));
throw new CopyFileError('`source` and `destination` required');
}
if (options.cwd) {
({sourcePath, destinationPath} = resolvePath(options.cwd, sourcePath, destinationPath));
}
options = {
overwrite: true,
...options
...options,
};
const progressEmitter = new ProgressEmitter(path.resolve(sourcePath), path.resolve(destinationPath));
const promise = cpFileAsync(sourcePath, destinationPath, options, progressEmitter);
return copyFileAsync(sourcePath, destinationPath, options);
}
promise.on = (...arguments_) => {
progressEmitter.on(...arguments_);
return promise;
};
return promise;
};
module.exports = cpFile;
const checkSourceIsFile = (stat, source) => {
if (stat.isDirectory()) {
throw Object.assign(new CpFileError(`EISDIR: illegal operation on a directory '${source}'`), {
throw Object.assign(new CopyFileError(`EISDIR: illegal operation on a directory '${source}'`), {
errno: -21,
code: 'EISDIR',
source
source,
});

@@ -88,19 +102,23 @@ }

module.exports.sync = (source, destination, options) => {
if (!source || !destination) {
throw new CpFileError('`source` and `destination` required');
export function copyFileSync(sourcePath, destinationPath, options = {}) {
if (!sourcePath || !destinationPath) {
throw new CopyFileError('`source` and `destination` required');
}
if (options.cwd) {
({sourcePath, destinationPath} = resolvePath(options.cwd, sourcePath, destinationPath));
}
options = {
overwrite: true,
...options
...options,
};
const stat = fs.statSync(source);
checkSourceIsFile(stat, source);
fs.makeDirSync(path.dirname(destination), {mode: options.directoryMode});
const stat = fs.statSync(sourcePath);
checkSourceIsFile(stat, sourcePath);
fs.makeDirectorySync(path.dirname(destinationPath), {mode: options.directoryMode});
const flags = options.overwrite ? null : fsConstants.COPYFILE_EXCL;
try {
fs.copyFileSync(source, destination, flags);
fs.copyFileSync(sourcePath, destinationPath, flags);
} catch (error) {

@@ -114,3 +132,3 @@ if (!options.overwrite && error.code === 'EEXIST') {

fs.utimesSync(destination, stat.atime, stat.mtime);
};
fs.utimesSync(destinationPath, stat.atime, stat.mtime);
}
{
"name": "cp-file",
"version": "9.1.0",
"version": "10.0.0",
"description": "Copy a file",

@@ -13,4 +13,7 @@ "license": "MIT",

},
"type": "module",
"exports": "./index.js",
"types": "./index.d.ts",
"engines": {
"node": ">=10"
"node": ">=14.16"
},

@@ -21,7 +24,6 @@ "scripts": {

"files": [
"cp-file-error.js",
"fs.js",
"index.js",
"index.d.ts",
"progress-emitter.js"
"copy-file-error.js",
"fs.js"
],

@@ -44,24 +46,26 @@ "keywords": [

"dependencies": {
"graceful-fs": "^4.1.2",
"make-dir": "^3.0.0",
"nested-error-stacks": "^2.0.0",
"p-event": "^4.1.0"
"graceful-fs": "^4.2.10",
"nested-error-stacks": "^2.1.1",
"p-event": "^5.0.1"
},
"devDependencies": {
"ava": "^2.1.0",
"clear-module": "^3.1.0",
"coveralls": "^3.0.4",
"del": "^5.1.0",
"import-fresh": "^3.0.0",
"nyc": "^15.0.0",
"sinon": "^9.0.0",
"tsd": "^0.11.0",
"uuid": "^7.0.2",
"xo": "^0.28.2"
"ava": "^4.3.0",
"clear-module": "^4.1.2",
"coveralls": "^3.1.1",
"del": "^6.1.1",
"import-fresh": "^3.3.0",
"nyc": "^15.1.0",
"sinon": "^14.0.0",
"tsd": "^0.21.0",
"xo": "^0.50.0"
},
"xo": {
"rules": {
"unicorn/string-content": "off"
"unicorn/string-content": "off",
"ava/assertion-arguments": "off"
}
},
"ava": {
"workerThreads": false
}
}

@@ -16,5 +16,5 @@ # cp-file

```sh
npm install cp-file
```
$ npm install cp-file
```

@@ -24,8 +24,6 @@ ## Usage

```js
const cpFile = require('cp-file');
import {copyFile} from 'cp-file';
(async () => {
await cpFile('source/unicorn.png', 'destination/unicorn.png');
console.log('File copied');
})();
await copyFile('source/unicorn.png', 'destination/unicorn.png');
console.log('File copied');
```

@@ -35,7 +33,7 @@

### cpFile(source, destination, options?)
### copyFile(source, destination, options?)
Returns a `Promise` that resolves when the file is copied.
### cpFile.sync(source, destination, options?)
### copyFileSync(source, destination, options?)

@@ -65,2 +63,11 @@ #### source

##### cwd
Type: `string`\
Default: `process.cwd()`
The working directory to find source files.
The source and destination path are relative to this.
##### directoryMode

@@ -75,11 +82,11 @@

### cpFile.on('progress', handler)
##### onProgress
Progress reporting. Only available when using the async method.
Type: `(progress: ProgressData) => void`
#### handler(data)
The given function is called whenever there is measurable progress.
Type: `Function`
Only available when using the async method.
##### data
###### `ProgressData`

@@ -96,3 +103,3 @@ ```js

- `source` and `destination` are absolute paths.
- `sourcePath` and `destinationPath` are absolute paths.
- `size` and `writtenBytes` are in bytes.

@@ -103,14 +110,12 @@ - `percent` is a value between `0` and `1`.

- For empty files, the `progress` event is emitted only once.
- The `.on()` method is available only right after the initial `cpFile()` call. So make sure
you add a `handler` before `.then()`:
- For empty files, the `onProgress` callback function is emitted only once.
```js
const cpFile = require('cp-file');
import {copyFile} from 'cp-file';
(async () => {
await cpFile(source, destination).on('progress', data => {
await copyFile(source, destination, {
onProgress: progress => {
// …
});
})();
}
});
```

@@ -117,0 +122,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc