New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for path matcher function #28
Changes from 11 commits
95d4390
8b80cf1
e8072bb
44e67bf
102b688
7a83413
6ad0dd8
ca48c76
f858bdd
eff8479
cba6f26
af9d361
b10d5b2
eb97a2f
ae4d8bc
bb10d62
94fafd1
41b8bdb
cf3157c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,8 @@ $ npm install find-up | |
`example.js` | ||
|
||
```js | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const findUp = require('find-up'); | ||
|
||
(async () => { | ||
|
@@ -47,13 +49,28 @@ const findUp = require('find-up'); | |
|
||
console.log(await findUp(['rainbow.png', 'unicorn.png'])); | ||
//=> '/Users/sindresorhus/unicorn.png' | ||
|
||
console.log(await findUp(dir => { | ||
return fs.existsSync(path.join(dir, 'unicorn.png')) && 'foo'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You shouldn't mix async and sync. Here, it should have used an async method to check whether it exists. The problem is that I'm thinking:
I know this seems like a lot, but I want Maybe we don't need the The methods could alternatively be passed into the callback as a sort of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or maybe we should have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I should've used
But now const pathExists = filepath => fs.promises.access(filepath).then(_ => true).catch(_ => false);
console.log(await findUp(async (directory) => {
const isInstalled = await pathExists(path.join(directory, 'node_modules'));
return isInstalled && 'package.json';
}}); That could replace the example below as well. As for the utility methods, I agree they are useful and I'd also prefer for them to be properties on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
👍
👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
})); | ||
//=> '/Users/sindresorhus/foo' | ||
|
||
console.log(await findUp(async dir => { | ||
const children = await fs.promises.readdir(dir); | ||
if (children.some(fileName => fileName.endsWith('.png'))) { | ||
return dir; | ||
} | ||
})); | ||
//=> '/Users/sindresorhus' | ||
sholladay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
})(); | ||
``` | ||
|
||
|
||
## API | ||
|
||
|
||
### findUp(name, [options]) | ||
### findUp(matcher, [options]) | ||
|
||
Returns a `Promise` for either the path or `undefined` if it couldn't be found. | ||
|
||
|
@@ -62,6 +79,7 @@ Returns a `Promise` for either the path or `undefined` if it couldn't be found. | |
Returns a `Promise` for either the first path found (by respecting the order) or `undefined` if none could be found. | ||
|
||
### findUp.sync(name, [options]) | ||
### findUp.sync(matcher, [options]) | ||
|
||
Returns a path or `undefined` if it couldn't be found. | ||
|
||
|
@@ -75,6 +93,14 @@ Type: `string` | |
|
||
Name of the file or directory to find. | ||
|
||
#### matcher | ||
|
||
Type: `Function` | ||
|
||
A function that will be called with each directory until it returns a filepath to stop the search or the root directory has been reached and nothing was found. Useful if you want to match files with a certain pattern, set of permissions, or other advanced use cases. | ||
sholladay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
When using async mode, `matcher` may optionally be an `async` function or return a `Promise` for the filepath. | ||
sholladay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### options | ||
|
||
Type: `object` | ||
|
@@ -86,6 +112,20 @@ Default: `process.cwd()` | |
|
||
Directory to start from. | ||
|
||
### findUp.stop | ||
|
||
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. | ||
|
||
```js | ||
const path = require('path'); | ||
const findUp = require('find-up'); | ||
|
||
(async () => { | ||
await findUp((directory) => { | ||
return path.basename(directory) === 'work' ? findUp.stop : 'logo.png'; | ||
}); | ||
})(); | ||
``` | ||
|
||
## Security | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I discovered that there's seemingly no way for me to tell TypeScript that the only boolean type that should be allowed is
false
. Annoying. Should we support returningtrue
? It's easy to support, but I remember we discussed that the semantics may not be obvious.Also, should I put this type on the namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should type this one as:
While JS is loose, we should try to keep the TS types strict.
Yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree in general, but in this case, if we are very strict, then people can't necessarily do:
... since
foo
might befalse
ornull
, etc. Is it worth losing that nice syntax?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TS users will definitely say yes. That's why they're using TS; they want strict types. It doesn't affect the majority that is using plain JS.
TS users can do:
It's just a tiny bit more verbose.