Skip to content

Commit f9d72e1

Browse files
committedNov 5, 2023
Require Node.js 18
1 parent 47b89a7 commit f9d72e1

File tree

8 files changed

+40
-48
lines changed

8 files changed

+40
-48
lines changed
 

‎.github/workflows/main.yml

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ jobs:
1212
node-version:
1313
- 20
1414
- 18
15-
- 16
1615
os:
1716
- ubuntu-latest
1817
- macos-latest
1918
- windows-latest
2019
steps:
21-
- uses: actions/checkout@v3
22-
- uses: actions/setup-node@v3
20+
- uses: actions/checkout@v4
21+
- uses: actions/setup-node@v4
2322
with:
2423
node-version: ${{ matrix.node-version }}
2524
- run: npm install

‎cpy-error.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import NestedError from 'nested-error-stacks';
2-
3-
export default class CpyError extends NestedError {
4-
constructor(message, nested) {
5-
super(message, nested);
6-
Object.assign(this, nested);
1+
export default class CpyError extends Error {
2+
constructor(message, {cause} = {}) {
3+
super(message, {cause});
4+
Object.assign(this, cause);
75
this.name = 'CpyError';
86
}
97
}

‎index.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {type Options as GlobOptions} from 'globby';
2-
import {type Options as CpFileOptions} from 'cp-file';
2+
import {type Options as CopyFileOptions} from 'copy-file';
33

44
export type Entry = {
55
/**
@@ -103,7 +103,7 @@ export type Options = {
103103
```
104104
*/
105105
readonly filter?: (file: Entry) => boolean | Promise<boolean>;
106-
} & Readonly<GlobOptions> & CpFileOptions; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
106+
} & Readonly<GlobOptions> & CopyFileOptions;
107107

108108
export type ProgressData = {
109109
/**

‎index.js

+8-19
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@ import EventEmitter from 'node:events';
33
import path from 'node:path';
44
import os from 'node:os';
55
import pMap from 'p-map';
6-
import arrify from 'arrify';
7-
import {copyFile} from 'cp-file';
6+
import {copyFile} from 'copy-file';
87
import pFilter from 'p-filter';
98
import {isDynamicPattern} from 'globby';
109
import micromatch from 'micromatch';
1110
import CpyError from './cpy-error.js';
1211
import GlobPattern from './glob-pattern.js';
1312

14-
const defaultConcurrency = (os.cpus().length || 1) * 2; // eslint-disable-line unicorn/explicit-length-check
15-
1613
/**
1714
@type {import('./index').Options}
1815
*/
@@ -139,7 +136,7 @@ const renameFile = (source, rename) => {
139136
export default function cpy(
140137
source,
141138
destination,
142-
{concurrency = defaultConcurrency, ...options} = {},
139+
{concurrency = os.availableParallelism(), ...options} = {},
143140
) {
144141
/**
145142
@type {Map<string, import('./index').CopyStatus>}
@@ -167,8 +164,8 @@ export default function cpy(
167164
/**
168165
@type {GlobPattern[]}
169166
*/
170-
let patterns = expandPatternsWithBraceExpansion(arrify(source))
171-
.map(string => string.replace(/\\/g, '/'));
167+
let patterns = expandPatternsWithBraceExpansion([source ?? []].flat())
168+
.map(string => string.replaceAll('\\', '/'));
172169
const sources = patterns.filter(item => !item.startsWith('!'));
173170
const ignore = patterns.filter(item => item.startsWith('!'));
174171

@@ -187,16 +184,11 @@ export default function cpy(
187184
try {
188185
matches = pattern.getMatches();
189186
} catch (error) {
190-
throw new CpyError(
191-
`Cannot glob \`${pattern.originalPath}\`: ${error.message}`,
192-
error,
193-
);
187+
throw new CpyError(`Cannot glob \`${pattern.originalPath}\`: ${error.message}`, {cause: error});
194188
}
195189

196190
if (matches.length === 0 && !isDynamicPattern(pattern.originalPath) && !isDynamicPattern(ignore)) {
197-
throw new CpyError(
198-
`Cannot copy \`${pattern.originalPath}\`: the file doesn't exist`,
199-
);
191+
throw new CpyError(`Cannot copy \`${pattern.originalPath}\`: the file doesn't exist`);
200192
}
201193

202194
entries = [
@@ -219,7 +211,7 @@ export default function cpy(
219211
}
220212

221213
/**
222-
@param {import('cp-file').ProgressData} event
214+
@param {import('copy-file').ProgressData} event
223215
*/
224216
const fileProgressHandler = event => {
225217
const fileStatus = copyStatus.get(event.sourcePath) || {
@@ -269,10 +261,7 @@ export default function cpy(
269261
try {
270262
await copyFile(entry.path, to, {...options, onProgress: fileProgressHandler});
271263
} catch (error) {
272-
throw new CpyError(
273-
`Cannot copy from \`${entry.relativePath}\` to \`${to}\`: ${error.message}`,
274-
error,
275-
);
264+
throw new CpyError(`Cannot copy from \`${entry.relativePath}\` to \`${to}\`: ${error.message}`, {cause: error});
276265
}
277266

278267
return to;

‎index.test-d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ expectType<Promise<string[]> & ProgressEmitter>(
88
cpy('foo.js', 'destination', {rename: 'foobar'}),
99
);
1010
expectType<Promise<string[]> & ProgressEmitter>(
11-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
11+
1212
cpy('foo.js', 'destination', {rename: basename => `prefix-${basename}`}),
1313
);
1414
expectType<Promise<string[]> & ProgressEmitter>(

‎package.json

+17-11
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
"url": "https://sindresorhus.com"
1212
},
1313
"type": "module",
14-
"exports": "./index.js",
14+
"exports": {
15+
"types": "./index.d.ts",
16+
"default": "./index.js"
17+
},
1518
"engines": {
16-
"node": ">=16"
19+
"node": ">=18"
1720
},
1821
"scripts": {
1922
"test": "xo && ava && tsd"
@@ -46,21 +49,24 @@
4649
"directories"
4750
],
4851
"dependencies": {
49-
"arrify": "^3.0.0",
50-
"cp-file": "^10.0.0",
51-
"globby": "^13.1.4",
52+
"copy-file": "^11.0.0",
53+
"globby": "^13.2.2",
5254
"junk": "^4.0.1",
5355
"micromatch": "^4.0.5",
54-
"nested-error-stacks": "^2.1.1",
5556
"p-filter": "^3.0.0",
5657
"p-map": "^6.0.0"
5758
},
5859
"devDependencies": {
59-
"ava": "^5.2.0",
60+
"ava": "^5.3.1",
6061
"proxyquire": "^2.1.3",
61-
"rimraf": "^5.0.0",
62-
"tempy": "^3.0.0",
63-
"tsd": "^0.28.1",
64-
"xo": "^0.54.2"
62+
"rimraf": "^5.0.5",
63+
"tempy": "^3.1.0",
64+
"tsd": "^0.29.0",
65+
"xo": "^0.56.0"
66+
},
67+
"xo": {
68+
"rules": {
69+
"unicorn/prefer-event-target": "off"
70+
}
6571
}
6672
}

‎readme.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
> Copy files
44
5-
**IMPORTANT:** This package has a lot of problems and I unfortunately don't have time to fix them. I would recommend against using this package until these problems are resolved. Help welcome (see the issue tracker)!
5+
**IMPORTANT:** This package has a lot of problems and I unfortunately don't have time to fix them. I would recommend against using this package until these problems are resolved. Help welcome (see the issue tracker) 🙏
66

77
## Why
88

9-
- Fast by using streams.
9+
- Fast by [cloning](https://stackoverflow.com/questions/71629903/node-js-why-we-should-use-copyfile-ficlone-and-copyfile-ficlone-force-what-is) the files whenever possible.
1010
- Resilient by using [graceful-fs](https://github.com/isaacs/node-graceful-fs).
1111
- User-friendly by accepting [globs](https://github.com/sindresorhus/globby#globbing-patterns) and creating non-existent destination directories.
1212
- User-friendly error messages.
@@ -227,6 +227,6 @@ await cpy(source, destination).on('progress', progress => {
227227
## Related
228228

229229
- [cpy-cli](https://github.com/sindresorhus/cpy-cli) - CLI for this module
230-
- [cp-file](https://github.com/sindresorhus/cp-file) - Copy a single file
230+
- [copy-file](https://github.com/sindresorhus/copy-file) - Copy a single file
231231
- [move-file](https://github.com/sindresorhus/move-file) - Move a file
232232
- [make-dir](https://github.com/sindresorhus/make-dir) - Make a directory and its parents if needed

‎test.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,9 @@ test('flatten single file', async t => {
287287

288288
// TODO: Enable again when ESM supports mocking.
289289
// eslint-disable-next-line ava/no-skip-test
290-
test.skip('cp-file errors are CpyErrors', async t => {
291-
const cpy = cpyMockedError('cp-file');
292-
await t.throwsAsync(cpy('license', t.context.dir), {message: /cp-file/, instanceOf: CpyError});
290+
test.skip('copy-file errors are CpyErrors', async t => {
291+
const cpy = cpyMockedError('copy-file');
292+
await t.throwsAsync(cpy('license', t.context.dir), {message: /copy-file/, instanceOf: CpyError});
293293
});
294294

295295
test('throws on non-existing file', async t => {

0 commit comments

Comments
 (0)
Please sign in to comment.