Skip to content

Commit

Permalink
Require Node.js 14 and move to ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Jun 21, 2022
1 parent cf322af commit 176d12f
Show file tree
Hide file tree
Showing 15 changed files with 427 additions and 535 deletions.
3 changes: 0 additions & 3 deletions .github/funding.yml

This file was deleted.

8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Expand Up @@ -10,16 +10,16 @@ jobs:
fail-fast: false
matrix:
node-version:
- 18
- 16
- 14
- 12
- 10
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
10 changes: 10 additions & 0 deletions copy-file-error.js
@@ -0,0 +1,10 @@
import NestedError from 'nested-error-stacks';

// TODO: Use `Error#cause`.
export default class CopyFileError extends NestedError {
constructor(message, nested) {
super(message, nested);
Object.assign(this, nested);
this.name = 'CopyFileError';
}
}
12 changes: 0 additions & 12 deletions cp-file-error.js

This file was deleted.

67 changes: 33 additions & 34 deletions fs.js
@@ -1,78 +1,77 @@
'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);

try {
await pEvent(read, ['readable', 'end']);
} 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);
}
};
195 changes: 88 additions & 107 deletions index.d.ts
@@ -1,124 +1,105 @@
declare namespace cpFile {
interface Options {
/**
Overwrite existing destination file.
@default true
*/
readonly overwrite?: boolean;

/**
[Permissions](https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation) for created directories.
It has no effect on Windows.
@default 0o777
*/
readonly directoryMode?: number;

/**
The working directory to find source files.
The source and destination path are relative to this.
@default process.cwd()
*/
readonly cwd?: string;
}

interface AsyncOptions {
/**
The given function is called whenever there is measurable progress.
Note: For empty files, the `onProgress` event is emitted only once.
@example
```
import cpFile = require('cp-file');
(async () => {
await cpFile('source/unicorn.png', 'destination/unicorn.png', {
onProgress: progress => {
// ...
}
});
})();
```
*/
readonly onProgress?: (progress: ProgressData) => void;
}

interface ProgressData {
/**
Absolute path to source.
*/
sourcePath: string;

/**
Absolute path to destination.
*/
destinationPath: string;

/**
File size in bytes.
*/
size: number;

/**
Copied size in bytes.
*/
writtenBytes: number;

/**
Copied percentage, a value between `0` and `1`.
*/
percent: number;
}

interface ProgressEmitter {
/**
@deprecated Use `onProgress` option instead.
Note: For empty files, the `progress` event is emitted only once.
*/
on(event: 'progress', handler: AsyncOptions['onProgress']): Promise<void>;
}
export interface Options {
/**
Overwrite existing destination file.
@default true
*/
readonly overwrite?: boolean;

/**
[Permissions](https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation) for created directories.
It has no effect on Windows.
@default 0o777
*/
readonly directoryMode?: number;

/**
The working directory to find source files.
The source and destination path are relative to this.
@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 & cpFile.AsyncOptions): Promise<void> & cpFile.ProgressEmitter;
readonly onProgress?: (progress: ProgressData) => void;
}

export interface ProgressData {
/**
Absolute path to source.
*/
sourcePath: string;

/**
Copy a file synchronously.
Absolute path to destination.
*/
destinationPath: string;

@param source - The file you want to copy.
@param destination - Where you want the file copied.
/**
File size in bytes.
*/
size: number;

@example
```
import cpFile = require('cp-file');
/**
Copied size in bytes.
*/
writtenBytes: number;

cpFile.sync('source/unicorn.png', 'destination/unicorn.png');
```
/**
Copied percentage, a value between `0` and `1`.
*/
sync(source: string, destination: string, options?: cpFile.Options): void;
};
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';
export = cpFile;
copyFileSync('source/unicorn.png', 'destination/unicorn.png');
```
*/
export function copyFileSync(source: string, destination: string, options?: Options): void;

0 comments on commit 176d12f

Please sign in to comment.