Skip to content

Commit 56b779b

Browse files
Add findUp.exists() and findUp.sync.exists() (#41)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent 4da9654 commit 56b779b

File tree

6 files changed

+137
-28
lines changed

6 files changed

+137
-28
lines changed

index.d.ts

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ declare const findUp: {
2121
```
2222
// /
2323
// └── Users
24-
// └── sindresorhus
25-
// ├── unicorn.png
26-
// └── foo
27-
// └── bar
28-
// ├── baz
29-
// └── example.js
24+
// └── sindresorhus
25+
// ├── unicorn.png
26+
// └── foo
27+
// └── bar
28+
// ├── baz
29+
// └── example.js
3030
3131
// example.js
3232
import findUp = require('find-up');
@@ -47,24 +47,88 @@ declare const findUp: {
4747
4848
@param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search.
4949
@returns The first path found or `undefined` if none could be found.
50+
51+
@example
52+
```
53+
import path = require('path');
54+
import findUp = require('find-up');
55+
56+
(async () => {
57+
console.log(await findUp(async directory => {
58+
const hasUnicorns = await findUp.exists(path.join(directory, 'unicorn.png'));
59+
return hasUnicorns && directory;
60+
}, {type: 'directory'}));
61+
//=> '/Users/sindresorhus'
62+
})();
63+
```
5064
*/
5165
(matcher: (directory: string) => (findUp.Match | Promise<findUp.Match>), options?: findUp.Options): Promise<string | undefined>;
5266

67+
sync: {
68+
/**
69+
Synchronously find a file or directory by walking up parent directories.
70+
71+
@param name - Name of the file or directory to find. Can be multiple.
72+
@returns The first path found (by respecting the order of `name`s) or `undefined` if none could be found.
73+
*/
74+
(name: string | string[], options?: findUp.Options): string | undefined;
75+
76+
/**
77+
Synchronously find a file or directory by walking up parent directories.
78+
79+
@param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search.
80+
@returns The first path found or `undefined` if none could be found.
81+
82+
@example
83+
```
84+
import path = require('path');
85+
import findUp = require('find-up');
86+
87+
console.log(findUp.sync(directory => {
88+
const hasUnicorns = findUp.sync.exists(path.join(directory, 'unicorn.png'));
89+
return hasUnicorns && directory;
90+
}, {type: 'directory'}));
91+
//=> '/Users/sindresorhus'
92+
```
93+
*/
94+
(matcher: (directory: string) => findUp.Match, options?: findUp.Options): string | undefined;
95+
96+
/**
97+
Synchronously check if a path exists.
98+
99+
@param path - Path to the file or directory.
100+
@returns Whether the path exists.
101+
102+
@example
103+
```
104+
import path = require('path');
105+
import findUp = require('find-up');
106+
107+
console.log(findUp.sync.exists(path.join('/Users', 'sindresorhus', 'unicorn.png')));
108+
//=> true
109+
```
110+
*/
111+
exists(path: string): boolean;
112+
}
113+
53114
/**
54-
Synchronously find a file or directory by walking up parent directories.
115+
Check if a path exists.
55116
56-
@param name - Name of the file or directory to find. Can be multiple.
57-
@returns The first path found (by respecting the order of `name`s) or `undefined` if none could be found.
58-
*/
59-
sync(name: string | string[], options?: findUp.Options): string | undefined;
117+
@param path - Path to a file or directory.
118+
@returns Whether the path exists.
60119
61-
/**
62-
Synchronously find a file or directory by walking up parent directories.
120+
@example
121+
```
122+
import path = require('path');
123+
import findUp = require('find-up');
63124
64-
@param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search.
65-
@returns The first path found or `undefined` if none could be found.
125+
(async () => {
126+
console.log(await findUp.exists(path.join('/Users', 'sindresorhus', 'unicorn.png')));
127+
//=> true
128+
})();
129+
```
66130
*/
67-
sync(matcher: (directory: string) => findUp.Match, options?: findUp.Options): string | undefined;
131+
exists(path: string): Promise<boolean>;
68132

69133
/**
70134
Return this in a `matcher` function to stop the search and force `findUp` to immediately return `undefined`.

index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
const path = require('path');
33
const locatePath = require('locate-path');
4+
const pathExists = require('path-exists');
45

56
const stop = Symbol('findUp.stop');
67

@@ -81,4 +82,8 @@ module.exports.sync = (name, options = {}) => {
8182
}
8283
};
8384

85+
module.exports.exists = pathExists;
86+
87+
module.exports.sync.exists = pathExists.sync;
88+
8489
module.exports.stop = stop;

index.test-d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,7 @@ expectType<string | undefined>(findUp.sync((): findUp.StopSymbol => findUp.stop,
7171
expectType<string | undefined>(findUp.sync((): findUp.StopSymbol => findUp.stop, {type: 'file'}));
7272
expectType<string | undefined>(findUp.sync((): findUp.StopSymbol => findUp.stop, {type: 'directory'}));
7373

74+
expectType<Promise<boolean>>(findUp.exists('unicorn.png'));
75+
expectType<boolean>(findUp.sync.exists('unicorn.png'));
76+
7477
expectType<Symbol>(findUp.stop);

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"path"
4141
],
4242
"dependencies": {
43-
"locate-path": "^5.0.0"
43+
"locate-path": "^5.0.0",
44+
"path-exists": "^4.0.0"
4445
},
4546
"devDependencies": {
4647
"ava": "^1.4.1",

readme.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,17 @@ $ npm install find-up
1515
```
1616
/
1717
└── Users
18-
└── sindresorhus
19-
├── unicorn.png
20-
└── foo
21-
└── bar
22-
├── baz
23-
└── example.js
18+
└── sindresorhus
19+
├── unicorn.png
20+
└── foo
21+
└── bar
22+
├── baz
23+
└── example.js
2424
```
2525

2626
`example.js`
2727

2828
```js
29-
const fs = require('fs');
3029
const path = require('path');
3130
const findUp = require('find-up');
3231

@@ -37,11 +36,10 @@ const findUp = require('find-up');
3736
console.log(await findUp(['rainbow.png', 'unicorn.png']));
3837
//=> '/Users/sindresorhus/unicorn.png'
3938

40-
const pathExists = filePath => fs.promises.access(filePath).then(_ => true).catch(_ => false);
4139
console.log(await findUp(async directory => {
42-
const hasUnicorns = await pathExists(path.join(directory, 'unicorn.png'));
40+
const hasUnicorns = await findUp.exists(path.join(directory, 'unicorn.png'));
4341
return hasUnicorns && directory;
44-
}}, {type: 'directory'});
42+
}, {type: 'directory'}));
4543
//=> '/Users/sindresorhus'
4644
})();
4745
```
@@ -107,6 +105,20 @@ Default: `true`
107105

108106
Allow symbolic links to match if they point to the chosen path type.
109107

108+
### findUp.exists(path)
109+
110+
Returns a `Promise<boolean>` of whether the path exists.
111+
112+
### findUp.sync.exists(path)
113+
114+
Returns a `boolean` of whether the path exists.
115+
116+
#### path
117+
118+
Type: `string`
119+
120+
Path to a file or directory.
121+
110122
### findUp.stop
111123

112124
A [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) that can be returned by a `matcher` function to stop the search and cause `findUp` to immediately return `undefined`. Useful as a performance optimization in case the current working directory is deeply nested in the filesystem.

test.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ test.afterEach(t => {
5050
fs.rmdirSync(t.context.disjoint);
5151
});
5252

53+
const isWindows = process.platform === 'win32';
54+
5355
test('async (child file)', async t => {
5456
const foundPath = await findUp(name.packageJson);
5557

@@ -84,7 +86,7 @@ test('sync (explicit type file)', t => {
8486
t.is(findUp.sync(name.packageJson, {type: 'directory'}), undefined);
8587
});
8688

87-
if (process.platform !== 'win32') {
89+
if (!isWindows) {
8890
test('async (symbolic links)', async t => {
8991
const cwd = absolute.fixtureDirectory;
9092

@@ -506,3 +508,25 @@ test('sync (matcher function stops early)', t => {
506508
t.true(visited.has(cwd));
507509
t.is(visited.size, 1);
508510
});
511+
512+
test('async (check if path exists)', async t => {
513+
if (!isWindows) {
514+
t.true(await findUp.exists(absolute.directoryLink));
515+
t.true(await findUp.exists(absolute.fileLink));
516+
}
517+
518+
t.true(await findUp.exists(absolute.barDir));
519+
t.true(await findUp.exists(absolute.packageJson));
520+
t.false(await findUp.exists('fake'));
521+
});
522+
523+
test('sync (check if path exists)', t => {
524+
if (!isWindows) {
525+
t.true(findUp.sync.exists(absolute.directoryLink));
526+
t.true(findUp.sync.exists(absolute.fileLink));
527+
}
528+
529+
t.true(findUp.sync.exists(absolute.barDir));
530+
t.true(findUp.sync.exists(absolute.packageJson));
531+
t.false(findUp.sync.exists('fake'));
532+
});

0 commit comments

Comments
 (0)