From 4413b4117d3012e33a39175223572077e157073d Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Thu, 11 Jul 2024 23:21:20 +0000 Subject: [PATCH 01/33] feat: add `fs/resolve-parent-paths` Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/README.md | 199 ++++++++++++ .../benchmark/benchmark.js | 96 ++++++ .../@stdlib/fs/resolve-parent-paths/bin/cli | 85 ++++++ .../fs/resolve-parent-paths/docs/repl.txt | 60 ++++ .../docs/types/index.d.ts | 141 +++++++++ .../resolve-parent-paths/docs/types/test.ts | 119 ++++++++ .../fs/resolve-parent-paths/docs/usage.txt | 9 + .../fs/resolve-parent-paths/etc/cli_opts.json | 17 ++ .../fs/resolve-parent-paths/examples/index.js | 47 +++ .../fs/resolve-parent-paths/lib/async.js | 132 ++++++++ .../fs/resolve-parent-paths/lib/index.js | 58 ++++ .../fs/resolve-parent-paths/lib/sync.js | 86 ++++++ .../fs/resolve-parent-paths/lib/validate.js | 67 +++++ .../fs/resolve-parent-paths/package.json | 78 +++++ .../test/fixtures/read_error.js.txt | 38 +++ .../resolve-parent-paths/test/test.async.js | 283 ++++++++++++++++++ .../fs/resolve-parent-paths/test/test.cli.js | 201 +++++++++++++ .../fs/resolve-parent-paths/test/test.js | 38 +++ .../fs/resolve-parent-paths/test/test.sync.js | 227 ++++++++++++++ .../test/test.validate.js | 121 ++++++++ 20 files changed, 2102 insertions(+) create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js create mode 100755 lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/test/fixtures/read_error.js.txt create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js create mode 100644 lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md new file mode 100644 index 00000000000..3648e46f05f --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md @@ -0,0 +1,199 @@ + + +# Resolve Parent Paths + +> Resolve a path from a set of paths by walking parent directories. + +
+ +## Usage + +```javascript +var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); +``` + + + +#### resolveParentPaths( paths\[, options], clbk ) + +Asynchronously resolves a path from a set of paths by walking parent directories. + +```javascript +resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); + +function onPath( error, path ) { + if ( error ) { + throw error; + } + console.log( path ); + // => '...' +} +``` + +The function accepts the following `options`: + +- **dir**: base directory from which to begin walking. May be either an absolute path or a path relative to the current working directory. + +By default, the function begins walking from the current working directory. To specify an alternative directory, set the `dir` option. + +```javascript +var opts = { + 'dir': __dirname +}; +resolveParentPaths( [ 'package.json' ], opts, onPath ); + +function onPath( error, path ) { + if ( error ) { + throw error; + } + console.log( path ); + // => '...' +} +``` + +#### resolveParentPaths.sync( paths\[, options] ) + +Synchronously resolves a path from a set of paths by walking parent directories. + +```javascript +var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); +// returns '...' +``` + +The function accepts the same `options` as [`resolveParentPaths()`](#resolve-parent-paths). + +
+ + + +
+ +## Notes + +- If unable to resolve a path, both functions return `null`. +- Paths are resolved in the order they appear in the array. +- This implementation is **not** similar in functionality to core [`path.resolve`][node-core-path-resolve]. The latter performs string manipulation to generate a full path. This implementation walks parent directories to perform a **search**, thereby touching the file system. Accordingly, this implementation resolves a _real_ absolute file path and is intended for use when a target's location in a parent directory is unknown relative to a child directory; e.g., when wanting to find a package root from deep within a package directory. + +
+ + + +
+ +## Examples + + + +```javascript +var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); + +var opts = { + 'dir': __dirname +}; + +/* Sync */ + +var out = resolveParentPaths.sync( [ 'package.json', 'non_existent_basename' ], opts ); +// returns '...' + +out = resolveParentPaths.sync( [ 'non_existent_basename' ] ); +// returns null + +/* Async */ + +resolveParentPaths( [ 'package.json', './../non_existent_path' ], opts, onPath ); +resolveParentPaths( [ './../non_existent_path' ], onPath ); + +function onPath( error, path ) { + if ( error ) { + throw error; + } + console.log( path ); +} +``` + +
+ + + +* * * + +
+ +## CLI + +
+ +### Usage + +```text +Usage: resolve-parent-paths [options] [...] + +Options: + + -h, --help Print this message. + -V, --version Print the package version. + --dir dir Base search directory. +``` + +
+ + + +
+ +### Examples + +```bash +$ resolve-parent-paths package.json package-lock.json +``` + +
+ + + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js new file mode 100644 index 00000000000..a4571f83d8c --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js @@ -0,0 +1,96 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pkg = require( './../package.json' ).name; +var resolveParentPaths = require( './../lib' ); + + +// VARIABLES // + +var PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ 'package.json', 'beep-boop!!!hello world!?!' ] +]; + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var opts; + var i; + + opts = { + 'dir': __dirname + }; + + i = 0; + b.tic(); + + return next(); + + function next() { + i += 1; + if ( i <= b.iterations ) { + return resolveParentPaths( PATHS[ i % 3 ], opts, done ); + } + b.toc(); + b.pass( 'benchmark finished' ); + b.end(); + } + + function done( error, path ) { + if ( error ) { + b.fail( error.message ); + } + if ( path === null ) { + b.fail( 'should return a path' ); + } + next(); + } +}); + +bench( pkg+':sync', function benchmark( b ) { + var opts; + var path; + var i; + + opts = { + 'dir': __dirname + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + path = resolveParentPaths.sync( PATHS[ i % 3 ], opts ); + if ( path === null ) { + b.fail( 'should return a path' ); + } + } + b.toc(); + if ( path === null ) { + b.fail( 'should return a path' ); + } else { + b.pass( 'benchmark finished' ); + } + b.end(); +}); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli new file mode 100755 index 00000000000..f86c323ad91 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli @@ -0,0 +1,85 @@ +#!/usr/bin/env node + +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var readFileSync = require( '@stdlib/fs/read-file' ).sync; +var CLI = require( '@stdlib/cli/ctor' ); +var resolveParentPaths = require( './../lib' ); + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +* @returns {void} +*/ +function main() { + var flags; + var args; + var opts; + var cli; + + // Create a command-line interface: + cli = new CLI({ + 'pkg': require( './../package.json' ), + 'options': require( './../etc/cli_opts.json' ), + 'help': readFileSync( resolve( __dirname, '..', 'docs', 'usage.txt' ), { + 'encoding': 'utf8' + }) + }); + + // Get any provided command-line options: + flags = cli.flags(); + if ( flags.help || flags.version ) { + return; + } + + // Get any provided command-line arguments: + args = cli.args(); + + opts = {}; + if ( flags.dir ) { + opts.dir = flags.dir; + } + resolveParentPaths( args, opts, onPath ); + + /** + * Callback invoked upon resolving a path. + * + * @private + * @param {(Error|null)} error - error object + * @param {string} path - resolved path + * @returns {void} + */ + function onPath( error, path ) { + if ( error ) { + return cli.error( error ); + } + console.log( path ); // eslint-disable-line no-console + } +} + +main(); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt new file mode 100644 index 00000000000..5257dab6f55 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt @@ -0,0 +1,60 @@ + +{{alias}}( paths[, options], clbk ) + Asynchronously resolves a path from a set of paths by walking parent + directories. + + If unable to resolve a path, the function returns `null` as the path result. + + Parameters + ---------- + paths: Array + Paths to resolve from. + + options: Object (optional) + Options. + + options.dir: string (optional) + Base directory from which to search. Default: current working directory. + + clbk: Function + Callback to invoke after resolving a path. + + Examples + -------- + > function onPath( error, path ) { + ... if ( error ) { + ... console.error( error.message ); + ... } else { + ... console.log( path ); + ... } + ... }; + > {{alias}}( [ 'package.json', 'package-lock.json' ], onPath ); + + +{{alias}}.sync( paths[, options] ) + Synchronously resolves a path from a set of paths by walking parent + directories. + + Parameters + ---------- + paths: Array + Paths to resolve from. + + options: Object (optional) + Options. + + options.dir: string (optional) + Base directory from which to search. Default: current working directory. + + Returns + ------- + out: string|null + Resolved path. + + Examples + -------- + > var out = {{alias}}.sync( [ 'package.json', 'package-lock.json' ] ); + + See Also + -------- + diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts new file mode 100644 index 00000000000..5f16bf9f802 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts @@ -0,0 +1,141 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/** +* Interface defining function options. +*/ +interface Options { + /** + * Base directory from which to search (default: current working directory). + */ + dir?: string; +} + +/** +* Callback invoked after resolving a path. +* +* @param err - error argument +* @param path - resolved path +*/ +type Callback = ( err: Error | null, path: string | null ) => void; + +/** +* Interface for resolving a path from a set of paths by walking parent directories. +*/ +interface ResolveParentPaths { + /** + * Asynchronously resolves a path from a set of paths by walking parent directories. + * + * ## Notes + * + * - Paths are resolved in the order they appear in the array. + * + * @param paths - path to resolve from + * @param options - function options + * @param options.dir - base directory + * @param clbk - callback to invoke after resolving a path + * @throws must provide valid options + * + * @example + * resolveParentPaths( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname }, onPath ); + * + * function onPath( error, path ) { + * if ( error ) { + * throw error; + * } + * console.log( path ); + * } + */ + ( paths: Array, options: Options, clbk: Callback ): void; + + /** + * Asynchronously resolves a path from a set of paths by walking parent directories. + * + * ## Notes + * + * - Paths are resolved in the order they appear in the array. + * + * @param paths - path to resolve from + * @param clbk - callback to invoke after resolving a path + * + * @example + * resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); + * + * function onPath( error, path ) { + * if ( error ) { + * throw error; + * } + * console.log( path ); + * } + */ + ( paths: Array, clbk: Callback ): void; + + /** + * Synchronously resolves a path from a set of paths by walking parent directories. + * + * ## Notes + * + * - If unable to resolve a path, the function returns `null` as the path result. + * - Paths are resolved in the order they appear in the array. + * + * @param paths - paths to resolve from + * @param options - function options + * @param options.dir - base directory + * @throws must provide valid options + * @returns resolved path or null + * + * @example + * var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname } ); + */ + sync( paths: Array, options?: Options ): string | null; +} + +/** +* Asynchronously resolves a path from a set of paths by walking parent directories. +* +* ## Notes +* +* - Paths are resolved in the order they appear in the array. +* +* @param paths - paths to resolve from +* @param options - function options +* @param options.dir - base directory +* @param clbk - callback to invoke after resolving a path +* @throws must provide valid options +* +* @example +* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); +* +* function onPath( error, path ) { +* if ( error ) { +* throw error; +* } +* console.log( path ); +* } +* +* @example +* var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); +*/ +declare var resolveParentPaths: ResolveParentPaths; + + +// EXPORTS // + +export = resolveParentPaths; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts new file mode 100644 index 00000000000..1848e7653e0 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts @@ -0,0 +1,119 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import resolveParentPaths = require( './index' ); + +const done = ( error: Error | null, path: string | null ): void => { + if ( error || path === null ) { + throw error; + } +}; + + +// TESTS // + +// The function does not have a return value... +{ + resolveParentPaths( [ 'package.json' ], done ); // $ExpectType void +} + +// The compiler throws an error if the function is provided a first argument which is not an array of strings... +{ + resolveParentPaths( 123, done ); // $ExpectError + resolveParentPaths( false, done ); // $ExpectError + resolveParentPaths( true, done ); // $ExpectError + resolveParentPaths( null, done ); // $ExpectError + resolveParentPaths( undefined, done ); // $ExpectError + resolveParentPaths( {}, done ); // $ExpectError + resolveParentPaths( ( x: number ): number => x, done ); // $ExpectError + resolveParentPaths( 'beep', done ); // $ExpectError + resolveParentPaths( [ 1, 2 ], done ); // $ExpectError +} + +// The compiler throws an error if the function is provided a callback argument which is not a function with the expected signature... +{ + resolveParentPaths( [ '/var/log/' ], 1 ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], false ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], true ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], null ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], undefined ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], [] ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {} ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an options argument which is not an object... +{ + resolveParentPaths( [ 'package.json' ], null, done ); // $ExpectError +} + +// The compiler throws an error if the function is provided an `dir` option which is not a string... +{ + resolveParentPaths( [ 'package.json' ], { 'dir': 123 }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'dir': true }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'dir': false }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'dir': null }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'dir': [] }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'dir': {} }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'dir': ( x: number ): number => x }, done ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + resolveParentPaths(); // $ExpectError + resolveParentPaths( [ 'C:\\foo\\bar\\baz' ] ); // $ExpectError +} + +// Attached to main export is a `sync` method which returns a string or null... +{ + resolveParentPaths.sync( [ 'package.json' ] ); // $ExpectType string | null +} + +// The compiler throws an error if the `sync` method is provided a first argument which is not an array of strings... +{ + resolveParentPaths.sync( 123 ); // $ExpectError + resolveParentPaths.sync( false ); // $ExpectError + resolveParentPaths.sync( true ); // $ExpectError + resolveParentPaths.sync( null ); // $ExpectError + resolveParentPaths.sync( undefined ); // $ExpectError + resolveParentPaths.sync( {} ); // $ExpectError + resolveParentPaths.sync( ( x: number ): number => x ); // $ExpectError + resolveParentPaths.sync( 'beep' ); // $ExpectError + resolveParentPaths.sync( [ 1, 2 ] ); // $ExpectError +} + +// The compiler throws an error if the `sync` method is provided an options argument which is not an object... +{ + resolveParentPaths.sync( [ 'package.json' ], null ); // $ExpectError +} + +// The compiler throws an error if the `sync` method is provided an `dir` option which is not a string... +{ + resolveParentPaths.sync( [ 'package.json' ], { 'dir': 123 } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'dir': true } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'dir': false } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'dir': null } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'dir': [] } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'dir': {} } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'dir': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `sync` method is provided an unsupported number of arguments... +{ + resolveParentPaths.sync(); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt new file mode 100644 index 00000000000..98e6479252d --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt @@ -0,0 +1,9 @@ + +Usage: resolve-parent-paths [options] [...] + +Options: + + -h, --help Print this message. + -V, --version Print the package version. + --dir dir Base search directory. + diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json b/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json new file mode 100644 index 00000000000..ed45901bc39 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json @@ -0,0 +1,17 @@ +{ + "string": [ + "dir" + ], + "boolean": [ + "help", + "version" + ], + "alias": { + "help": [ + "h" + ], + "version": [ + "V" + ] + } +} diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js new file mode 100644 index 00000000000..ef9a3034655 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js @@ -0,0 +1,47 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var resolveParentPaths = require( './../lib' ); + +var opts = { + 'dir': __dirname +}; + +/* Sync */ + +var out = resolveParentPaths.sync( [ 'package.json', 'non_existent_basename' ], opts ); +console.log( out ); +// => '...' + +out = resolveParentPaths.sync( [ 'non_existent_basename' ] ); +console.log( out ); +// => null + +/* Async */ + +resolveParentPaths( [ 'package.json', './../non_existent_path' ], opts, onPath ); +resolveParentPaths( [ './../non_existent_path' ], onPath ); + +function onPath( error, path ) { + if ( error ) { + throw error; + } + console.log( path ); +} diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js new file mode 100644 index 00000000000..7894f9692eb --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -0,0 +1,132 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var isFunction = require( '@stdlib/assert/is-function' ); +var cwd = require( '@stdlib/process/cwd' ); +var exists = require( '@stdlib/fs/exists' ); +var format = require( '@stdlib/string/format' ); +var validate = require( './validate.js' ); + + +// MAIN // + +/** +* Asynchronously resolves a path from a set of paths by walking parent directories. +* +* @param {Array} paths - paths to resolve from +* @param {Options} [options] - function options +* @param {string} [options.dir] - base directory +* @param {Callback} clbk - callback to invoke after resolving a path +* @throws {TypeError} first argument must be an array of strings +* @throws {TypeError} callback argument must be a function +* @throws {TypeError} options argument must be an object +* @throws {TypeError} must provide valid options +* @returns {void} +* +* @example +* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); +* +* function onPath( error, path ) { +* if ( error ) { +* throw error; +* } +* console.log( path ); +* } +*/ +function resolveParentPaths( paths, options, clbk ) { + var spath; + var child; + var opts; + var done; + var dir; + var err; + var i; + + if ( !isStringArray( paths ) ) { + throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); + } + opts = {}; + if ( arguments.length > 2 ) { + done = clbk; + err = validate( opts, options ); + if ( err ) { + throw err; + } + } else { + done = options; + } + if ( !isFunction( done ) ) { + throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', done ) ); + } + if ( opts.dir ) { + dir = resolve( cwd(), opts.dir ); + } else { + dir = cwd(); + } + for ( i = 0; i < paths.length - 1; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists.sync( spath ) ) { + return done( null, spath ); + } + } + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); + + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool ) { + return done( null, spath ); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, null ); + } + // Resolve the next search path: + for ( j = 0; j < paths.length - 1; j++ ) { + spath = resolve( dir, paths[ j ] ); + if ( exists.sync( spath ) ) { + return done( null, spath ); + } + } + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); + } +} + + +// EXPORTS // + +module.exports = resolveParentPaths; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js new file mode 100644 index 00000000000..49976b7de0c --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js @@ -0,0 +1,58 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Resolve a path from a set of paths by walking parent directories. +* +* @module @stdlib/fs/resolve-parent-paths +* +* @example +* var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); +* +* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); +* +* function onPath( error, path ) { +* if ( error ) { +* throw error; +* } +* console.log( path ); +* } +* +* @example +* var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); +* +* var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); +*/ + +// MODULES // + +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var resolveParentPaths = require( './async.js' ); +var sync = require( './sync.js' ); + + +// MAIN // + +setReadOnly( resolveParentPaths, 'sync', sync ); + + +// EXPORTS // + +module.exports = resolveParentPaths; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js new file mode 100644 index 00000000000..781b73febcc --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -0,0 +1,86 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var cwd = require( '@stdlib/process/cwd' ); +var exists = require( '@stdlib/fs/exists' ).sync; +var format = require( '@stdlib/string/format' ); +var validate = require( './validate.js' ); + + +// MAIN // + +/** +* Synchronously resolves a path from a set of paths by walking parent directories. +* +* @param {Array} paths - paths to resolve from +* @param {Options} [options] - function options +* @param {string} [options.dir] - base directory +* @throws {TypeError} first argument must be an array of strings +* @throws {TypeError} options argument must be an object +* @throws {TypeError} must provide valid options +* @returns {(string|null)} resolved path or null +* +* @example +* var path = resolveParentPaths( [ 'package.json', 'package-lock.json' ] ); +*/ +function resolveParentPaths( paths, options ) { + var spath; + var child; + var opts; + var dir; + var err; + var i; + if ( !isStringArray( paths ) ) { + throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); + } + opts = {}; + if ( arguments.length > 1 ) { + err = validate( opts, options ); + if ( err ) { + throw err; + } + } + if ( opts.dir ) { + dir = resolve( cwd(), opts.dir ); + } else { + dir = cwd(); + } + // Start at a base directory and continue moving up through each parent directory until able to resolve a search path or until reaching the root directory... + while ( child !== dir ) { + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists( spath ) ) { + return spath; + } + } + child = dir; + dir = resolve( dir, '..' ); + } + return null; +} + + +// EXPORTS // + +module.exports = resolveParentPaths; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js new file mode 100644 index 00000000000..47391c96775 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js @@ -0,0 +1,67 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var isObject = require( '@stdlib/assert/is-plain-object' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var format = require( '@stdlib/string/format' ); + + +// MAIN // + +/** +* Validates function options. +* +* @private +* @param {Object} opts - destination object +* @param {Options} options - function options +* @param {string} [options.dir] - base directory +* @returns {(Error|null)} error object or null +* +* @example +* var opts = {}; +* var options = { +* 'dir': '/foo/bar/baz' +* }; +* +* var err = validate( opts, options ); +* if ( err ) { +* throw err; +* } +*/ +function validate( opts, options ) { + if ( !isObject( options ) ) { + return new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + if ( hasOwnProp( options, 'dir' ) ) { + opts.dir = options.dir; + if ( !isString( opts.dir ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'dir', opts.dir ) ); + } + } + return null; +} + + +// EXPORTS // + +module.exports = validate; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json b/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json new file mode 100644 index 00000000000..203a15bd84b --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json @@ -0,0 +1,78 @@ +{ + "name": "@stdlib/fs/resolve-parent-paths", + "version": "0.0.0", + "description": "Resolve a path from a set of paths by walking parent directories.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "bin": { + "resolve-parent-paths": "./bin/cli" + }, + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdfs", + "fs", + "resolve", + "parent", + "path", + "async", + "sync", + "file", + "directory", + "dir", + "find", + "up", + "findup", + "find-up", + "upsearch", + "search", + "lookup", + "look-up", + "locate", + "walk", + "filesystem" + ] +} diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/fixtures/read_error.js.txt b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/fixtures/read_error.js.txt new file mode 100644 index 00000000000..683cbbc2f4c --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/fixtures/read_error.js.txt @@ -0,0 +1,38 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +var proc = require( 'process' ); +var resolve = require( 'path' ).resolve; +var proxyquire = require( 'proxyquire' ); + +var fpath = resolve( __dirname, '..', 'bin', 'cli' ); + +proc.stdin.isTTY = false; +proc.argv[ 2 ] = 'package.json'; + +proxyquire( fpath, { + './../lib': resolveParentPaths +}); + +function resolveParentPaths() { + var clbk = arguments[ arguments.length-1 ]; + setTimeout( onTimeout, 0 ); + function onTimeout() { + clbk( new Error( 'beep' ) ); + } +} diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js new file mode 100644 index 00000000000..dfb94acb4fc --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -0,0 +1,283 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var basename = require( 'path' ).basename; +var tape = require( 'tape' ); +var IS_BROWSER = require( '@stdlib/assert/is-browser' ); +var noop = require( '@stdlib/utils/noop' ); +var cwd = require( '@stdlib/process/cwd' ); +var resolveParentPaths = require( './../lib/async.js' ); + + +// VARIABLES // + +// Don't run tests in the browser...for now... +var opts = { + 'skip': IS_BROWSER // FIXME +}; + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof resolveParentPaths, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if provided a `paths` argument which is not an array of strings', function test( t ) { + var values; + var i; + + values = [ + 5, + NaN, + null, + void 0, + true, + {}, + function noop() {}, + 'beep', + [ 1, 2 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( value, noop ); + }; + } +}); + +tape( 'the function throws an error if provided a `paths` argument which is not an array of strings (options)', function test( t ) { + var values; + var i; + + values = [ + 5, + NaN, + null, + void 0, + true, + {}, + function noop() {}, + 'beep', + [ 1, 2 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( value, {}, noop ); + }; + } +}); + +tape( 'the function throws an error if provided a callback argument which is not a function', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + null, + void 0, + true, + [], + {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( [ 'beep' ], value ); + }; + } +}); + +tape( 'the function throws an error if provided a callback argument which is not a function (options)', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + null, + void 0, + true, + [], + {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( [ 'beep' ], {}, value ); + }; + } +}); + +tape( 'the function throws an error if provided an options argument which is not an object', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + null, + void 0, + true, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( [ 'beep' ], value, noop ); + }; + } +}); + +tape( 'the function throws an error if provided an invalid option', function test( t ) { + var values; + var i; + + values = [ + 5, + NaN, + null, + void 0, + true, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( [ 'beep' ], { + 'dir': value + }, noop ); + }; + } +}); + +tape( 'the function resolves a path from a set of paths by walking parent directories', opts, function test( t ) { + var expected; + var base; + var dir; + + dir = cwd(); + base = basename( dir ); + + expected = dir; + resolveParentPaths( [ base ], onPath ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!', base ], onPath ); + resolveParentPaths( [ base, 'beep-boop!!!hello world!?!' ], onPath ); + t.end(); + + function onPath( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual, expected, 'returns path' ); + } +}); + +tape( 'the function resolves a path from a set of paths by walking parent directories (dir option)', opts, function test( t ) { + var expected; + var opts; + + expected = resolve( __dirname, '../package.json' ); + + opts = { + 'dir': __dirname + }; + resolveParentPaths( [ 'package.json' ], opts, onPath ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!', 'package.json' ], opts, onPath ); + resolveParentPaths( [ 'package.json', 'beep-boop!!!hello world!?!' ], opts, onPath ); + t.end(); + + function onPath( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual, expected, 'returns path' ); + } +}); + +tape( 'the function returns `null` if unable to resolve a parent path', opts, function test( t ) { + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], onPath ); + t.end(); + + function onPath( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual, null, 'returns null' ); + } +}); + +tape( 'the function returns `null` if unable to resolve a parent path (options)', opts, function test( t ) { + var opts = { + 'dir': __dirname + }; + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPath ); + t.end(); + + function onPath( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual, null, 'returns null' ); + } +}); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js new file mode 100644 index 00000000000..74c21df75e2 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js @@ -0,0 +1,201 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var exec = require( 'child_process' ).exec; +var tape = require( 'tape' ); +var replace = require( '@stdlib/string/replace' ); +var isAbsolutePath = require( '@stdlib/assert/is-absolute-path' ); +var IS_BROWSER = require( '@stdlib/assert/is-browser' ); +var IS_WINDOWS = require( '@stdlib/assert/is-windows' ); +var EXEC_PATH = require( '@stdlib/process/exec-path' ); +var readFileSync = require( '@stdlib/fs/read-file' ).sync; + + +// VARIABLES // + +var fpath = resolve( __dirname, '..', 'bin', 'cli' ); +var opts = { + 'skip': IS_BROWSER || IS_WINDOWS +}; + + +// FIXTURES // + +var PKG_VERSION = require( './../package.json' ).version; + + +// TESTS // + +tape( 'command-line interface', function test( t ) { + t.ok( true, __filename ); + t.end(); +}); + +tape( 'when invoked with a `--help` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) { + var expected; + var cmd; + + expected = readFileSync( resolve( __dirname, '..', 'docs', 'usage.txt' ), { + 'encoding': 'utf8' + }); + cmd = [ + EXEC_PATH, + fpath, + '--help' + ]; + + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + if ( error ) { + t.fail( error.message ); + } else { + t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' ); + t.strictEqual( stderr.toString(), expected+'\n', 'expected value' ); + } + t.end(); + } +}); + +tape( 'when invoked with a `-h` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) { + var expected; + var cmd; + + expected = readFileSync( resolve( __dirname, '..', 'docs', 'usage.txt' ), { + 'encoding': 'utf8' + }); + cmd = [ + EXEC_PATH, + fpath, + '-h' + ]; + + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + if ( error ) { + t.fail( error.message ); + } else { + t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' ); + t.strictEqual( stderr.toString(), expected+'\n', 'expected value' ); + } + t.end(); + } +}); + +tape( 'when invoked with a `--version` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) { + var cmd = [ + EXEC_PATH, + fpath, + '--version' + ]; + + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + if ( error ) { + t.fail( error.message ); + } else { + t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' ); + t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' ); + } + t.end(); + } +}); + +tape( 'when invoked with a `-V` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) { + var cmd = [ + EXEC_PATH, + fpath, + '-V' + ]; + + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + if ( error ) { + t.fail( error.message ); + } else { + t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' ); + t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' ); + } + t.end(); + } +}); + +tape( 'the command-line interface resolves a path from a set of paths by walking parent directories', opts, function test( t ) { + var cmd = [ + EXEC_PATH, + fpath, + 'package.json', + 'beep-boop!!!hello world!?!' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var str; + if ( error ) { + t.fail( error.message ); + } else { + str = stdout.toString(); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); + } + t.end(); + } +}); + +tape( 'if an error is encountered when reading a file, the command-line interface prints an error and sets a non-zero exit code', opts, function test( t ) { + var script; + var opts; + var cmd; + + script = readFileSync( resolve( __dirname, 'fixtures', 'read_error.js.txt' ), { + 'encoding': 'utf8' + }); + + // Replace single quotes with double quotes: + script = replace( script, '\'', '"' ); + + cmd = [ + EXEC_PATH, + '-e', + '\''+script+'\'' + ]; + + opts = { + 'cwd': __dirname + }; + + exec( cmd.join( ' ' ), opts, done ); + + function done( error, stdout, stderr ) { + if ( error ) { + t.pass( error.message ); + t.strictEqual( error.code, 1, 'expected exit code' ); + } + t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' ); + t.strictEqual( stderr.toString(), 'Error: beep\n', 'expected value' ); + t.end(); + } +}); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js new file mode 100644 index 00000000000..7cc991d88cc --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js @@ -0,0 +1,38 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var resolveParentPaths = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof resolveParentPaths, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'attached to the main export is a function to resolve a parent paths synchronously', function test( t ) { + t.equal( typeof resolveParentPaths.sync, 'function', 'has `sync` method' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js new file mode 100644 index 00000000000..c65f45f9154 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -0,0 +1,227 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var resolve = require( 'path' ).resolve; +var basename = require( 'path' ).basename; +var tape = require( 'tape' ); +var IS_BROWSER = require( '@stdlib/assert/is-browser' ); +var cwd = require( '@stdlib/process/cwd' ); +var resolveParentPaths = require( './../lib/sync.js' ); + + +// VARIABLES // + +// Don't run tests in the browser...for now... +var opts = { + 'skip': IS_BROWSER // FIXME +}; + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof resolveParentPaths, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if provided a `paths` argument which is not an array of strings', function test( t ) { + var values; + var i; + + values = [ + 5, + NaN, + null, + void 0, + true, + {}, + function noop() {}, + 'beep', + [ 1, 2 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( value ); + }; + } +}); + +tape( 'the function throws an error if provided a `paths` argument which is not an array of strings (options)', function test( t ) { + var values; + var i; + + values = [ + 5, + NaN, + null, + void 0, + true, + {}, + function noop() {}, + 'beep', + [ 1, 2 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( value, {} ); + }; + } +}); + +tape( 'the function throws an error if provided an options argument which is not an object', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + null, + void 0, + true, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( [ 'beep' ], value ); + }; + } +}); + +tape( 'the function throws an error if provided an invalid option', function test( t ) { + var values; + var i; + + values = [ + 5, + NaN, + null, + void 0, + true, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + resolveParentPaths( [ 'beep' ], { + 'dir': value + }); + }; + } +}); + +tape( 'the function resolves a path from a set of paths by walking parent directories', opts, function test( t ) { + var expected; + var actual; + var base; + var dir; + + dir = cwd(); + base = basename( dir ); + + expected = dir; + actual = resolveParentPaths( [ base ] ); + t.strictEqual( actual, expected, 'returns path' ); + + expected = dir; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!', base ] ); + t.strictEqual( actual, expected, 'returns path' ); + + expected = dir; + actual = resolveParentPaths( [ base, 'beep-boop!!!hello world!?!' ] ); + t.strictEqual( actual, expected, 'returns path' ); + + t.end(); +}); + +tape( 'the function resolves a path from a set of paths by walking parent directories (dir option)', opts, function test( t ) { + var expected; + var actual; + var opts; + var dir; + + opts = { + 'dir': __dirname + }; + dir = resolve( __dirname, '../package.json' ); + + expected = dir; + actual = resolveParentPaths( [ 'package.json' ], opts ); + t.strictEqual( actual, expected, 'returns path' ); + + expected = dir; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!', 'package.json' ] ); + t.strictEqual( actual, expected, 'returns path' ); + + expected = dir; + actual = resolveParentPaths( [ 'package.json', 'beep-boop!!!hello world!?!' ] ); + t.strictEqual( actual, expected, 'returns path' ); + + t.end(); +}); + +tape( 'the function returns `null` if unable to resolve a parent path', opts, function test( t ) { + var actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ] ); + + t.strictEqual( actual, null, 'returns null' ); + t.end(); +}); + +tape( 'the function returns `null` if unable to resolve a parent path (options)', opts, function test( t ) { + var actual; + var opts; + + opts = { + 'dir': __dirname + }; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + + t.strictEqual( actual, null, 'returns null' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js new file mode 100644 index 00000000000..50eecedc507 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js @@ -0,0 +1,121 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var validate = require( './../lib/validate.js' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof validate, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'if provided an `options` argument which is not an `object`, the function returns a type error', function test( t ) { + var values; + var opts; + var err; + var i; + + values = [ + '5', + 5, + NaN, + true, + null, + void 0, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + opts = {}; + err = validate( opts, values[i] ); + t.equal( err instanceof TypeError, true, 'returns a type error when provided '+values[i] ); + } + t.end(); +}); + +tape( 'if provided a `dir` option which is not a `string`, the function returns a type error', function test( t ) { + var values; + var opts; + var err; + var i; + + values = [ + 5, + NaN, + true, + null, + void 0, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + opts = {}; + err = validate( opts, { + 'dir': values[i] + }); + t.equal( err instanceof TypeError, true, 'returns a type error when provided '+values[i] ); + } + t.end(); +}); + +tape( 'the function returns `null` if all options are valid', function test( t ) { + var opts; + var obj; + var err; + + opts = { + 'dir': './beep/boop' + }; + obj = {}; + err = validate( obj, opts ); + + t.equal( err, null, 'returns null' ); + t.equal( obj.dir, opts.dir, 'sets dir option' ); + + t.end(); +}); + +tape( 'the function ignores unsupported/unrecognized options', function test( t ) { + var opts; + var obj; + var err; + + opts = { + 'beep': 'boop', + 'a': 'b', + 'c': [ 1, 2, 3 ] + }; + obj = {}; + err = validate( obj, opts ); + + t.equal( err, null, 'returns null' ); + t.deepEqual( obj, {}, 'does not set any options' ); + + t.end(); +}); From c44d1bc0447a13e1cb3f23eb6ddddc5d11d8f1f6 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Thu, 11 Jul 2024 23:37:36 +0000 Subject: [PATCH 02/33] test: fix failing test Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/test/test.sync.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js index c65f45f9154..95e524710ea 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -196,11 +196,11 @@ tape( 'the function resolves a path from a set of paths by walking parent direct t.strictEqual( actual, expected, 'returns path' ); expected = dir; - actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!', 'package.json' ] ); + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!', 'package.json' ], opts ); t.strictEqual( actual, expected, 'returns path' ); expected = dir; - actual = resolveParentPaths( [ 'package.json', 'beep-boop!!!hello world!?!' ] ); + actual = resolveParentPaths( [ 'package.json', 'beep-boop!!!hello world!?!' ], opts ); t.strictEqual( actual, expected, 'returns path' ); t.end(); From 72038be3bc1bedf3df35ab41cbeaa2f1ebc3a4b0 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Sun, 14 Jul 2024 21:52:36 +0000 Subject: [PATCH 03/33] feat: add multiple modes of operation Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/README.md | 58 +-- .../benchmark/benchmark.js | 259 +++++++++++++- .../@stdlib/fs/resolve-parent-paths/bin/cli | 11 +- .../fs/resolve-parent-paths/docs/repl.txt | 34 +- .../docs/types/index.d.ts | 82 +++-- .../resolve-parent-paths/docs/types/test.ts | 26 +- .../fs/resolve-parent-paths/docs/usage.txt | 1 + .../fs/resolve-parent-paths/etc/cli_opts.json | 3 +- .../fs/resolve-parent-paths/examples/index.js | 21 +- .../fs/resolve-parent-paths/lib/async.js | 332 +++++++++++++++--- .../fs/resolve-parent-paths/lib/index.js | 10 +- .../fs/resolve-parent-paths/lib/sync.js | 175 ++++++++- .../fs/resolve-parent-paths/lib/validate.js | 23 +- .../fs/resolve-parent-paths/package.json | 2 +- .../resolve-parent-paths/test/test.async.js | 221 +++++++++++- .../fs/resolve-parent-paths/test/test.cli.js | 122 ++++++- .../fs/resolve-parent-paths/test/test.js | 2 +- .../fs/resolve-parent-paths/test/test.sync.js | 185 ++++++++-- .../test/test.validate.js | 32 +- 19 files changed, 1385 insertions(+), 214 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md index 3648e46f05f..474e83e6d68 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md @@ -20,7 +20,7 @@ limitations under the License. # Resolve Parent Paths -> Resolve a path from a set of paths by walking parent directories. +> Resolve paths from a set of paths by walking parent directories.
@@ -34,16 +34,16 @@ var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); #### resolveParentPaths( paths\[, options], clbk ) -Asynchronously resolves a path from a set of paths by walking parent directories. +Asynchronously resolves paths from a set of paths by walking parent directories. ```javascript -resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); +resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); -function onPath( error, path ) { +function onPaths( error, paths ) { if ( error ) { throw error; } - console.log( path ); + console.log( paths ); // => '...' } ``` @@ -52,30 +52,37 @@ The function accepts the following `options`: - **dir**: base directory from which to begin walking. May be either an absolute path or a path relative to the current working directory. -By default, the function begins walking from the current working directory. To specify an alternative directory, set the `dir` option. +- **mode**: mode of operation. The following modes are supported: + - `first`: first resolved path is returned. + - `some`: first set of paths resolved at a directory level are returned. + - `all`: all paths resolved at a directory level are returned. + - `each`: each path resolved at any directory level is returned. + +By default, the function begins walking from the current working directory in `all` mode. To specify an alternative directory, set the `dir` and/or `mode` option. ```javascript var opts = { - 'dir': __dirname + 'dir': __dirname, + 'mode': 'first' }; -resolveParentPaths( [ 'package.json' ], opts, onPath ); +resolveParentPaths( [ 'package.json' ], opts, onPaths ); -function onPath( error, path ) { +function onPaths( error, paths ) { if ( error ) { throw error; } - console.log( path ); + console.log( paths ); // => '...' } ``` #### resolveParentPaths.sync( paths\[, options] ) -Synchronously resolves a path from a set of paths by walking parent directories. +Synchronously resolves paths from a set of paths by walking parent directories. ```javascript -var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); -// returns '...' +var paths = resolveParentPaths.sync( [ 'package.json', 'README.md' ] ); +// returns [ '...', '...' ] ``` The function accepts the same `options` as [`resolveParentPaths()`](#resolve-parent-paths). @@ -88,9 +95,7 @@ The function accepts the same `options` as [`resolveParentPaths()`](#resolve-par ## Notes -- If unable to resolve a path, both functions return `null`. -- Paths are resolved in the order they appear in the array. -- This implementation is **not** similar in functionality to core [`path.resolve`][node-core-path-resolve]. The latter performs string manipulation to generate a full path. This implementation walks parent directories to perform a **search**, thereby touching the file system. Accordingly, this implementation resolves a _real_ absolute file path and is intended for use when a target's location in a parent directory is unknown relative to a child directory; e.g., when wanting to find a package root from deep within a package directory. +- This implementation is **not** similar in functionality to core [`path.resolve`][node-core-path-resolve]. The latter performs string manipulation to generate a full path. This implementation walks parent directories to perform a **search**, thereby touching the file system. Accordingly, this implementation resolves _real_ absolute file paths and is intended for use when a target's location in a parent directory is unknown relative to a child directory; e.g., when wanting to find a package root from deep within a package directory.
@@ -111,22 +116,26 @@ var opts = { /* Sync */ -var out = resolveParentPaths.sync( [ 'package.json', 'non_existent_basename' ], opts ); -// returns '...' +var out = resolveParentPaths.sync( [ 'package.json', 'README.md' ], opts ); +// returns [ '...', '...' ] + +out = resolveParentPaths.sync( [ 'non_existent_basename' ], opts ); +// returns [] -out = resolveParentPaths.sync( [ 'non_existent_basename' ] ); -// returns null +opts.mode = 'first'; +out = resolveParentPaths.sync( [ 'non_existent_basename', 'package.json' ], opts ); +// returns [ '...' ] /* Async */ -resolveParentPaths( [ 'package.json', './../non_existent_path' ], opts, onPath ); -resolveParentPaths( [ './../non_existent_path' ], onPath ); +resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); +resolveParentPaths( [ './../non_existent_path' ], onPaths ); -function onPath( error, path ) { +function onPaths( error, paths ) { if ( error ) { throw error; } - console.log( path ); + console.log( paths ); } ``` @@ -152,6 +161,7 @@ Options: -h, --help Print this message. -V, --version Print the package version. --dir dir Base search directory. + --mode mode Mode of operation. ``` diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js index a4571f83d8c..d81987beadb 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js @@ -20,28 +20,68 @@ // MODULES // +var basename = require( 'path' ).basename; var bench = require( '@stdlib/bench' ); var pkg = require( './../package.json' ).name; var resolveParentPaths = require( './../lib' ); -// VARIABLES // +// MAIN // -var PATHS = [ - [ 'package.json' ], - [ 'beep-boop!!!hello world!?!', 'package.json' ], - [ 'package.json', 'beep-boop!!!hello world!?!' ] -]; +bench( pkg+':async,first', function benchmark( b ) { + var PATHS; + var opts; + var i; + PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ 'package.json', 'README.md' ] + ]; + opts = { + 'dir': __dirname, + 'mode': 'first' + }; -// MAIN // + i = 0; + b.tic(); + + return next(); + + function next() { + i += 1; + if ( i <= b.iterations ) { + return resolveParentPaths( PATHS[ i % 3 ], opts, done ); + } + b.toc(); + b.pass( 'benchmark finished' ); + b.end(); + } + + function done( error, paths ) { + if ( error ) { + b.fail( error.message ); + } + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + next(); + } +}); -bench( pkg, function benchmark( b ) { +bench( pkg+':async,some', function benchmark( b ) { + var PATHS; var opts; var i; + PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ 'package.json', 'README.md' ] + ]; opts = { - 'dir': __dirname + 'dir': __dirname, + 'mode': 'some' }; i = 0; @@ -59,35 +99,220 @@ bench( pkg, function benchmark( b ) { b.end(); } - function done( error, path ) { + function done( error, paths ) { + if ( error ) { + b.fail( error.message ); + } + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + next(); + } +}); + +bench( pkg+':async,all', function benchmark( b ) { + var PATHS; + var opts; + var i; + + PATHS = [ + [ 'package.json' ], + [ 'package.json', 'README.md' ] + ]; + opts = { + 'dir': __dirname, + 'mode': 'all' + }; + + i = 0; + b.tic(); + + return next(); + + function next() { + i += 1; + if ( i <= b.iterations ) { + return resolveParentPaths( PATHS[ i % 2 ], opts, done ); + } + b.toc(); + b.pass( 'benchmark finished' ); + b.end(); + } + + function done( error, paths ) { + if ( error ) { + b.fail( error.message ); + } + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + next(); + } +}); + +bench( pkg+':async,each', function benchmark( b ) { + var PATHS; + var opts; + var i; + + PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ basename( __dirname ), 'README.md' ], + [ 'README.md', 'package.json' ] + ]; + opts = { + 'dir': __dirname, + 'mode': 'each' + }; + + i = 0; + b.tic(); + + return next(); + + function next() { + i += 1; + if ( i <= b.iterations ) { + return resolveParentPaths( PATHS[ i % 4 ], opts, done ); + } + b.toc(); + b.pass( 'benchmark finished' ); + b.end(); + } + + function done( error, paths ) { if ( error ) { b.fail( error.message ); } - if ( path === null ) { + if ( paths.length === 0 ) { b.fail( 'should return a path' ); } next(); } }); -bench( pkg+':sync', function benchmark( b ) { +bench( pkg+':sync,first', function benchmark( b ) { + var PATHS; + var paths; + var opts; + var i; + + PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ 'package.json', 'README.md' ] + ]; + opts = { + 'dir': __dirname, + 'mode': 'first' + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + paths = resolveParentPaths.sync( PATHS[ i % 3 ], opts ); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + } + b.toc(); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } else { + b.pass( 'benchmark finished' ); + } + b.end(); +}); + +bench( pkg+':sync,some', function benchmark( b ) { + var PATHS; + var paths; + var opts; + var i; + + PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ 'package.json', 'README.md' ] + ]; + opts = { + 'dir': __dirname, + 'mode': 'some' + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + paths = resolveParentPaths.sync( PATHS[ i % 3 ], opts ); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + } + b.toc(); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } else { + b.pass( 'benchmark finished' ); + } + b.end(); +}); + +bench( pkg+':sync,all', function benchmark( b ) { + var PATHS; + var paths; + var opts; + var i; + + PATHS = [ + [ 'package.json' ], + [ 'package.json', 'README.md' ] + ]; + opts = { + 'dir': __dirname, + 'mode': 'all' + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + paths = resolveParentPaths.sync( PATHS[ i % 2 ], opts ); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + } + b.toc(); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } else { + b.pass( 'benchmark finished' ); + } + b.end(); +}); + +bench( pkg+':sync,each', function benchmark( b ) { + var PATHS; + var paths; var opts; - var path; var i; + PATHS = [ + [ 'package.json' ], + [ 'beep-boop!!!hello world!?!', 'package.json' ], + [ basename( __dirname ), 'README.md' ], + [ 'README.md', 'package.json' ] + ]; opts = { - 'dir': __dirname + 'dir': __dirname, + 'mode': 'each' }; b.tic(); for ( i = 0; i < b.iterations; i++ ) { - path = resolveParentPaths.sync( PATHS[ i % 3 ], opts ); - if ( path === null ) { + paths = resolveParentPaths.sync( PATHS[ i % 4 ], opts ); + if ( paths.length === 0 ) { b.fail( 'should return a path' ); } } b.toc(); - if ( path === null ) { + if ( paths.length === 0 ) { b.fail( 'should return a path' ); } else { b.pass( 'benchmark finished' ); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli index f86c323ad91..8de501a7a93 100755 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli @@ -64,21 +64,24 @@ function main() { if ( flags.dir ) { opts.dir = flags.dir; } - resolveParentPaths( args, opts, onPath ); + if ( flags.mode ) { + opts.mode = flags.mode; + } + resolveParentPaths( args, opts, onPaths ); /** * Callback invoked upon resolving a path. * * @private * @param {(Error|null)} error - error object - * @param {string} path - resolved path + * @param {string} paths - resolved paths * @returns {void} */ - function onPath( error, path ) { + function onPaths( error, paths ) { if ( error ) { return cli.error( error ); } - console.log( path ); // eslint-disable-line no-console + console.log( paths ); // eslint-disable-line no-console } } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt index 5257dab6f55..7a200fdc8ef 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt @@ -1,9 +1,14 @@ {{alias}}( paths[, options], clbk ) - Asynchronously resolves a path from a set of paths by walking parent + Asynchronously resolves paths from a set of paths by walking parent directories. - If unable to resolve a path, the function returns `null` as the path result. + The following modes are supported: + + - first: first resolved path is returned. + - some: first set of paths resolved at a directory level are returned. + - all: all paths resolved at a directory level are returned. + - each: each path resolved at any directory level is returned. Parameters ---------- @@ -16,25 +21,35 @@ options.dir: string (optional) Base directory from which to search. Default: current working directory. + options.mode: string (optional) + Mode of operation. Default: `all`. + clbk: Function Callback to invoke after resolving a path. Examples -------- - > function onPath( error, path ) { + > function onPaths( error, paths ) { ... if ( error ) { ... console.error( error.message ); ... } else { - ... console.log( path ); + ... console.log( paths ); ... } ... }; - > {{alias}}( [ 'package.json', 'package-lock.json' ], onPath ); + > {{alias}}( [ 'package.json', 'package-lock.json' ], onPaths ); {{alias}}.sync( paths[, options] ) - Synchronously resolves a path from a set of paths by walking parent + Synchronously resolves paths from a set of paths by walking parent directories. + The following modes are supported: + + - first: first resolved path is returned + - some: first set of paths resolved at a directory level are returned + - all: all paths resolved at a directory level are returned + - each: each path resolved at any directory level is returned + Parameters ---------- paths: Array @@ -46,10 +61,13 @@ options.dir: string (optional) Base directory from which to search. Default: current working directory. + options.mode: string (optional) + Mode of operation. Default: `all`. + Returns ------- - out: string|null - Resolved path. + out: Array + Resolved paths. Examples -------- diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts index 5f16bf9f802..5826de95b6c 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts @@ -26,112 +26,124 @@ interface Options { * Base directory from which to search (default: current working directory). */ dir?: string; + + /** + * Mode of operation (default: `all`). + */ + mode?: string; } /** -* Callback invoked after resolving a path. +* Callback invoked after resolving paths. * * @param err - error argument -* @param path - resolved path +* @param paths - resolved paths */ -type Callback = ( err: Error | null, path: string | null ) => void; +type Callback = ( err: Error | null, paths: Array ) => void; /** -* Interface for resolving a path from a set of paths by walking parent directories. +* Interface for resolving paths from a set of paths by walking parent directories. */ interface ResolveParentPaths { /** - * Asynchronously resolves a path from a set of paths by walking parent directories. + * Asynchronously resolves paths from a set of paths by walking parent directories. * - * ## Notes + * The following modes are supported: * - * - Paths are resolved in the order they appear in the array. + * - `first`: first resolved path is returned. + * - `some`: first set of paths resolved at a directory level are returned. + * - `all`: all paths resolved at a directory level are returned. (default) + * - `each`: each path resolved at any directory level is returned. * * @param paths - path to resolve from * @param options - function options * @param options.dir - base directory - * @param clbk - callback to invoke after resolving a path + * @param options.mode - mode of operation + * @param clbk - callback to invoke after resolving paths * @throws must provide valid options * * @example - * resolveParentPaths( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname }, onPath ); + * resolveParentPaths( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname, 'mode': 'some' }, onPaths ); * - * function onPath( error, path ) { + * function onPaths( error, paths ) { * if ( error ) { * throw error; * } - * console.log( path ); + * console.log( paths ); * } */ ( paths: Array, options: Options, clbk: Callback ): void; /** - * Asynchronously resolves a path from a set of paths by walking parent directories. - * - * ## Notes - * - * - Paths are resolved in the order they appear in the array. + * Asynchronously resolves paths from a set of paths by walking parent directories. * * @param paths - path to resolve from - * @param clbk - callback to invoke after resolving a path + * @param clbk - callback to invoke after resolving paths * * @example - * resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); + * resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); * - * function onPath( error, path ) { + * function onPaths( error, paths ) { * if ( error ) { * throw error; * } - * console.log( path ); + * console.log( paths ); * } */ ( paths: Array, clbk: Callback ): void; /** - * Synchronously resolves a path from a set of paths by walking parent directories. + * Synchronously resolves paths from a set of paths by walking parent directories. * - * ## Notes + * The following modes are supported: * - * - If unable to resolve a path, the function returns `null` as the path result. - * - Paths are resolved in the order they appear in the array. + * - `first`: first resolved path is returned. + * - `some`: first set of paths resolved at a directory level are returned. + * - `all`: all paths resolved at a directory level are returned (default). + * - `each`: each path resolved at any directory level is returned. * * @param paths - paths to resolve from * @param options - function options * @param options.dir - base directory + * @param options.mode - mode of operation * @throws must provide valid options - * @returns resolved path or null + * @returns resolved paths * * @example - * var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname } ); + * var paths = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname, 'mode': 'some' } ); */ - sync( paths: Array, options?: Options ): string | null; + sync( paths: Array, options?: Options ): Array; } /** -* Asynchronously resolves a path from a set of paths by walking parent directories. +* Asynchronously resolves paths from a set of paths by walking parent directories. * -* ## Notes +* The following modes are supported: * -* - Paths are resolved in the order they appear in the array. +* - `first`: first resolved path is returned. +* - `some`: first set of paths resolved at a directory level are returned. +* - `all`: all paths resolved at a directory level are returned. (default) +* - `each`: each path resolved at any directory level is returned. * * @param paths - paths to resolve from * @param options - function options * @param options.dir - base directory -* @param clbk - callback to invoke after resolving a path +* @param options.mode - mode of operation +* @param clbk - callback to invoke after resolving paths * @throws must provide valid options * * @example -* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); +* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); * -* function onPath( error, path ) { +* function onPaths( error, paths ) { * if ( error ) { * throw error; * } -* console.log( path ); +* console.log( paths ); * } * * @example -* var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); +* var paths = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); */ declare var resolveParentPaths: ResolveParentPaths; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts index 1848e7653e0..0a607d96221 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts @@ -73,15 +73,26 @@ const done = ( error: Error | null, path: string | null ): void => { resolveParentPaths( [ 'package.json' ], { 'dir': ( x: number ): number => x }, done ); // $ExpectError } +// The compiler throws an error if the function is provided an `mode` option which is not a string... +{ + resolveParentPaths( [ 'package.json' ], { 'mode': 123 }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'mode': true }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'mode': false }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'mode': null }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'mode': [] }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'mode': {} }, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], { 'mode': ( x: number ): number => x }, done ); // $ExpectError +} + // The compiler throws an error if the function is provided an unsupported number of arguments... { resolveParentPaths(); // $ExpectError resolveParentPaths( [ 'C:\\foo\\bar\\baz' ] ); // $ExpectError } -// Attached to main export is a `sync` method which returns a string or null... +// Attached to main export is a `sync` method which returns an array... { - resolveParentPaths.sync( [ 'package.json' ] ); // $ExpectType string | null + resolveParentPaths.sync( [ 'package.json' ] ); // $ExpectType (string | null)[] } // The compiler throws an error if the `sync` method is provided a first argument which is not an array of strings... @@ -113,6 +124,17 @@ const done = ( error: Error | null, path: string | null ): void => { resolveParentPaths.sync( [ 'package.json' ], { 'dir': ( x: number ): number => x } ); // $ExpectError } +// The compiler throws an error if the `sync` method is provided an `mode` option which is not a string... +{ + resolveParentPaths.sync( [ 'package.json' ], { 'mode': 123 } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'mode': true } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'mode': false } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'mode': null } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'mode': [] } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'mode': {} } ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], { 'mode': ( x: number ): number => x } ); // $ExpectError +} + // The compiler throws an error if the `sync` method is provided an unsupported number of arguments... { resolveParentPaths.sync(); // $ExpectError diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt index 98e6479252d..b0b99674f53 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt @@ -6,4 +6,5 @@ Options: -h, --help Print this message. -V, --version Print the package version. --dir dir Base search directory. + --mode mode Mode of operation. diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json b/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json index ed45901bc39..68f423bede7 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json @@ -1,6 +1,7 @@ { "string": [ - "dir" + "dir", + "mode" ], "boolean": [ "help", diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js index ef9a3034655..c95bbb380bc 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js @@ -26,22 +26,27 @@ var opts = { /* Sync */ -var out = resolveParentPaths.sync( [ 'package.json', 'non_existent_basename' ], opts ); +var out = resolveParentPaths.sync( [ 'package.json', 'README.md' ], opts ); console.log( out ); -// => '...' +// => [ '...', '...' ] -out = resolveParentPaths.sync( [ 'non_existent_basename' ] ); +out = resolveParentPaths.sync( [ 'non_existent_basename', 'package.json' ], opts ); console.log( out ); -// => null +// => [] + +opts.mode = 'first'; +out = resolveParentPaths.sync( [ 'non_existent_basename', 'package.json' ], opts ); +console.log( out ); +// => [ '...' ] /* Async */ -resolveParentPaths( [ 'package.json', './../non_existent_path' ], opts, onPath ); -resolveParentPaths( [ './../non_existent_path' ], onPath ); +resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); +resolveParentPaths( [ './../non_existent_path' ], onPaths ); -function onPath( error, path ) { +function onPaths( error, paths ) { if ( error ) { throw error; } - console.log( path ); + console.log( paths ); } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 7894f9692eb..30910b2c2be 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -23,71 +23,168 @@ var resolve = require( 'path' ).resolve; var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; var isFunction = require( '@stdlib/assert/is-function' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ); var format = require( '@stdlib/string/format' ); var validate = require( './validate.js' ); -// MAIN // +// VARIABLES // + +var MODES = { + 'first': first, + 'some': some, + 'all': all, + 'each': each +}; + + +// FUNCTIONS // /** -* Asynchronously resolves a path from a set of paths by walking parent directories. +* Asynchronously resolves any first path from a set of paths by walking parent directories. * +* @private * @param {Array} paths - paths to resolve from -* @param {Options} [options] - function options -* @param {string} [options.dir] - base directory -* @param {Callback} clbk - callback to invoke after resolving a path -* @throws {TypeError} first argument must be an array of strings -* @throws {TypeError} callback argument must be a function -* @throws {TypeError} options argument must be an object -* @throws {TypeError} must provide valid options +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths * @returns {void} -* -* @example -* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); -* -* function onPath( error, path ) { -* if ( error ) { -* throw error; -* } -* console.log( path ); -* } */ -function resolveParentPaths( paths, options, clbk ) { - var spath; +function first( paths, dir, done ) { var child; - var opts; - var done; - var dir; - var err; + var spath; + var out = []; var i; - if ( !isStringArray( paths ) ) { - throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); + // Start at a base directory and continue moving up through each parent directory... + for ( i = 0; i < paths.length - 1; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists.sync( spath ) ) { + out.push( spath ); + return done( null, out ); + } } - opts = {}; - if ( arguments.length > 2 ) { - done = clbk; - err = validate( opts, options ); - if ( err ) { - throw err; + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); + + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool ) { + out.push( spath ); + return done( null, out ); } - } else { - done = options; + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, out ); + } + for ( j = 0; j < paths.length - 1; j++ ) { + spath = resolve( dir, paths[ j ] ); + if ( exists.sync( spath ) ) { + out.push( spath ); + return done( null, out ); + } + } + // Resolve paths at next directory level: + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); } - if ( !isFunction( done ) ) { - throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', done ) ); +} + +/** +* Asynchronously resolves some paths from a set of paths at a directory level by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths +* @returns {void} +*/ +function some( paths, dir, done ) { + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... + for ( i = 0; i < paths.length - 1; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists.sync( spath ) ) { + out.push( spath ); + } } - if ( opts.dir ) { - dir = resolve( cwd(), opts.dir ); - } else { - dir = cwd(); + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); + + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool ) { + out.push( spath ); + } + // Check if we have resolved any path... + if ( out.length > 0 ) { + return done( null, out ); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, out ); + } + for ( j = 0; j < paths.length - 1; j++ ) { + spath = resolve( dir, paths[ j ] ); + if ( exists.sync( spath ) ) { + out.push( spath ); + } + } + // Resolve paths at next directory level: + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); } +} + +/** +* Asynchronously resolves all paths from a set of paths at a directory level by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths +* @returns {void} +*/ +function all( paths, dir, done ) { + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... for ( i = 0; i < paths.length - 1; i++ ) { spath = resolve( dir, paths[ i ] ); if ( exists.sync( spath ) ) { - return done( null, spath ); + out.push( spath ); } } spath = resolve( dir, paths[ paths.length - 1 ] ); @@ -104,29 +201,172 @@ function resolveParentPaths( paths, options, clbk ) { function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err var j; if ( bool ) { - return done( null, spath ); + out.push( spath ); + } + // Check if we have resolved all paths... + if ( out.length === paths.length ) { + return done( null, out ); } // Resolve a parent directory: + out = []; child = dir; dir = resolve( dir, '..' ); // If we have already reached root, we cannot resolve any higher directories... if ( child === dir ) { - return done( null, null ); + return done( null, out ); } - // Resolve the next search path: for ( j = 0; j < paths.length - 1; j++ ) { spath = resolve( dir, paths[ j ] ); if ( exists.sync( spath ) ) { - return done( null, spath ); + out.push( spath ); + } + } + // Resolve paths at next directory level: + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); + } +} + +/** +* Asynchronously resolves each path from a set of paths by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths +* @returns {void} +*/ +function each( paths, dir, done ) { + var resolved = {}; + var count = 0; + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... + for ( i = 0; i < paths.length - 1; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists.sync( spath ) && !hasOwnProp( resolved, i ) ) { + resolved[ i ] = spath; + count += 1; + } + } + spath = resolve( dir, paths[ paths.length - 1 ] ); + exists( spath, onExists ); + + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool && !hasOwnProp( resolved, paths.length - 1 ) ) { + resolved[ paths.length - 1 ] = spath; + count += 1; + } + // Check if we have resolved all paths... + if ( count === paths.length ) { + for ( j = 0; j < paths.length; j++ ) { + out.push( resolved[ j ] ); + } + return done( null, out ); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + for ( j = 0; j < paths.length; j++ ) { + if ( hasOwnProp( resolved, j ) ) { + out.push( resolved[ j ] ); + continue; + } + out.push( null ); } + return done( null, out ); } + for ( j = 0; j < paths.length - 1; j++ ) { + spath = resolve( dir, paths[ j ] ); + if ( exists.sync( spath ) && !hasOwnProp( resolved, j ) ) { + resolved[ j ] = spath; + count += 1; + } + } + // Resolve paths at next directory level: spath = resolve( dir, paths[ paths.length - 1 ] ); exists( spath, onExists ); } } +// MAIN // + +/** +* Asynchronously resolves paths from a set of paths by walking parent directories. +* +* @param {Array} paths - paths to resolve from +* @param {Options} [options] - function options +* @param {string} [options.dir] - base directory +* @param {string} [options.mode] - mode of operation +* @param {Callback} clbk - callback to invoke after resolving paths +* @throws {TypeError} first argument must be an array of strings +* @throws {TypeError} callback argument must be a function +* @throws {TypeError} options argument must be an object +* @throws {TypeError} must provide valid options +* @returns {void} +* +* @example +* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); +* +* function onPaths( error, paths ) { +* if ( error ) { +* throw error; +* } +* console.log( paths ); +* } +*/ +function resolveParentPaths( paths, options, clbk ) { + var opts; + var done; + var mode; + var dir; + var fcn; + var err; + if ( !isStringArray( paths ) ) { + throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); + } + opts = {}; + if ( arguments.length > 2 ) { + done = clbk; + err = validate( opts, options ); + if ( err ) { + throw err; + } + } else { + done = options; + } + if ( !isFunction( done ) ) { + throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', done ) ); + } + if ( opts.dir ) { + dir = resolve( cwd(), opts.dir ); + } else { + dir = cwd(); + } + mode = opts.mode || 'all'; + + fcn = MODES[ mode ]; + fcn( paths, dir, done ); +} + + // EXPORTS // module.exports = resolveParentPaths; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js index 49976b7de0c..b1275d31ad8 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js @@ -19,26 +19,26 @@ 'use strict'; /** -* Resolve a path from a set of paths by walking parent directories. +* Resolve paths from a set of paths by walking parent directories. * * @module @stdlib/fs/resolve-parent-paths * * @example * var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); * -* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPath ); +* resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); * -* function onPath( error, path ) { +* function onPaths( error, paths ) { * if ( error ) { * throw error; * } -* console.log( path ); +* console.log( paths ); * } * * @example * var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); * -* var path = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); +* var paths = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); */ // MODULES // diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js index 781b73febcc..1cf9094cd22 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -22,35 +22,182 @@ var resolve = require( 'path' ).resolve; var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ).sync; var format = require( '@stdlib/string/format' ); var validate = require( './validate.js' ); +// VARIABLES // + +var MODES = { + 'first': first, + 'some': some, + 'all': all, + 'each': each +}; + + +// FUNCTIONS // + +/** +* Synchronously resolves any first path from a set of paths by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @returns {Array} resolved paths +*/ +function first( paths, dir ) { + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... + while ( child !== dir ) { + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists( spath ) ) { + out.push( spath ); + return out; + } + } + child = dir; + dir = resolve( dir, '..' ); + } + return out; +} + +/** +* Synchronously resolves some paths from a set of paths at a directory level by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @returns {Array} resolved paths +*/ +function some( paths, dir ) { + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... + while ( child !== dir ) { + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists( spath ) ) { + out.push( spath ); + } + } + if ( out.length > 0 ) { + return out; + } + child = dir; + dir = resolve( dir, '..' ); + } + return out; +} + +/** +* Synchronously resolves all paths from a set of paths at a directory level by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @returns {Array} resolved paths +*/ +function all( paths, dir ) { + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... + while ( child !== dir ) { + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists( spath ) ) { + out.push( spath ); + } + } + if ( out.length === paths.length ) { + return out; + } + out = []; + child = dir; + dir = resolve( dir, '..' ); + } + return out; +} + +/** +* Synchronously resolves each path from a set of paths by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve from +* @param {string} dir - base directory +* @returns {Array} resolved paths +*/ +function each( paths, dir ) { + var resolved = {}; + var count = 0; + var child; + var spath; + var out = []; + var i; + + // Start at a base directory and continue moving up through each parent directory... + while ( child !== dir ) { + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + if ( exists( spath ) && !hasOwnProp( resolved, i ) ) { + resolved[ i ] = spath; + count += 1; + } + } + if ( count === paths.length ) { + break; + } + child = dir; + dir = resolve( dir, '..' ); + } + for ( i = 0; i < paths.length; i++ ) { + if ( hasOwnProp( resolved, i ) ) { + out.push( resolved[ i ] ); + continue; + } + out.push( null ); + } + return out; +} + + // MAIN // /** -* Synchronously resolves a path from a set of paths by walking parent directories. +* Synchronously resolves paths from a set of paths by walking parent directories. * * @param {Array} paths - paths to resolve from * @param {Options} [options] - function options * @param {string} [options.dir] - base directory +* @param {string} [options.mode] - mode of operation * @throws {TypeError} first argument must be an array of strings * @throws {TypeError} options argument must be an object * @throws {TypeError} must provide valid options -* @returns {(string|null)} resolved path or null +* @returns {Array} resolved paths * * @example -* var path = resolveParentPaths( [ 'package.json', 'package-lock.json' ] ); +* var paths = resolveParentPaths( [ 'package.json', 'package-lock.json' ] ); */ function resolveParentPaths( paths, options ) { - var spath; - var child; var opts; + var mode; var dir; + var fcn; var err; - var i; if ( !isStringArray( paths ) ) { throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); } @@ -66,18 +213,10 @@ function resolveParentPaths( paths, options ) { } else { dir = cwd(); } - // Start at a base directory and continue moving up through each parent directory until able to resolve a search path or until reaching the root directory... - while ( child !== dir ) { - for ( i = 0; i < paths.length; i++ ) { - spath = resolve( dir, paths[ i ] ); - if ( exists( spath ) ) { - return spath; - } - } - child = dir; - dir = resolve( dir, '..' ); - } - return null; + mode = opts.mode || 'all'; + + fcn = MODES[ mode ]; + return fcn( paths, dir ); } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js index 47391c96775..6fd3988e348 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js @@ -26,6 +26,16 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var format = require( '@stdlib/string/format' ); +// VARIABLES // + +var isMode = { + 'first': true, + 'some': true, + 'all': true, + 'each': true +}; + + // MAIN // /** @@ -35,12 +45,14 @@ var format = require( '@stdlib/string/format' ); * @param {Object} opts - destination object * @param {Options} options - function options * @param {string} [options.dir] - base directory +* @param {string} [options.mode] - operation mode * @returns {(Error|null)} error object or null * * @example * var opts = {}; * var options = { -* 'dir': '/foo/bar/baz' +* 'dir': '/foo/bar/baz', +* 'mode': 'some' * }; * * var err = validate( opts, options ); @@ -58,6 +70,15 @@ function validate( opts, options ) { return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'dir', opts.dir ) ); } } + if ( hasOwnProp( options, 'mode' ) ) { + opts.mode = options.mode; + if ( !isString( opts.mode ) ) { + return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'mode', opts.mode ) ); + } + if ( !isMode[ opts.mode ] ) { + return new TypeError( format( 'invalid option. `%s` option must be a valid mode. Option: `%s`.', 'mode', opts.mode ) ); + } + } return null; } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json b/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json index 203a15bd84b..ef6d3936459 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/package.json @@ -1,7 +1,7 @@ { "name": "@stdlib/fs/resolve-parent-paths", "version": "0.0.0", - "description": "Resolve a path from a set of paths by walking parent directories.", + "description": "Resolve paths from a set of paths by walking parent directories.", "license": "Apache-2.0", "author": { "name": "The Stdlib Authors", diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js index dfb94acb4fc..ae2f53dab68 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -211,25 +211,27 @@ tape( 'the function throws an error if provided an invalid option', function tes } }); -tape( 'the function resolves a path from a set of paths by walking parent directories', opts, function test( t ) { +tape( 'the function resolves paths from a set of paths by walking parent directories', opts, function test( t ) { var expected; var base; var dir; + opts = { + 'mode': 'first' + }; dir = cwd(); base = basename( dir ); expected = dir; - resolveParentPaths( [ base ], onPath ); - resolveParentPaths( [ 'beep-boop!!!hello world!?!', base ], onPath ); - resolveParentPaths( [ base, 'beep-boop!!!hello world!?!' ], onPath ); + resolveParentPaths( [ base ], opts, onPaths ); t.end(); - function onPath( error, actual ) { + function onPaths( error, actual ) { if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual, expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); } }); @@ -237,37 +239,220 @@ tape( 'the function resolves a path from a set of paths by walking parent direct var expected; var opts; + opts = { + 'dir': __dirname + }; expected = resolve( __dirname, '../package.json' ); + resolveParentPaths( [ 'package.json' ], opts, onPaths ); + t.end(); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); + } +}); + +tape( 'the function resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { + var expected; + var dir; + opts = { - 'dir': __dirname + 'dir': __dirname, + 'mode': 'first' }; - resolveParentPaths( [ 'package.json' ], opts, onPath ); - resolveParentPaths( [ 'beep-boop!!!hello world!?!', 'package.json' ], opts, onPath ); - resolveParentPaths( [ 'package.json', 'beep-boop!!!hello world!?!' ], opts, onPath ); + dir = resolve( __dirname, '../package.json' ); + + expected = dir; + resolveParentPaths( [ 'package.json' ], opts, onPaths ); + resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths ); + resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); t.end(); - function onPath( error, actual ) { + function onPaths( error, actual ) { if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual, expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); } }); -tape( 'the function returns `null` if unable to resolve a parent path', opts, function test( t ) { - resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], onPath ); +tape( 'the function resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { + var dir1; + var dir2; + + opts = { + 'dir': __dirname, + 'mode': 'some' + }; + dir1 = resolve( __dirname, '../package.json' ); + dir2 = resolve( __dirname, '../README.md' ); + + resolveParentPaths( [ 'package.json' ], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths1 ); + resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths2 ); t.end(); - function onPath( error, actual ) { + function onPaths1( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + } + + function onPaths2( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + } +}); + +tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { + var dir1; + var dir2; + + opts = { + 'dir': __dirname, + 'mode': 'all' + }; + dir1 = resolve( __dirname, '../package.json' ); + dir2 = resolve( __dirname, '../README.md' ); + + resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); + resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPathsPositive ); + t.end(); + + function onPathsNegative( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns expected number of paths' ); + } + + function onPathsPositive( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + } +}); + +tape( 'the function resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { + var dir1; + var dir2; + var base; + + opts = { + 'dir': __dirname, + 'mode': 'each' + }; + dir1 = resolve( __dirname, '../package.json' ); + dir2 = __dirname; + base = basename( dir2 ); + + resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); + resolveParentPaths( [ 'package.json', base ], opts, onPathsPositive ); + t.end(); + + function onPathsNegative( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); + t.strictEqual( actual[ 1 ], dir1, 'returns path' ); + } + + function onPathsPositive( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + } +}); + +tape( 'the function returns an empty array if unable to resolve a parent path (`first` mode)', opts, function test( t ) { + var opts; + + opts = { + 'mode': 'first' + }; + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + t.end(); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns empty array' ); + } +}); + +tape( 'the function returns an empty array if unable to resolve a parent path (`some` mode)', opts, function test( t ) { + var opts; + + opts = { + 'mode': 'some' + }; + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + t.end(); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns empty array' ); + } +}); + +tape( 'the function returns an empty array if unable to resolve a parent path (`all` mode)', opts, function test( t ) { + var opts; + + opts = { + 'mode': 'all' + }; + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + t.end(); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns empty array' ); + } +}); + +tape( 'the function returns a `null` array if unable to resolve a parent path (`each` mode)', opts, function test( t ) { + var opts; + + opts = { + 'mode': 'each' + }; + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + t.end(); + + function onPaths( error, actual ) { if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual, null, 'returns null' ); + t.strictEqual( actual.length, 1, 'returns expected array' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); } }); -tape( 'the function returns `null` if unable to resolve a parent path (options)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (options)', opts, function test( t ) { var opts = { 'dir': __dirname }; @@ -278,6 +463,6 @@ tape( 'the function returns `null` if unable to resolve a parent path (options)' if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual, null, 'returns null' ); + t.strictEqual( actual.length, 0, 'returns empty array' ); } }); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js index 74c21df75e2..4166af41b32 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js @@ -21,9 +21,11 @@ // MODULES // var resolve = require( 'path' ).resolve; +var basename = require( 'path' ).basename; var exec = require( 'child_process' ).exec; var tape = require( 'tape' ); var replace = require( '@stdlib/string/replace' ); +var trim = require( '@stdlib/string/trim' ); var isAbsolutePath = require( '@stdlib/assert/is-absolute-path' ); var IS_BROWSER = require( '@stdlib/assert/is-browser' ); var IS_WINDOWS = require( '@stdlib/assert/is-windows' ); @@ -37,6 +39,7 @@ var fpath = resolve( __dirname, '..', 'bin', 'cli' ); var opts = { 'skip': IS_BROWSER || IS_WINDOWS }; +var EXTRA_LINES = 3; // square brackets + empty line // FIXTURES // @@ -143,22 +146,135 @@ tape( 'when invoked with a `-V` flag, the command-line interface prints the vers } }); -tape( 'the command-line interface resolves a path from a set of paths by walking parent directories', opts, function test( t ) { +tape( 'the command-line interface resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, + '--mode', + 'first', + '--dir', + __dirname, 'package.json', - 'beep-boop!!!hello world!?!' + 'beep-boop!!!helloWorld!?!' ]; exec( cmd.join( ' ' ), done ); function done( error, stdout, stderr ) { + var actual; var str; if ( error ) { t.fail( error.message ); } else { - str = stdout.toString(); + actual = stdout.split( '\n' ); + t.strictEqual( actual.length - EXTRA_LINES, 1, 'prints expected number of paths' ); + + str = trim( actual[ 1 ] ).slice( 1, -1 ); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + + t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); + } + t.end(); + } +}); + +tape( 'the command-line interface resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { + var cmd = [ + EXEC_PATH, + fpath, + '--mode', + 'some', + '--dir', + __dirname, + 'package.json', + 'beep-boop!!!helloWorld!?!', + 'README.md' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + var str; + if ( error ) { + t.fail( error.message ); + } else { + actual = stdout.split( '\n' ); + t.strictEqual( actual.length - EXTRA_LINES, 2, 'prints expected number of paths' ); + + str = trim( actual[ 1 ] ).slice( 1, -2 ); t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + + str = trim( actual[ 2 ] ).slice( 1, -1 ); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + + t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); + } + t.end(); + } +}); + +tape( 'the command-line interface resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { + var cmd = [ + EXEC_PATH, + fpath, + '--mode', + 'all', + '--dir', + __dirname, + 'package.json', + 'README.md' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + var str; + if ( error ) { + t.fail( error.message ); + } else { + actual = stdout.split( '\n' ); + t.strictEqual( actual.length - EXTRA_LINES, 2, 'prints expected number of paths' ); + + str = trim( actual[ 1 ] ).slice( 1, -2 ); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + + str = trim( actual[ 2 ] ).slice( 1, -1 ); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + + t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); + } + t.end(); + } +}); + +tape( 'the command-line interface resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { + var base = basename( fpath ); + var cmd = [ + EXEC_PATH, + fpath, + '--mode', + 'each', + '--dir', + __dirname, + 'package.json', + base + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + var str; + if ( error ) { + t.fail( error.message ); + } else { + actual = stdout.split( '\n' ); + t.strictEqual( actual.length - EXTRA_LINES, 2, 'prints expected number of paths' ); + + str = trim( actual[ 1 ] ).slice( 1, -2 ); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + + str = trim( actual[ 2 ] ).slice( 1, -1 ); + t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); } t.end(); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js index 7cc991d88cc..38ab906fcd4 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.js @@ -32,7 +32,7 @@ tape( 'main export is a function', function test( t ) { t.end(); }); -tape( 'attached to the main export is a function to resolve a parent paths synchronously', function test( t ) { +tape( 'attached to the main export is a function to resolve parent paths synchronously', function test( t ) { t.equal( typeof resolveParentPaths.sync, 'function', 'has `sync` method' ); t.end(); }); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js index 95e524710ea..bd7a697615d 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -156,64 +156,207 @@ tape( 'the function throws an error if provided an invalid option', function tes } }); -tape( 'the function resolves a path from a set of paths by walking parent directories', opts, function test( t ) { +tape( 'the function resolves paths from a set of paths by walking parent directories', opts, function test( t ) { var expected; var actual; var base; var dir; + opts = { + 'mode': 'first' + }; dir = cwd(); base = basename( dir ); expected = dir; actual = resolveParentPaths( [ base ] ); - t.strictEqual( actual, expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); - expected = dir; - actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!', base ] ); - t.strictEqual( actual, expected, 'returns path' ); + t.end(); +}); + +tape( 'the function resolves paths from a set of paths by walking parent directories (dir option)', opts, function test( t ) { + var expected; + var actual; + var opts; + var dir; + + opts = { + 'dir': __dirname + }; + dir = resolve( __dirname, '../package.json' ); expected = dir; - actual = resolveParentPaths( [ base, 'beep-boop!!!hello world!?!' ] ); - t.strictEqual( actual, expected, 'returns path' ); + actual = resolveParentPaths( [ 'package.json' ], opts ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); t.end(); }); -tape( 'the function resolves a path from a set of paths by walking parent directories (dir option)', opts, function test( t ) { +tape( 'the function resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { var expected; var actual; var opts; var dir; opts = { - 'dir': __dirname + 'dir': __dirname, + 'mode': 'first' }; dir = resolve( __dirname, '../package.json' ); expected = dir; actual = resolveParentPaths( [ 'package.json' ], opts ); - t.strictEqual( actual, expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); - expected = dir; - actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!', 'package.json' ], opts ); - t.strictEqual( actual, expected, 'returns path' ); + actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); - expected = dir; - actual = resolveParentPaths( [ 'package.json', 'beep-boop!!!hello world!?!' ], opts ); - t.strictEqual( actual, expected, 'returns path' ); + actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], expected, 'returns path' ); + + t.end(); +}); + +tape( 'the function resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { + var actual; + var opts; + var dir1; + var dir2; + + opts = { + 'dir': __dirname, + 'mode': 'some' + }; + dir1 = resolve( __dirname, '../package.json' ); + dir2 = resolve( __dirname, '../README.md' ); + + actual = resolveParentPaths( [ 'package.json' ], opts ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + + actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); + t.strictEqual( actual.length, 1, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + + actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], dir2, 'returns path' ); t.end(); }); -tape( 'the function returns `null` if unable to resolve a parent path', opts, function test( t ) { - var actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ] ); +tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { + var actual; + var opts; + var dir1; + var dir2; + + opts = { + 'dir': __dirname, + 'mode': 'all' + }; + dir1 = resolve( __dirname, '../package.json' ); + dir2 = resolve( __dirname, '../README.md' ); + + actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); + t.strictEqual( actual.length, 0, 'returns expected number of paths' ); + + actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + + t.end(); +}); + +tape( 'the function resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { + var actual; + var opts; + var dir1; + var dir2; + var base; + + opts = { + 'dir': __dirname, + 'mode': 'each' + }; + dir1 = resolve( __dirname, '../package.json' ); + dir2 = __dirname; + base = basename( dir2 ); + + actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); + t.strictEqual( actual[ 1 ], dir1, 'returns path' ); + + actual = resolveParentPaths( [ 'package.json', base ], opts ); + t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + + t.end(); +}); + +tape( 'the function returns an empty array if unable to resolve a parent path (`first` mode)', opts, function test( t ) { + var actual; + var opts; + + opts = { + 'mode': 'first' + }; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + + t.strictEqual( actual.length, 0, 'returns empty array' ); + t.end(); +}); + +tape( 'the function returns an empty array if unable to resolve a parent path (`some` mode)', opts, function test( t ) { + var actual; + var opts; + + opts = { + 'mode': 'some' + }; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + + t.strictEqual( actual.length, 0, 'returns empty array' ); + t.end(); +}); + +tape( 'the function returns an empty array if unable to resolve a parent path (`all` mode)', opts, function test( t ) { + var actual; + var opts; + + opts = { + 'mode': 'all' + }; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + + t.strictEqual( actual.length, 0, 'returns empty array' ); + t.end(); +}); + +tape( 'the function returns a `null` array if unable to resolve a parent path (`each` mode)', opts, function test( t ) { + var actual; + var opts; + + opts = { + 'mode': 'each' + }; + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); - t.strictEqual( actual, null, 'returns null' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); t.end(); }); -tape( 'the function returns `null` if unable to resolve a parent path (options)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (options)', opts, function test( t ) { var actual; var opts; @@ -222,6 +365,6 @@ tape( 'the function returns `null` if unable to resolve a parent path (options)' }; actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); - t.strictEqual( actual, null, 'returns null' ); + t.strictEqual( actual.length, 0, 'returns empty array' ); t.end(); }); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js index 50eecedc507..0d1648f5a84 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js @@ -84,19 +84,49 @@ tape( 'if provided a `dir` option which is not a `string`, the function returns t.end(); }); +tape( 'if provided a `mode` option which is not a valid mode, the function returns a type error', function test( t ) { + var values; + var opts; + var err; + var i; + + values = [ + 5, + NaN, + true, + null, + void 0, + [], + {}, + function noop() {}, + 'beep' + ]; + + for ( i = 0; i < values.length; i++ ) { + opts = {}; + err = validate( opts, { + 'mode': values[i] + }); + t.equal( err instanceof TypeError, true, 'returns a type error when provided '+values[i] ); + } + t.end(); +}); + tape( 'the function returns `null` if all options are valid', function test( t ) { var opts; var obj; var err; opts = { - 'dir': './beep/boop' + 'dir': './beep/boop', + 'mode': 'first' }; obj = {}; err = validate( obj, opts ); t.equal( err, null, 'returns null' ); t.equal( obj.dir, opts.dir, 'sets dir option' ); + t.equal( obj.mode, opts.mode, 'sets mode option' ); t.end(); }); From b394d6a359a3bed496631a1ffe24d7faa0deba86 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 15 Jul 2024 16:38:09 -0700 Subject: [PATCH 04/33] refactor: avoid unnecessary object creation --- .../fs/resolve-parent-paths/lib/sync.js | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js index 1cf9094cd22..5d2f6691fab 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -22,9 +22,9 @@ var resolve = require( 'path' ).resolve; var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ).sync; +var filled = require( '@stdlib/array/base/filled' ); var format = require( '@stdlib/string/format' ); var validate = require( './validate.js' ); @@ -42,20 +42,21 @@ var MODES = { // FUNCTIONS // /** -* Synchronously resolves any first path from a set of paths by walking parent directories. +* Synchronously resolves the first path match from a set of paths by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @returns {Array} resolved paths */ function first( paths, dir ) { var child; var spath; - var out = []; + var out; var i; // Start at a base directory and continue moving up through each parent directory... + out = []; while ( child !== dir ) { for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); @@ -71,20 +72,21 @@ function first( paths, dir ) { } /** -* Synchronously resolves some paths from a set of paths at a directory level by walking parent directories. +* Synchronously resolves one or more paths from a set of paths at a directory level by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @returns {Array} resolved paths */ function some( paths, dir ) { var child; var spath; - var out = []; + var out; var i; // Start at a base directory and continue moving up through each parent directory... + out = []; while ( child !== dir ) { for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); @@ -105,17 +107,18 @@ function some( paths, dir ) { * Synchronously resolves all paths from a set of paths at a directory level by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @returns {Array} resolved paths */ function all( paths, dir ) { var child; var spath; - var out = []; + var out; var i; // Start at a base directory and continue moving up through each parent directory... + out = []; while ( child !== dir ) { for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); @@ -137,24 +140,29 @@ function all( paths, dir ) { * Synchronously resolves each path from a set of paths by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @returns {Array} resolved paths */ function each( paths, dir ) { - var resolved = {}; - var count = 0; + var count; var child; var spath; - var out = []; + var out; var i; + count = 0; + out = filled( null, paths.length ); + // Start at a base directory and continue moving up through each parent directory... while ( child !== dir ) { for ( i = 0; i < paths.length; i++ ) { + if ( out[ i ] === null ) { + continue; + } spath = resolve( dir, paths[ i ] ); - if ( exists( spath ) && !hasOwnProp( resolved, i ) ) { - resolved[ i ] = spath; + if ( exists( spath ) ) { + out[ i ] = spath; count += 1; } } @@ -164,13 +172,6 @@ function each( paths, dir ) { child = dir; dir = resolve( dir, '..' ); } - for ( i = 0; i < paths.length; i++ ) { - if ( hasOwnProp( resolved, i ) ) { - out.push( resolved[ i ] ); - continue; - } - out.push( null ); - } return out; } @@ -180,10 +181,10 @@ function each( paths, dir ) { /** * Synchronously resolves paths from a set of paths by walking parent directories. * -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {Options} [options] - function options * @param {string} [options.dir] - base directory -* @param {string} [options.mode] - mode of operation +* @param {string} [options.mode='all'] - mode of operation * @throws {TypeError} first argument must be an array of strings * @throws {TypeError} options argument must be an object * @throws {TypeError} must provide valid options From 1b0de3b8c4471e451e73cebfd4e8440650a96f50 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 15 Jul 2024 16:39:37 -0700 Subject: [PATCH 05/33] refactor: simplify assertion logic --- .../@stdlib/fs/resolve-parent-paths/lib/validate.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js index 6fd3988e348..d9f48c1955b 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js @@ -23,17 +23,13 @@ var isObject = require( '@stdlib/assert/is-plain-object' ); var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var contains = require( '@stdlib/array/base/assert/contains' ).factory; var format = require( '@stdlib/string/format' ); // VARIABLES // -var isMode = { - 'first': true, - 'some': true, - 'all': true, - 'each': true -}; +var isMode = contains( [ 'first', 'some', 'all', 'each' ] ); // MAIN // @@ -72,10 +68,7 @@ function validate( opts, options ) { } if ( hasOwnProp( options, 'mode' ) ) { opts.mode = options.mode; - if ( !isString( opts.mode ) ) { - return new TypeError( format( 'invalid option. `%s` option must be a string. Option: `%s`.', 'mode', opts.mode ) ); - } - if ( !isMode[ opts.mode ] ) { + if ( !isMode( opts.mode ) ) { return new TypeError( format( 'invalid option. `%s` option must be a valid mode. Option: `%s`.', 'mode', opts.mode ) ); } } From 0e0961959978cdfc793bbdcee79679a23de86180 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Mon, 15 Jul 2024 16:45:17 -0700 Subject: [PATCH 06/33] fix: update conditional --- lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js index 5d2f6691fab..f0c6c4c2afd 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -157,7 +157,7 @@ function each( paths, dir ) { // Start at a base directory and continue moving up through each parent directory... while ( child !== dir ) { for ( i = 0; i < paths.length; i++ ) { - if ( out[ i ] === null ) { + if ( out[ i ] !== null ) { continue; } spath = resolve( dir, paths[ i ] ); From 10c2b19e8cadc52b3ddfd65b73cd3d035d83d6fe Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 07:22:24 +0000 Subject: [PATCH 07/33] fix: make every operation asynchronous Signed-off-by: Snehil Shah --- .../fs/resolve-parent-paths/lib/async.js | 353 ++++++++++-------- .../resolve-parent-paths/test/test.async.js | 62 ++- 2 files changed, 248 insertions(+), 167 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 30910b2c2be..8473c79ce33 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -23,9 +23,9 @@ var resolve = require( 'path' ).resolve; var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; var isFunction = require( '@stdlib/assert/is-function' ); -var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ); +var filled = require( '@stdlib/array/base/filled' ); var format = require( '@stdlib/string/format' ); var validate = require( './validate.js' ); @@ -43,10 +43,10 @@ var MODES = { // FUNCTIONS // /** -* Asynchronously resolves any first path from a set of paths by walking parent directories. +* Asynchronously resolves the first path from a set of paths by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @param {Callback} done - callback to invoke after resolving paths * @returns {void} @@ -54,60 +54,73 @@ var MODES = { function first( paths, dir, done ) { var child; var spath; - var out = []; + var FLG = 0; // flag to track if we are done traversing a directory level + var out; var i; // Start at a base directory and continue moving up through each parent directory... - for ( i = 0; i < paths.length - 1; i++ ) { + out = []; + for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); - if ( exists.sync( spath ) ) { - out.push( spath ); - return done( null, out ); - } + exists( spath, getCallback( spath ) ); } - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); /** - * Callback invoked after checking for path existence. + * Returns a callback to be invoked upon checking for path existence. * * @private - * @param {(Error|null)} error - error object - * @param {boolean} bool - boolean indicating if a path exists - * @returns {void} + * @param {string} spath - resolved path + * @returns {Callback} callback */ - function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; - if ( bool ) { - out.push( spath ); - return done( null, out ); - } - // Resolve a parent directory: - child = dir; - dir = resolve( dir, '..' ); + function getCallback( spath ) { + return onExists; - // If we have already reached root, we cannot resolve any higher directories... - if ( child === dir ) { - return done( null, out ); - } - for ( j = 0; j < paths.length - 1; j++ ) { - spath = resolve( dir, paths[ j ] ); - if ( exists.sync( spath ) ) { + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool ) { out.push( spath ); - return done( null, out ); + } + // If we have traversed all paths at the current directory level, resolve parent directory... + FLG += 1; + if ( FLG === paths.length ) { + // Check if we have resolved any path... + if ( out.length > 0 ) { + return done( null, [ out[ 0 ] ] ); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // Reset flag: + FLG = 0; + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, out ); + } + // Resolve paths at next directory level: + for ( j = 0; j < paths.length; j++ ) { + spath = resolve( dir, paths[ j ] ); + exists( spath, getCallback( spath ) ); + } } } - // Resolve paths at next directory level: - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); } } /** -* Asynchronously resolves some paths from a set of paths at a directory level by walking parent directories. +* Asynchronously resolves one or more paths from a set of paths at a directory level by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @param {Callback} done - callback to invoke after resolving paths * @returns {void} @@ -115,53 +128,65 @@ function first( paths, dir, done ) { function some( paths, dir, done ) { var child; var spath; - var out = []; + var FLG = 0; // flag to track if we are done traversing a directory level + var out; var i; // Start at a base directory and continue moving up through each parent directory... - for ( i = 0; i < paths.length - 1; i++ ) { + out = []; + for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); - if ( exists.sync( spath ) ) { - out.push( spath ); - } + exists( spath, getCallback( spath ) ); } - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); /** - * Callback invoked after checking for path existence. + * Returns a callback to be invoked upon checking for path existence. * * @private - * @param {(Error|null)} error - error object - * @param {boolean} bool - boolean indicating if a path exists - * @returns {void} + * @param {string} spath - resolved path + * @returns {Callback} callback */ - function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; - if ( bool ) { - out.push( spath ); - } - // Check if we have resolved any path... - if ( out.length > 0 ) { - return done( null, out ); - } - // Resolve a parent directory: - child = dir; - dir = resolve( dir, '..' ); + function getCallback( spath ) { + return onExists; - // If we have already reached root, we cannot resolve any higher directories... - if ( child === dir ) { - return done( null, out ); - } - for ( j = 0; j < paths.length - 1; j++ ) { - spath = resolve( dir, paths[ j ] ); - if ( exists.sync( spath ) ) { + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool ) { out.push( spath ); } + // If we have traversed all paths at the current directory level, resolve parent directory... + FLG += 1; + if ( FLG === paths.length ) { + // Check if we have resolved any path... + if ( out.length > 0 ) { + return done( null, out ); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // Reset flag: + FLG = 0; + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, out ); + } + // Resolve paths at next directory level: + for ( j = 0; j < paths.length; j++ ) { + spath = resolve( dir, paths[ j ] ); + exists( spath, getCallback( spath ) ); + } + } } - // Resolve paths at next directory level: - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); } } @@ -175,56 +200,74 @@ function some( paths, dir, done ) { * @returns {void} */ function all( paths, dir, done ) { + var count; var child; var spath; - var out = []; + var FLG = 0; // flag to track if we are done traversing a directory level + var out; var i; + count = 0; + out = []; + // Start at a base directory and continue moving up through each parent directory... - for ( i = 0; i < paths.length - 1; i++ ) { + for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); - if ( exists.sync( spath ) ) { - out.push( spath ); - } + exists( spath, getCallback( i, spath ) ); } - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); /** - * Callback invoked after checking for path existence. + * Returns a callback to be invoked upon checking for path existence. * * @private - * @param {(Error|null)} error - error object - * @param {boolean} bool - boolean indicating if a path exists - * @returns {void} + * @param {NonNegativeInteger} idx - index + * @param {string} spath - resolved path + * @returns {Callback} callback */ - function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; - if ( bool ) { - out.push( spath ); - } - // Check if we have resolved all paths... - if ( out.length === paths.length ) { - return done( null, out ); - } - // Resolve a parent directory: - out = []; - child = dir; - dir = resolve( dir, '..' ); - - // If we have already reached root, we cannot resolve any higher directories... - if ( child === dir ) { - return done( null, out ); - } - for ( j = 0; j < paths.length - 1; j++ ) { - spath = resolve( dir, paths[ j ] ); - if ( exists.sync( spath ) ) { - out.push( spath ); + function getCallback( idx, spath ) { + return onExists; + + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool ) { + out[ idx ] = spath; + count += 1; + } + // If we have traversed all paths at the current directory level, resolve parent directory... + FLG += 1; + if ( FLG === paths.length ) { + // Check if we have resolved any path... + if ( count === paths.length ) { + return done( null, out ); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // Reset flag and buffers: + FLG = 0; + out = []; + count = 0; + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, out ); + } + // Resolve paths at next directory level: + for ( j = 0; j < paths.length; j++ ) { + spath = resolve( dir, paths[ j ] ); + exists( spath, getCallback( j, spath ) ); + } } } - // Resolve paths at next directory level: - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); } } @@ -238,70 +281,72 @@ function all( paths, dir, done ) { * @returns {void} */ function each( paths, dir, done ) { - var resolved = {}; - var count = 0; + var count; var child; var spath; - var out = []; + var FLG = 0; // flag to track if we are done traversing a directory level + var out; var i; + count = 0; + out = filled( null, paths.length ); + // Start at a base directory and continue moving up through each parent directory... - for ( i = 0; i < paths.length - 1; i++ ) { + for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); - if ( exists.sync( spath ) && !hasOwnProp( resolved, i ) ) { - resolved[ i ] = spath; - count += 1; - } + exists( spath, getCallback( i, spath ) ); } - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); /** - * Callback invoked after checking for path existence. + * Returns a callback to be invoked upon checking for path existence. * * @private - * @param {(Error|null)} error - error object - * @param {boolean} bool - boolean indicating if a path exists - * @returns {void} + * @param {NonNegativeInteger} idx - index + * @param {string} spath - resolved path + * @returns {Callback} callback */ - function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; - if ( bool && !hasOwnProp( resolved, paths.length - 1 ) ) { - resolved[ paths.length - 1 ] = spath; - count += 1; - } - // Check if we have resolved all paths... - if ( count === paths.length ) { - for ( j = 0; j < paths.length; j++ ) { - out.push( resolved[ j ] ); + function getCallback( idx, spath ) { + return onExists; + + /** + * Callback invoked after checking for path existence. + * + * @private + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} + */ + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + var j; + if ( bool && out[ idx ] === null ) { + out[ idx ] = spath; + count += 1; } - return done( null, out ); - } - // Resolve a parent directory: - child = dir; - dir = resolve( dir, '..' ); - - // If we have already reached root, we cannot resolve any higher directories... - if ( child === dir ) { - for ( j = 0; j < paths.length; j++ ) { - if ( hasOwnProp( resolved, j ) ) { - out.push( resolved[ j ] ); - continue; - } - out.push( null ); + // Check if we have resolved all paths... + if ( count === paths.length ) { + return done( null, out ); } - return done( null, out ); - } - for ( j = 0; j < paths.length - 1; j++ ) { - spath = resolve( dir, paths[ j ] ); - if ( exists.sync( spath ) && !hasOwnProp( resolved, j ) ) { - resolved[ j ] = spath; - count += 1; + // If we have traversed all paths at the current directory level, resolve parent directory... + FLG += 1; + if ( FLG === paths.length ) { + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // Reset flag: + FLG = 0; + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + return done( null, out ); + } + // Resolve paths at next directory level: + for ( j = 0; j < paths.length; j++ ) { + spath = resolve( dir, paths[ j ] ); + exists( spath, getCallback( j, spath ) ); + } } } - // Resolve paths at next directory level: - spath = resolve( dir, paths[ paths.length - 1 ] ); - exists( spath, onExists ); } } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js index ae2f53dab68..f4a36f99527 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -24,6 +24,7 @@ var resolve = require( 'path' ).resolve; var basename = require( 'path' ).basename; var tape = require( 'tape' ); var IS_BROWSER = require( '@stdlib/assert/is-browser' ); +var contains = require( '@stdlib/assert/contains' ); var noop = require( '@stdlib/utils/noop' ); var cwd = require( '@stdlib/process/cwd' ); var resolveParentPaths = require( './../lib/async.js' ); @@ -224,7 +225,6 @@ tape( 'the function resolves paths from a set of paths by walking parent directo expected = dir; resolveParentPaths( [ base ], opts, onPaths ); - t.end(); function onPaths( error, actual ) { if ( error ) { @@ -232,6 +232,7 @@ tape( 'the function resolves paths from a set of paths by walking parent directo } t.strictEqual( actual.length, 1, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.end(); } }); @@ -245,7 +246,6 @@ tape( 'the function resolves a path from a set of paths by walking parent direct expected = resolve( __dirname, '../package.json' ); resolveParentPaths( [ 'package.json' ], opts, onPaths ); - t.end(); function onPaths( error, actual ) { if ( error ) { @@ -253,37 +253,44 @@ tape( 'the function resolves a path from a set of paths by walking parent direct } t.strictEqual( actual.length, 1, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.end(); } }); tape( 'the function resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { - var expected; - var dir; + var dir1; + var dir2; + var FLG = 0; opts = { 'dir': __dirname, 'mode': 'first' }; - dir = resolve( __dirname, '../package.json' ); + dir1 = resolve( __dirname, '../package.json' ); + dir2 = resolve( __dirname, '../README.md' ); - expected = dir; resolveParentPaths( [ 'package.json' ], opts, onPaths ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths ); resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); - t.end(); function onPaths( error, actual ) { if ( error ) { t.ok( false, error.message ); } t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual[ 0 ] === dir1 || actual[ 0 ] === dir2, true, 'returns path' ); + + FLG += 1; + if ( FLG === 3 ) { + t.end(); + } } }); tape( 'the function resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { var dir1; var dir2; + var FLG = 0; opts = { 'dir': __dirname, @@ -295,7 +302,6 @@ tape( 'the function resolves some paths from a set of paths at a directory level resolveParentPaths( [ 'package.json' ], opts, onPaths1 ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths1 ); resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths2 ); - t.end(); function onPaths1( error, actual ) { if ( error ) { @@ -303,6 +309,11 @@ tape( 'the function resolves some paths from a set of paths at a directory level } t.strictEqual( actual.length, 1, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + + FLG += 1; + if ( FLG === 3 ) { + t.end(); + } } function onPaths2( error, actual ) { @@ -310,14 +321,20 @@ tape( 'the function resolves some paths from a set of paths at a directory level t.ok( false, error.message ); } t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); - t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + t.strictEqual( contains( actual, dir1 ), true, 'returns path' ); + t.strictEqual( contains( actual, dir2 ), true, 'returns path' ); + + FLG += 1; + if ( FLG === 3 ) { + t.end(); + } } }); tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { var dir1; var dir2; + var FLG = 0; opts = { 'dir': __dirname, @@ -328,13 +345,17 @@ tape( 'the function resolves all paths from a set of paths at a directory level resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPathsPositive ); - t.end(); function onPathsNegative( error, actual ) { if ( error ) { t.ok( false, error.message ); } t.strictEqual( actual.length, 0, 'returns expected number of paths' ); + + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } function onPathsPositive( error, actual ) { @@ -344,6 +365,11 @@ tape( 'the function resolves all paths from a set of paths at a directory level t.strictEqual( actual.length, 2, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], dir1, 'returns path' ); t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } }); @@ -351,6 +377,7 @@ tape( 'the function resolves each path from a set of paths by walking parent dir var dir1; var dir2; var base; + var FLG = 0; opts = { 'dir': __dirname, @@ -362,7 +389,6 @@ tape( 'the function resolves each path from a set of paths by walking parent dir resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); resolveParentPaths( [ 'package.json', base ], opts, onPathsPositive ); - t.end(); function onPathsNegative( error, actual ) { if ( error ) { @@ -371,6 +397,11 @@ tape( 'the function resolves each path from a set of paths by walking parent dir t.strictEqual( actual.length, 2, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], null, 'returns expected value' ); t.strictEqual( actual[ 1 ], dir1, 'returns path' ); + + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } function onPathsPositive( error, actual ) { @@ -380,6 +411,11 @@ tape( 'the function resolves each path from a set of paths by walking parent dir t.strictEqual( actual.length, 2, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], dir1, 'returns path' ); t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } }); From fce2e61dab70397aae69ee7fd1d1f9e759da3781 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 07:31:51 +0000 Subject: [PATCH 08/33] style: keep function descriptions consistent Signed-off-by: Snehil Shah --- lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js | 2 +- .../@stdlib/fs/resolve-parent-paths/test/test.async.js | 4 ++-- .../@stdlib/fs/resolve-parent-paths/test/test.cli.js | 4 ++-- .../@stdlib/fs/resolve-parent-paths/test/test.sync.js | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 8473c79ce33..c39322a1d92 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -43,7 +43,7 @@ var MODES = { // FUNCTIONS // /** -* Asynchronously resolves the first path from a set of paths by walking parent directories. +* Asynchronously resolves the first path match from a set of paths by walking parent directories. * * @private * @param {Array} paths - paths to resolve diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js index f4a36f99527..a34eb45c5ea 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -257,7 +257,7 @@ tape( 'the function resolves a path from a set of paths by walking parent direct } }); -tape( 'the function resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { +tape( 'the function resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { var dir1; var dir2; var FLG = 0; @@ -287,7 +287,7 @@ tape( 'the function resolves any first path from a set of paths by walking paren } }); -tape( 'the function resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { +tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { var dir1; var dir2; var FLG = 0; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js index 4166af41b32..8aa4db103d4 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js @@ -146,7 +146,7 @@ tape( 'when invoked with a `-V` flag, the command-line interface prints the vers } }); -tape( 'the command-line interface resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { +tape( 'the command-line interface resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, @@ -177,7 +177,7 @@ tape( 'the command-line interface resolves any first path from a set of paths by } }); -tape( 'the command-line interface resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { +tape( 'the command-line interface resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js index bd7a697615d..2b25e4ea3c0 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -195,7 +195,7 @@ tape( 'the function resolves paths from a set of paths by walking parent directo t.end(); }); -tape( 'the function resolves any first path from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { +tape( 'the function resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { var expected; var actual; var opts; @@ -223,7 +223,7 @@ tape( 'the function resolves any first path from a set of paths by walking paren t.end(); }); -tape( 'the function resolves some paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { +tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { var actual; var opts; var dir1; From 0ca54bcc5a2cd28c6a37023146c447a6f7bca2d7 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 09:05:53 +0000 Subject: [PATCH 09/33] refactor: use a depth-first approach for `each` mode Signed-off-by: Snehil Shah --- .../fs/resolve-parent-paths/lib/async.js | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index c39322a1d92..53be25e6e01 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -25,7 +25,6 @@ var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; var isFunction = require( '@stdlib/assert/is-function' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ); -var filled = require( '@stdlib/array/base/filled' ); var format = require( '@stdlib/string/format' ); var validate = require( './validate.js' ); @@ -284,17 +283,17 @@ function each( paths, dir, done ) { var count; var child; var spath; - var FLG = 0; // flag to track if we are done traversing a directory level + var FLG = false; // flag to check if we are done resolving all paths var out; var i; count = 0; - out = filled( null, paths.length ); + out = []; // Start at a base directory and continue moving up through each parent directory... for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); - exists( spath, getCallback( i, spath ) ); + exists( spath, getCallback( i, spath, dir ) ); } /** @@ -303,9 +302,10 @@ function each( paths, dir, done ) { * @private * @param {NonNegativeInteger} idx - index * @param {string} spath - resolved path + * @param {string} dir - base directory * @returns {Callback} callback */ - function getCallback( idx, spath ) { + function getCallback( idx, spath, dir ) { return onExists; /** @@ -317,35 +317,42 @@ function each( paths, dir, done ) { * @returns {void} */ function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; - if ( bool && out[ idx ] === null ) { + if ( bool ) { out[ idx ] = spath; count += 1; + + // Check if we have resolved all paths... + if ( count === paths.length ) { + if ( FLG ) { + return; + } + FLG = true; + return done( null, out ); + } + return; } - // Check if we have resolved all paths... - if ( count === paths.length ) { - return done( null, out ); - } - // If we have traversed all paths at the current directory level, resolve parent directory... - FLG += 1; - if ( FLG === paths.length ) { - // Resolve a parent directory: - child = dir; - dir = resolve( dir, '..' ); + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); - // Reset flag: - FLG = 0; + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + out[ idx ] = null; + count += 1; - // If we have already reached root, we cannot resolve any higher directories... - if ( child === dir ) { + // Check if we have resolved all paths... + if ( count === paths.length ) { + if ( FLG ) { + return; + } + FLG = true; return done( null, out ); } - // Resolve paths at next directory level: - for ( j = 0; j < paths.length; j++ ) { - spath = resolve( dir, paths[ j ] ); - exists( spath, getCallback( j, spath ) ); - } + return; } + // Resolve path at next directory level: + spath = resolve( dir, paths[ idx ] ); + exists( spath, getCallback( idx, spath, dir ) ); } } } From 13fca364ec2885c2021503f3fb9855e2c569e3f9 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 09:06:44 +0000 Subject: [PATCH 10/33] test: include specific case for `each` mode Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/test/test.async.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js index a34eb45c5ea..249a8fa201b 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -376,7 +376,6 @@ tape( 'the function resolves all paths from a set of paths at a directory level tape( 'the function resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { var dir1; var dir2; - var base; var FLG = 0; opts = { @@ -384,11 +383,10 @@ tape( 'the function resolves each path from a set of paths by walking parent dir 'mode': 'each' }; dir1 = resolve( __dirname, '../package.json' ); - dir2 = __dirname; - base = basename( dir2 ); + dir2 = resolve( __dirname, '../../resolve-parent-paths' ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); - resolveParentPaths( [ 'package.json', base ], opts, onPathsPositive ); + resolveParentPaths( [ 'package.json', 'resolve-parent-paths' ], opts, onPathsPositive ); function onPathsNegative( error, actual ) { if ( error ) { From 16815545baed3aeee3e966768380ac98ca4b8304 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 09:29:03 +0000 Subject: [PATCH 11/33] fix: initialize out array with `null` values Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/lib/async.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 53be25e6e01..0808b72e97e 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -25,6 +25,7 @@ var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; var isFunction = require( '@stdlib/assert/is-function' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ); +var filled = require( '@stdlib/array/base/filled' ); var format = require( '@stdlib/string/format' ); var validate = require( './validate.js' ); @@ -207,7 +208,7 @@ function all( paths, dir, done ) { var i; count = 0; - out = []; + out = filled( null, paths.length ); // Start at a base directory and continue moving up through each parent directory... for ( i = 0; i < paths.length; i++ ) { @@ -288,7 +289,7 @@ function each( paths, dir, done ) { var i; count = 0; - out = []; + out = filled( null, paths.length ); // Start at a base directory and continue moving up through each parent directory... for ( i = 0; i < paths.length; i++ ) { From 99e4bb8ac07fe96e3015ec5672f042a5ebb3ac9a Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 18:35:33 +0000 Subject: [PATCH 12/33] perf: avoid wasted `access` syscalls in `first` mode Signed-off-by: Snehil Shah --- .../fs/resolve-parent-paths/lib/async.js | 31 ++++++------------- .../resolve-parent-paths/test/test.async.js | 8 ++--- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 0808b72e97e..64632deb8d5 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -54,25 +54,22 @@ var MODES = { function first( paths, dir, done ) { var child; var spath; - var FLG = 0; // flag to track if we are done traversing a directory level var out; - var i; // Start at a base directory and continue moving up through each parent directory... out = []; - for ( i = 0; i < paths.length; i++ ) { - spath = resolve( dir, paths[ i ] ); - exists( spath, getCallback( spath ) ); - } + spath = resolve( dir, paths[ 0 ] ); + exists( spath, getCallback( 1, spath ) ); /** * Returns a callback to be invoked upon checking for path existence. * * @private + * @param {NonNegativeInteger} idx - index * @param {string} spath - resolved path * @returns {Callback} callback */ - function getCallback( spath ) { + function getCallback( idx, spath ) { return onExists; /** @@ -84,34 +81,24 @@ function first( paths, dir, done ) { * @returns {void} */ function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; if ( bool ) { out.push( spath ); + return done( null, out ); } // If we have traversed all paths at the current directory level, resolve parent directory... - FLG += 1; - if ( FLG === paths.length ) { - // Check if we have resolved any path... - if ( out.length > 0 ) { - return done( null, [ out[ 0 ] ] ); - } + if ( idx === paths.length ) { // Resolve a parent directory: child = dir; dir = resolve( dir, '..' ); - // Reset flag: - FLG = 0; - // If we have already reached root, we cannot resolve any higher directories... if ( child === dir ) { return done( null, out ); } - // Resolve paths at next directory level: - for ( j = 0; j < paths.length; j++ ) { - spath = resolve( dir, paths[ j ] ); - exists( spath, getCallback( spath ) ); - } + idx = 0; } + spath = resolve( dir, paths[ idx ] ); + exists( spath, getCallback( idx + 1, spath ) ); } } } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js index 249a8fa201b..93ed3b53d18 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -258,16 +258,14 @@ tape( 'the function resolves a path from a set of paths by walking parent direct }); tape( 'the function resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { - var dir1; - var dir2; + var dir; var FLG = 0; opts = { 'dir': __dirname, 'mode': 'first' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../README.md' ); + dir = resolve( __dirname, '../package.json' ); resolveParentPaths( [ 'package.json' ], opts, onPaths ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths ); @@ -278,7 +276,7 @@ tape( 'the function resolves the first path match from a set of paths by walking t.ok( false, error.message ); } t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ] === dir1 || actual[ 0 ] === dir2, true, 'returns path' ); + t.strictEqual( actual[ 0 ], dir, 'returns path' ); FLG += 1; if ( FLG === 3 ) { From 8de5033a54cfb89959b1dbfba2db650c2395e517 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 18:39:46 +0000 Subject: [PATCH 13/33] style: add space after list header Signed-off-by: Snehil Shah --- lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md index 474e83e6d68..b2315551dda 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md @@ -53,6 +53,7 @@ The function accepts the following `options`: - **dir**: base directory from which to begin walking. May be either an absolute path or a path relative to the current working directory. - **mode**: mode of operation. The following modes are supported: + - `first`: first resolved path is returned. - `some`: first set of paths resolved at a directory level are returned. - `all`: all paths resolved at a directory level are returned. From fb86abde23a7915ca6629583e03ecc95a86d0fdd Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 18:51:06 +0000 Subject: [PATCH 14/33] style: separate variable declarations and assignments Signed-off-by: Snehil Shah --- .../fs/resolve-parent-paths/lib/async.js | 17 +++++++++++------ .../@stdlib/fs/resolve-parent-paths/lib/sync.js | 1 + .../fs/resolve-parent-paths/test/test.async.js | 12 ++++++++---- .../fs/resolve-parent-paths/test/test.cli.js | 4 +--- .../fs/resolve-parent-paths/test/test.sync.js | 6 ++---- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 64632deb8d5..0556d1652a2 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -115,12 +115,14 @@ function first( paths, dir, done ) { function some( paths, dir, done ) { var child; var spath; - var FLG = 0; // flag to track if we are done traversing a directory level + var FLG; var out; var i; - // Start at a base directory and continue moving up through each parent directory... + FLG = 0; // initialize flag to track if we are done traversing a directory level out = []; + + // Start at a base directory and continue moving up through each parent directory... for ( i = 0; i < paths.length; i++ ) { spath = resolve( dir, paths[ i ] ); exists( spath, getCallback( spath ) ); @@ -190,11 +192,12 @@ function all( paths, dir, done ) { var count; var child; var spath; - var FLG = 0; // flag to track if we are done traversing a directory level + var FLG; var out; var i; - count = 0; + count = 0; // initialize counter to track if we are done resolving all paths + FLG = 0; // initialize flag to track if we are done traversing a directory level out = filled( null, paths.length ); // Start at a base directory and continue moving up through each parent directory... @@ -271,11 +274,12 @@ function each( paths, dir, done ) { var count; var child; var spath; - var FLG = false; // flag to check if we are done resolving all paths + var FLG; var out; var i; - count = 0; + count = 0; // initialize counter to track if we are done resolving all paths + FLG = 0; // initialize flag to check if we are done resolving all paths out = filled( null, paths.length ); // Start at a base directory and continue moving up through each parent directory... @@ -379,6 +383,7 @@ function resolveParentPaths( paths, options, clbk ) { var dir; var fcn; var err; + if ( !isStringArray( paths ) ) { throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js index f0c6c4c2afd..f20ff7e6f3d 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -199,6 +199,7 @@ function resolveParentPaths( paths, options ) { var dir; var fcn; var err; + if ( !isStringArray( paths ) ) { throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js index 93ed3b53d18..db96ce8c828 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js @@ -259,8 +259,9 @@ tape( 'the function resolves a path from a set of paths by walking parent direct tape( 'the function resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { var dir; - var FLG = 0; + var FLG; + FLG = 0; opts = { 'dir': __dirname, 'mode': 'first' @@ -288,8 +289,9 @@ tape( 'the function resolves the first path match from a set of paths by walking tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { var dir1; var dir2; - var FLG = 0; + var FLG; + FLG = 0; opts = { 'dir': __dirname, 'mode': 'some' @@ -332,8 +334,9 @@ tape( 'the function resolves one or more paths from a set of paths at a director tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { var dir1; var dir2; - var FLG = 0; + var FLG; + FLG = 0; opts = { 'dir': __dirname, 'mode': 'all' @@ -374,8 +377,9 @@ tape( 'the function resolves all paths from a set of paths at a directory level tape( 'the function resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { var dir1; var dir2; - var FLG = 0; + var FLG; + FLG = 0; opts = { 'dir': __dirname, 'mode': 'each' diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js index 8aa4db103d4..1f4cc082a3b 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js @@ -21,7 +21,6 @@ // MODULES // var resolve = require( 'path' ).resolve; -var basename = require( 'path' ).basename; var exec = require( 'child_process' ).exec; var tape = require( 'tape' ); var replace = require( '@stdlib/string/replace' ); @@ -247,7 +246,6 @@ tape( 'the command-line interface resolves all paths from a set of paths at a di }); tape( 'the command-line interface resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { - var base = basename( fpath ); var cmd = [ EXEC_PATH, fpath, @@ -256,7 +254,7 @@ tape( 'the command-line interface resolves each path from a set of paths by walk '--dir', __dirname, 'package.json', - base + 'resolve-parent-paths' ]; exec( cmd.join( ' ' ), done ); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js index 2b25e4ea3c0..0cb0151b7f4 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -281,22 +281,20 @@ tape( 'the function resolves each path from a set of paths by walking parent dir var opts; var dir1; var dir2; - var base; opts = { 'dir': __dirname, 'mode': 'each' }; dir1 = resolve( __dirname, '../package.json' ); - dir2 = __dirname; - base = basename( dir2 ); + dir2 = resolve( __dirname, '../../resolve-parent-paths' ); actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); t.strictEqual( actual.length, 2, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], null, 'returns expected value' ); t.strictEqual( actual[ 1 ], dir1, 'returns path' ); - actual = resolveParentPaths( [ 'package.json', base ], opts ); + actual = resolveParentPaths( [ 'package.json', 'resolve-parent-paths' ], opts ); t.strictEqual( actual.length, 2, 'returns expected number of paths' ); t.strictEqual( actual[ 0 ], dir1, 'returns path' ); t.strictEqual( actual[ 1 ], dir2, 'returns path' ); From 39cc0e3edb27a2e454fccbd66e5a362ec3126e15 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 19:01:06 +0000 Subject: [PATCH 15/33] docs: add a note for unpredictable return order in `some` mode Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/README.md | 1 + .../@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md index b2315551dda..300646cd5b0 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md @@ -96,6 +96,7 @@ The function accepts the same `options` as [`resolveParentPaths()`](#resolve-par ## Notes +- In `some` mode, the return order of resolved paths is not guaranteed when using asynchronously. - This implementation is **not** similar in functionality to core [`path.resolve`][node-core-path-resolve]. The latter performs string manipulation to generate a full path. This implementation walks parent directories to perform a **search**, thereby touching the file system. Accordingly, this implementation resolves _real_ absolute file paths and is intended for use when a target's location in a parent directory is unknown relative to a child directory; e.g., when wanting to find a package root from deep within a package directory. diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts index 5826de95b6c..09059efbc4b 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts @@ -55,6 +55,10 @@ interface ResolveParentPaths { * - `all`: all paths resolved at a directory level are returned. (default) * - `each`: each path resolved at any directory level is returned. * + * ## Notes + * + * - In `some` mode, the return order of resolved paths is not guaranteed. + * * @param paths - path to resolve from * @param options - function options * @param options.dir - base directory @@ -125,6 +129,10 @@ interface ResolveParentPaths { * - `all`: all paths resolved at a directory level are returned. (default) * - `each`: each path resolved at any directory level is returned. * +* ## Notes +* +* - In `some` mode, the return order of resolved paths is not guaranteed. +* * @param paths - paths to resolve from * @param options - function options * @param options.dir - base directory From f6562e31207204e2c119cc851095ee98a5f37225 Mon Sep 17 00:00:00 2001 From: Snehil Shah Date: Tue, 16 Jul 2024 19:04:56 +0000 Subject: [PATCH 16/33] docs: keep it consistent Signed-off-by: Snehil Shah --- .../@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts | 8 ++++---- .../@stdlib/fs/resolve-parent-paths/lib/async.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts index 09059efbc4b..6da9fc38168 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts @@ -59,7 +59,7 @@ interface ResolveParentPaths { * * - In `some` mode, the return order of resolved paths is not guaranteed. * - * @param paths - path to resolve from + * @param paths - path to resolve * @param options - function options * @param options.dir - base directory * @param options.mode - mode of operation @@ -81,7 +81,7 @@ interface ResolveParentPaths { /** * Asynchronously resolves paths from a set of paths by walking parent directories. * - * @param paths - path to resolve from + * @param paths - path to resolve * @param clbk - callback to invoke after resolving paths * * @example @@ -106,7 +106,7 @@ interface ResolveParentPaths { * - `all`: all paths resolved at a directory level are returned (default). * - `each`: each path resolved at any directory level is returned. * - * @param paths - paths to resolve from + * @param paths - paths to resolve * @param options - function options * @param options.dir - base directory * @param options.mode - mode of operation @@ -133,7 +133,7 @@ interface ResolveParentPaths { * * - In `some` mode, the return order of resolved paths is not guaranteed. * -* @param paths - paths to resolve from +* @param paths - paths to resolve * @param options - function options * @param options.dir - base directory * @param options.mode - mode of operation diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js index 0556d1652a2..c380ababb81 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js @@ -183,7 +183,7 @@ function some( paths, dir, done ) { * Asynchronously resolves all paths from a set of paths at a directory level by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @param {Callback} done - callback to invoke after resolving paths * @returns {void} @@ -265,7 +265,7 @@ function all( paths, dir, done ) { * Asynchronously resolves each path from a set of paths by walking parent directories. * * @private -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {string} dir - base directory * @param {Callback} done - callback to invoke after resolving paths * @returns {void} @@ -355,7 +355,7 @@ function each( paths, dir, done ) { /** * Asynchronously resolves paths from a set of paths by walking parent directories. * -* @param {Array} paths - paths to resolve from +* @param {Array} paths - paths to resolve * @param {Options} [options] - function options * @param {string} [options.dir] - base directory * @param {string} [options.mode] - mode of operation From de579f162eaffcb23a0ef8b13471006846ae2caf Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 16:14:49 -0700 Subject: [PATCH 17/33] refactor: rename file and reduce code duplication --- .../fs/resolve-parent-paths/lib/index.js | 8 +- .../lib/{async.js => main.js} | 154 +++++++++--------- .../fs/resolve-parent-paths/lib/sync.js | 8 +- .../test/{test.async.js => test.main.js} | 2 +- 4 files changed, 88 insertions(+), 84 deletions(-) rename lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/{async.js => main.js} (79%) rename lib/node_modules/@stdlib/fs/resolve-parent-paths/test/{test.async.js => test.main.js} (99%) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js index b1275d31ad8..a118ad53b2d 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js @@ -44,15 +44,17 @@ // MODULES // var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); -var resolveParentPaths = require( './async.js' ); +var main = require( './main.js' ); var sync = require( './sync.js' ); // MAIN // -setReadOnly( resolveParentPaths, 'sync', sync ); +setReadOnly( main, 'sync', sync ); // EXPORTS // -module.exports = resolveParentPaths; +module.exports = main; + +// exports: { "sync": "main.sync" } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js similarity index 79% rename from lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js rename to lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js index c380ababb81..c34b50435fc 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js @@ -54,52 +54,45 @@ var MODES = { function first( paths, dir, done ) { var child; var spath; + var idx; var out; - // Start at a base directory and continue moving up through each parent directory... out = []; + + // Start at a base directory and continue moving up through each parent directory... spath = resolve( dir, paths[ 0 ] ); - exists( spath, getCallback( 1, spath ) ); + + idx = 1; // index of next path + exists( spath, onExists ); /** - * Returns a callback to be invoked upon checking for path existence. + * Callback invoked after checking for path existence. * * @private - * @param {NonNegativeInteger} idx - index - * @param {string} spath - resolved path - * @returns {Callback} callback + * @param {(Error|null)} error - error object + * @param {boolean} bool - boolean indicating if a path exists + * @returns {void} */ - function getCallback( idx, spath ) { - return onExists; + function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err + if ( bool ) { + out.push( spath ); + return done( null, out ); + } + // If we have traversed all paths at the current directory level, resolve parent directory... + if ( idx === paths.length ) { + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); - /** - * Callback invoked after checking for path existence. - * - * @private - * @param {(Error|null)} error - error object - * @param {boolean} bool - boolean indicating if a path exists - * @returns {void} - */ - function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - if ( bool ) { - out.push( spath ); + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { return done( null, out ); } - // If we have traversed all paths at the current directory level, resolve parent directory... - if ( idx === paths.length ) { - // Resolve a parent directory: - child = dir; - dir = resolve( dir, '..' ); - - // If we have already reached root, we cannot resolve any higher directories... - if ( child === dir ) { - return done( null, out ); - } - idx = 0; - } - spath = resolve( dir, paths[ idx ] ); - exists( spath, getCallback( idx + 1, spath ) ); + idx = 0; } + spath = resolve( dir, paths[ idx ] ); + idx += 1; + exists( spath, onExists ); } } @@ -117,15 +110,25 @@ function some( paths, dir, done ) { var spath; var FLG; var out; - var i; FLG = 0; // initialize flag to track if we are done traversing a directory level out = []; // Start at a base directory and continue moving up through each parent directory... - for ( i = 0; i < paths.length; i++ ) { - spath = resolve( dir, paths[ i ] ); - exists( spath, getCallback( spath ) ); + return next( dir ); + + /** + * Resolves paths within a directory. + * + * @private + * @param {string} dir - directory to search + */ + function next( dir ) { + var i; + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + exists( spath, getCallback( spath ) ); + } } /** @@ -147,14 +150,12 @@ function some( paths, dir, done ) { * @returns {void} */ function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; if ( bool ) { out.push( spath ); } - // If we have traversed all paths at the current directory level, resolve parent directory... FLG += 1; if ( FLG === paths.length ) { - // Check if we have resolved any path... + // Check if we have resolved any paths... if ( out.length > 0 ) { return done( null, out ); } @@ -170,10 +171,7 @@ function some( paths, dir, done ) { return done( null, out ); } // Resolve paths at next directory level: - for ( j = 0; j < paths.length; j++ ) { - spath = resolve( dir, paths[ j ] ); - exists( spath, getCallback( spath ) ); - } + return next( dir ); } } } @@ -194,16 +192,26 @@ function all( paths, dir, done ) { var spath; var FLG; var out; - var i; count = 0; // initialize counter to track if we are done resolving all paths FLG = 0; // initialize flag to track if we are done traversing a directory level out = filled( null, paths.length ); // Start at a base directory and continue moving up through each parent directory... - for ( i = 0; i < paths.length; i++ ) { - spath = resolve( dir, paths[ i ] ); - exists( spath, getCallback( i, spath ) ); + return next( dir ); + + /** + * Resolves paths within a directory. + * + * @private + * @param {string} dir - directory to search + */ + function next( dir ) { + var i; + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + exists( spath, getCallback( i, spath ) ); + } } /** @@ -226,12 +234,10 @@ function all( paths, dir, done ) { * @returns {void} */ function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err - var j; if ( bool ) { out[ idx ] = spath; count += 1; } - // If we have traversed all paths at the current directory level, resolve parent directory... FLG += 1; if ( FLG === paths.length ) { // Check if we have resolved any path... @@ -252,10 +258,7 @@ function all( paths, dir, done ) { return done( null, out ); } // Resolve paths at next directory level: - for ( j = 0; j < paths.length; j++ ) { - spath = resolve( dir, paths[ j ] ); - exists( spath, getCallback( j, spath ) ); - } + return next( dir ); } } } @@ -288,6 +291,25 @@ function each( paths, dir, done ) { exists( spath, getCallback( i, spath, dir ) ); } + /** + * Determines whether all paths have been resolved. + * + * @private + * @returns {void} + */ + function next() { + count += 1; + + // Check if we have resolved all paths... + if ( count === paths.length ) { + if ( FLG ) { + return; + } + FLG = true; + return done( null, out ); + } + } + /** * Returns a callback to be invoked upon checking for path existence. * @@ -311,17 +333,7 @@ function each( paths, dir, done ) { function onExists( error, bool ) { // eslint-disable-line node/handle-callback-err if ( bool ) { out[ idx ] = spath; - count += 1; - - // Check if we have resolved all paths... - if ( count === paths.length ) { - if ( FLG ) { - return; - } - FLG = true; - return done( null, out ); - } - return; + return next(); } // Resolve a parent directory: child = dir; @@ -330,17 +342,7 @@ function each( paths, dir, done ) { // If we have already reached root, we cannot resolve any higher directories... if ( child === dir ) { out[ idx ] = null; - count += 1; - - // Check if we have resolved all paths... - if ( count === paths.length ) { - if ( FLG ) { - return; - } - FLG = true; - return done( null, out ); - } - return; + return next(); } // Resolve path at next directory level: spath = resolve( dir, paths[ idx ] ); diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js index f20ff7e6f3d..deca4ac7aa3 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -47,7 +47,7 @@ var MODES = { * @private * @param {Array} paths - paths to resolve * @param {string} dir - base directory -* @returns {Array} resolved paths +* @returns {Array} resolved paths */ function first( paths, dir ) { var child; @@ -77,7 +77,7 @@ function first( paths, dir ) { * @private * @param {Array} paths - paths to resolve * @param {string} dir - base directory -* @returns {Array} resolved paths +* @returns {Array} resolved paths */ function some( paths, dir ) { var child; @@ -109,7 +109,7 @@ function some( paths, dir ) { * @private * @param {Array} paths - paths to resolve * @param {string} dir - base directory -* @returns {Array} resolved paths +* @returns {Array} resolved paths */ function all( paths, dir ) { var child; @@ -142,7 +142,7 @@ function all( paths, dir ) { * @private * @param {Array} paths - paths to resolve * @param {string} dir - base directory -* @returns {Array} resolved paths +* @returns {Array} resolved paths */ function each( paths, dir ) { var count; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js similarity index 99% rename from lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js rename to lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js index db96ce8c828..0996b8057b5 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.async.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js @@ -27,7 +27,7 @@ var IS_BROWSER = require( '@stdlib/assert/is-browser' ); var contains = require( '@stdlib/assert/contains' ); var noop = require( '@stdlib/utils/noop' ); var cwd = require( '@stdlib/process/cwd' ); -var resolveParentPaths = require( './../lib/async.js' ); +var resolveParentPaths = require( './../lib/main.js' ); // VARIABLES // From bdae1fd347f2582d71c7aa9bbc01b26d884eb4b5 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:05:40 -0700 Subject: [PATCH 18/33] docs: update copy --- .../fs/resolve-parent-paths/docs/repl.txt | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt index 7a200fdc8ef..c46cf73a964 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt @@ -3,17 +3,10 @@ Asynchronously resolves paths from a set of paths by walking parent directories. - The following modes are supported: - - - first: first resolved path is returned. - - some: first set of paths resolved at a directory level are returned. - - all: all paths resolved at a directory level are returned. - - each: each path resolved at any directory level is returned. - Parameters ---------- paths: Array - Paths to resolve from. + Paths to resolve. options: Object (optional) Options. @@ -22,7 +15,17 @@ Base directory from which to search. Default: current working directory. options.mode: string (optional) - Mode of operation. Default: `all`. + Mode of operation. The following modes are supported: + + - first: return the first resolved path. + - some: return one or more paths resolved within the first directory + level containing a match. + - all: return all resolved paths within the first directory level + containing matches for all provided paths. + - each: independently return the first resolved path for each path at + any directory level. + + Default: 'all'. clbk: Function Callback to invoke after resolving a path. @@ -43,17 +46,10 @@ Synchronously resolves paths from a set of paths by walking parent directories. - The following modes are supported: - - - first: first resolved path is returned - - some: first set of paths resolved at a directory level are returned - - all: all paths resolved at a directory level are returned - - each: each path resolved at any directory level is returned - Parameters ---------- paths: Array - Paths to resolve from. + Paths to resolve. options: Object (optional) Options. @@ -62,7 +58,17 @@ Base directory from which to search. Default: current working directory. options.mode: string (optional) - Mode of operation. Default: `all`. + Mode of operation. The following modes are supported: + + - first: return the first resolved path. + - some: return one or more paths resolved within the first directory + level containing a match. + - all: return all resolved paths within the first directory level + containing matches for all provided paths. + - each: independently return the first resolved path for each path at + any directory level. + + Default: 'all'. Returns ------- From 2cf120ce29ab1246f44eb172ab1a4961c0260646 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:10:41 -0700 Subject: [PATCH 19/33] docs: update copy --- .../docs/types/index.d.ts | 46 ++++++------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts index 6da9fc38168..43a5b5ddafa 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts @@ -28,9 +28,22 @@ interface Options { dir?: string; /** - * Mode of operation (default: `all`). + * Mode of operation. + * + * ## Notes + * + * - The following modes are supported: + * + * - **first**: return the first resolved path. + * - **some**: return one or more paths resolved within the first directory level containing a match. + * - **all**: return all resolved paths within the first directory level containing matches for all provided paths. + * - **each**: independently return the first resolved path for each path at any directory level. + * + * Default: `'all'`. + * + * - In `'some'` mode, the return order of resolved paths is not guaranteed. */ - mode?: string; + mode?: 'first' | 'some' | 'all' | 'each'; } /** @@ -48,17 +61,6 @@ interface ResolveParentPaths { /** * Asynchronously resolves paths from a set of paths by walking parent directories. * - * The following modes are supported: - * - * - `first`: first resolved path is returned. - * - `some`: first set of paths resolved at a directory level are returned. - * - `all`: all paths resolved at a directory level are returned. (default) - * - `each`: each path resolved at any directory level is returned. - * - * ## Notes - * - * - In `some` mode, the return order of resolved paths is not guaranteed. - * * @param paths - path to resolve * @param options - function options * @param options.dir - base directory @@ -99,13 +101,6 @@ interface ResolveParentPaths { /** * Synchronously resolves paths from a set of paths by walking parent directories. * - * The following modes are supported: - * - * - `first`: first resolved path is returned. - * - `some`: first set of paths resolved at a directory level are returned. - * - `all`: all paths resolved at a directory level are returned (default). - * - `each`: each path resolved at any directory level is returned. - * * @param paths - paths to resolve * @param options - function options * @param options.dir - base directory @@ -122,17 +117,6 @@ interface ResolveParentPaths { /** * Asynchronously resolves paths from a set of paths by walking parent directories. * -* The following modes are supported: -* -* - `first`: first resolved path is returned. -* - `some`: first set of paths resolved at a directory level are returned. -* - `all`: all paths resolved at a directory level are returned. (default) -* - `each`: each path resolved at any directory level is returned. -* -* ## Notes -* -* - In `some` mode, the return order of resolved paths is not guaranteed. -* * @param paths - paths to resolve * @param options - function options * @param options.dir - base directory From acf2af1b6498e836d1bb99f9f2ae87dc23076a53 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:11:34 -0700 Subject: [PATCH 20/33] refactor: use function declaration --- .../@stdlib/fs/resolve-parent-paths/docs/types/test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts index 0a607d96221..1a82d18b755 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts @@ -18,11 +18,17 @@ import resolveParentPaths = require( './index' ); -const done = ( error: Error | null, path: string | null ): void => { +/** +* Callback function. +* +* @param error - error object +* @param path - resolved path +*/ +function done( error: Error | null, path: string | null ): void { if ( error || path === null ) { throw error; } -}; +} // TESTS // From e1a719eac8f74113bc86a0e78b85f532f8337dcd Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:16:57 -0700 Subject: [PATCH 21/33] test: fix callback and add test cases --- .../resolve-parent-paths/docs/types/test.ts | 57 +++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts index 1a82d18b755..9ebce5f12af 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts @@ -24,8 +24,8 @@ import resolveParentPaths = require( './index' ); * @param error - error object * @param path - resolved path */ -function done( error: Error | null, path: string | null ): void { - if ( error || path === null ) { +function done( error: Error | null, paths: Array ): void { + if ( error || paths === null ) { throw error; } } @@ -36,6 +36,7 @@ function done( error: Error | null, path: string | null ): void { // The function does not have a return value... { resolveParentPaths( [ 'package.json' ], done ); // $ExpectType void + resolveParentPaths( [ 'package.json' ], {}, done ); // $ExpectType void } // The compiler throws an error if the function is provided a first argument which is not an array of strings... @@ -49,6 +50,16 @@ function done( error: Error | null, path: string | null ): void { resolveParentPaths( ( x: number ): number => x, done ); // $ExpectError resolveParentPaths( 'beep', done ); // $ExpectError resolveParentPaths( [ 1, 2 ], done ); // $ExpectError + + resolveParentPaths( 123, {}, done ); // $ExpectError + resolveParentPaths( false, {}, done ); // $ExpectError + resolveParentPaths( true, {}, done ); // $ExpectError + resolveParentPaths( null, {}, done ); // $ExpectError + resolveParentPaths( undefined, {}, done ); // $ExpectError + resolveParentPaths( {}, {}, done ); // $ExpectError + resolveParentPaths( ( x: number ): number => x, {}, done ); // $ExpectError + resolveParentPaths( 'beep', {}, done ); // $ExpectError + resolveParentPaths( [ 1, 2 ], {}, done ); // $ExpectError } // The compiler throws an error if the function is provided a callback argument which is not a function with the expected signature... @@ -61,11 +72,27 @@ function done( error: Error | null, path: string | null ): void { resolveParentPaths( [ '/var/log/' ], [] ); // $ExpectError resolveParentPaths( [ '/var/log/' ], {} ); // $ExpectError resolveParentPaths( [ '/var/log/' ], ( x: number ): number => x ); // $ExpectError + + resolveParentPaths( [ '/var/log/' ], {}, 1 ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, false ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, true ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, null ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, undefined ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, [] ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, {} ); // $ExpectError + resolveParentPaths( [ '/var/log/' ], {}, ( x: number ): number => x ); // $ExpectError } // The compiler throws an error if the function is provided an options argument which is not an object... { + resolveParentPaths( [ 'package.json' ], '5', done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], 5, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], true, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], false, done ); // $ExpectError resolveParentPaths( [ 'package.json' ], null, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], undefined, done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], [], done ); // $ExpectError + resolveParentPaths( [ 'package.json' ], ( x: number ): number => x, done ); // $ExpectError } // The compiler throws an error if the function is provided an `dir` option which is not a string... @@ -79,8 +106,9 @@ function done( error: Error | null, path: string | null ): void { resolveParentPaths( [ 'package.json' ], { 'dir': ( x: number ): number => x }, done ); // $ExpectError } -// The compiler throws an error if the function is provided an `mode` option which is not a string... +// The compiler throws an error if the function is provided an `mode` option which is not a recognized string... { + resolveParentPaths( [ 'package.json' ], { 'mode': 'beep' }, done ); // $ExpectError resolveParentPaths( [ 'package.json' ], { 'mode': 123 }, done ); // $ExpectError resolveParentPaths( [ 'package.json' ], { 'mode': true }, done ); // $ExpectError resolveParentPaths( [ 'package.json' ], { 'mode': false }, done ); // $ExpectError @@ -94,11 +122,14 @@ function done( error: Error | null, path: string | null ): void { { resolveParentPaths(); // $ExpectError resolveParentPaths( [ 'C:\\foo\\bar\\baz' ] ); // $ExpectError + resolveParentPaths( [ 'C:\\foo\\bar\\baz' ], {} ); // $ExpectError + resolveParentPaths( [ 'C:\\foo\\bar\\baz' ], {}, done, {} ); // $ExpectError } // Attached to main export is a `sync` method which returns an array... { resolveParentPaths.sync( [ 'package.json' ] ); // $ExpectType (string | null)[] + resolveParentPaths.sync( [ 'package.json' ], {} ); // $ExpectType (string | null)[] } // The compiler throws an error if the `sync` method is provided a first argument which is not an array of strings... @@ -112,11 +143,27 @@ function done( error: Error | null, path: string | null ): void { resolveParentPaths.sync( ( x: number ): number => x ); // $ExpectError resolveParentPaths.sync( 'beep' ); // $ExpectError resolveParentPaths.sync( [ 1, 2 ] ); // $ExpectError + + resolveParentPaths.sync( 123, {} ); // $ExpectError + resolveParentPaths.sync( false, {} ); // $ExpectError + resolveParentPaths.sync( true, {} ); // $ExpectError + resolveParentPaths.sync( null, {} ); // $ExpectError + resolveParentPaths.sync( undefined, {} ); // $ExpectError + resolveParentPaths.sync( {}, {} ); // $ExpectError + resolveParentPaths.sync( ( x: number ): number => x, {} ); // $ExpectError + resolveParentPaths.sync( 'beep', {} ); // $ExpectError + resolveParentPaths.sync( [ 1, 2 ], {} ); // $ExpectError } // The compiler throws an error if the `sync` method is provided an options argument which is not an object... { + resolveParentPaths.sync( [ 'package.json' ], '5' ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], 5 ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], true ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], false ); // $ExpectError resolveParentPaths.sync( [ 'package.json' ], null ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], [] ); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], ( x: number ): number => x ); // $ExpectError } // The compiler throws an error if the `sync` method is provided an `dir` option which is not a string... @@ -130,8 +177,9 @@ function done( error: Error | null, path: string | null ): void { resolveParentPaths.sync( [ 'package.json' ], { 'dir': ( x: number ): number => x } ); // $ExpectError } -// The compiler throws an error if the `sync` method is provided an `mode` option which is not a string... +// The compiler throws an error if the `sync` method is provided an `mode` option which is not a recognized string... { + resolveParentPaths.sync( [ 'package.json' ], { 'mode': 'beep' } ); // $ExpectError resolveParentPaths.sync( [ 'package.json' ], { 'mode': 123 } ); // $ExpectError resolveParentPaths.sync( [ 'package.json' ], { 'mode': true } ); // $ExpectError resolveParentPaths.sync( [ 'package.json' ], { 'mode': false } ); // $ExpectError @@ -144,4 +192,5 @@ function done( error: Error | null, path: string | null ): void { // The compiler throws an error if the `sync` method is provided an unsupported number of arguments... { resolveParentPaths.sync(); // $ExpectError + resolveParentPaths.sync( [ 'package.json' ], {}, {} ); // $ExpectError } From f41d0f72478e5c467a19579d584f069872164694 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:21:07 -0700 Subject: [PATCH 22/33] bench: fix descriptions --- .../benchmark/benchmark.js | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js index d81987beadb..337cd9726de 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js @@ -28,7 +28,7 @@ var resolveParentPaths = require( './../lib' ); // MAIN // -bench( pkg+':async,first', function benchmark( b ) { +bench( pkg+':mode=first', function benchmark( b ) { var PATHS; var opts; var i; @@ -69,7 +69,7 @@ bench( pkg+':async,first', function benchmark( b ) { } }); -bench( pkg+':async,some', function benchmark( b ) { +bench( pkg+':mode=some', function benchmark( b ) { var PATHS; var opts; var i; @@ -110,7 +110,7 @@ bench( pkg+':async,some', function benchmark( b ) { } }); -bench( pkg+':async,all', function benchmark( b ) { +bench( pkg+':mode=all', function benchmark( b ) { var PATHS; var opts; var i; @@ -150,7 +150,7 @@ bench( pkg+':async,all', function benchmark( b ) { } }); -bench( pkg+':async,each', function benchmark( b ) { +bench( pkg+':mode=each', function benchmark( b ) { var PATHS; var opts; var i; @@ -192,7 +192,7 @@ bench( pkg+':async,each', function benchmark( b ) { } }); -bench( pkg+':sync,first', function benchmark( b ) { +bench( pkg+':sync:mode=first', function benchmark( b ) { var PATHS; var paths; var opts; @@ -218,13 +218,12 @@ bench( pkg+':sync,first', function benchmark( b ) { b.toc(); if ( paths.length === 0 ) { b.fail( 'should return a path' ); - } else { - b.pass( 'benchmark finished' ); } + b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':sync,some', function benchmark( b ) { +bench( pkg+':sync:mode=some', function benchmark( b ) { var PATHS; var paths; var opts; @@ -250,13 +249,12 @@ bench( pkg+':sync,some', function benchmark( b ) { b.toc(); if ( paths.length === 0 ) { b.fail( 'should return a path' ); - } else { - b.pass( 'benchmark finished' ); } + b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':sync,all', function benchmark( b ) { +bench( pkg+':sync:mode=all', function benchmark( b ) { var PATHS; var paths; var opts; @@ -281,13 +279,12 @@ bench( pkg+':sync,all', function benchmark( b ) { b.toc(); if ( paths.length === 0 ) { b.fail( 'should return a path' ); - } else { - b.pass( 'benchmark finished' ); } + b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':sync,each', function benchmark( b ) { +bench( pkg+':sync:mode=each', function benchmark( b ) { var PATHS; var paths; var opts; @@ -314,8 +311,7 @@ bench( pkg+':sync,each', function benchmark( b ) { b.toc(); if ( paths.length === 0 ) { b.fail( 'should return a path' ); - } else { - b.pass( 'benchmark finished' ); } + b.pass( 'benchmark finished' ); b.end(); }); From 4aa5483bdd65ef30d40b871f167469e80a53c81c Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:47:43 -0700 Subject: [PATCH 23/33] fix: print results as newline delimited results and update tests --- .../@stdlib/fs/resolve-parent-paths/bin/cli | 7 ++- .../fs/resolve-parent-paths/test/test.cli.js | 58 +++++++++---------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli index 8de501a7a93..acb2123a871 100755 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli @@ -78,10 +78,15 @@ function main() { * @returns {void} */ function onPaths( error, paths ) { + var i; if ( error ) { return cli.error( error ); } - console.log( paths ); // eslint-disable-line no-console + for ( i = 0; i < paths.length; i++ ) { + if ( paths[ i ] ) { + console.log( paths[ i ] ); // eslint-disable-line no-console + } + } } } diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js index 1f4cc082a3b..5251e659106 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js @@ -25,7 +25,9 @@ var exec = require( 'child_process' ).exec; var tape = require( 'tape' ); var replace = require( '@stdlib/string/replace' ); var trim = require( '@stdlib/string/trim' ); +var RE_EOL = require( '@stdlib/regexp/eol' ).REGEXP; var isAbsolutePath = require( '@stdlib/assert/is-absolute-path' ); +var contains = require( '@stdlib/array/base/assert/contains' ); var IS_BROWSER = require( '@stdlib/assert/is-browser' ); var IS_WINDOWS = require( '@stdlib/assert/is-windows' ); var EXEC_PATH = require( '@stdlib/process/exec-path' ); @@ -38,7 +40,6 @@ var fpath = resolve( __dirname, '..', 'bin', 'cli' ); var opts = { 'skip': IS_BROWSER || IS_WINDOWS }; -var EXTRA_LINES = 3; // square brackets + empty line // FIXTURES // @@ -145,7 +146,7 @@ tape( 'when invoked with a `-V` flag, the command-line interface prints the vers } }); -tape( 'the command-line interface resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { +tape( 'the command-line interface resolves the first path match from a set of paths by walking parent directories (mode=first)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, @@ -160,15 +161,14 @@ tape( 'the command-line interface resolves the first path match from a set of pa function done( error, stdout, stderr ) { var actual; - var str; if ( error ) { t.fail( error.message ); } else { - actual = stdout.split( '\n' ); - t.strictEqual( actual.length - EXTRA_LINES, 1, 'prints expected number of paths' ); + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 1, 'returns expected value' ); - str = trim( actual[ 1 ] ).slice( 1, -1 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( actual[ 0 ], resolve( __dirname, '..', 'package.json' ), 'returns expected value' ); t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); } @@ -176,7 +176,7 @@ tape( 'the command-line interface resolves the first path match from a set of pa } }); -tape( 'the command-line interface resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { +tape( 'the command-line interface resolves one or more paths from a set of paths at a directory level by walking parent directories (mode=some)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, @@ -192,18 +192,17 @@ tape( 'the command-line interface resolves one or more paths from a set of paths function done( error, stdout, stderr ) { var actual; - var str; if ( error ) { t.fail( error.message ); } else { - actual = stdout.split( '\n' ); - t.strictEqual( actual.length - EXTRA_LINES, 2, 'prints expected number of paths' ); + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 2, 'returns expected value' ); - str = trim( actual[ 1 ] ).slice( 1, -2 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( contains( actual, resolve( __dirname, '..', 'package.json' ) ), true, 'returns expected value' ); - str = trim( actual[ 2 ] ).slice( 1, -1 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 1 ] ), true, 'returns expected value' ); + t.strictEqual( contains( actual, resolve( __dirname, '..', 'README.md' ) ), true, 'returns expected value' ); t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); } @@ -211,7 +210,7 @@ tape( 'the command-line interface resolves one or more paths from a set of paths } }); -tape( 'the command-line interface resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { +tape( 'the command-line interface resolves all paths from a set of paths at a directory level by walking parent directories (mode=all)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, @@ -226,18 +225,17 @@ tape( 'the command-line interface resolves all paths from a set of paths at a di function done( error, stdout, stderr ) { var actual; - var str; if ( error ) { t.fail( error.message ); } else { - actual = stdout.split( '\n' ); - t.strictEqual( actual.length - EXTRA_LINES, 2, 'prints expected number of paths' ); + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 2, 'returns expected value' ); - str = trim( actual[ 1 ] ).slice( 1, -2 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( actual[ 0 ], resolve( __dirname, '..', 'package.json' ), 'returns expected value' ); - str = trim( actual[ 2 ] ).slice( 1, -1 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 1 ] ), true, 'returns expected value' ); + t.strictEqual( actual[ 1 ], resolve( __dirname, '..', 'README.md' ), 'returns expected value' ); t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); } @@ -245,7 +243,7 @@ tape( 'the command-line interface resolves all paths from a set of paths at a di } }); -tape( 'the command-line interface resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { +tape( 'the command-line interface resolves each path from a set of paths by walking parent directories (mode=each)', opts, function test( t ) { var cmd = [ EXEC_PATH, fpath, @@ -260,18 +258,16 @@ tape( 'the command-line interface resolves each path from a set of paths by walk function done( error, stdout, stderr ) { var actual; - var str; if ( error ) { t.fail( error.message ); } else { - actual = stdout.split( '\n' ); - t.strictEqual( actual.length - EXTRA_LINES, 2, 'prints expected number of paths' ); + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 2, 'returns expected value' ); - str = trim( actual[ 1 ] ).slice( 1, -2 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( actual[ 0 ], resolve( __dirname, '..', 'package.json' ), 'returns expected value' ); - str = trim( actual[ 2 ] ).slice( 1, -1 ); - t.strictEqual( isAbsolutePath( str ), true, 'prints contents to `stdout`' ); + t.strictEqual( isAbsolutePath( actual[ 1 ] ), true, 'returns expected value' ); t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' ); } From 19ae5d18c91a58543431c98bca89b83be5572750 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:49:23 -0700 Subject: [PATCH 24/33] test: update test messages --- .../fs/resolve-parent-paths/test/test.validate.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js index 0d1648f5a84..fbb6a8425a2 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js @@ -57,7 +57,7 @@ tape( 'if provided an `options` argument which is not an `object`, the function t.end(); }); -tape( 'if provided a `dir` option which is not a `string`, the function returns a type error', function test( t ) { +tape( 'if provided a `dir` option which is not a string, the function returns a type error', function test( t ) { var values; var opts; var err; @@ -124,9 +124,9 @@ tape( 'the function returns `null` if all options are valid', function test( t ) obj = {}; err = validate( obj, opts ); - t.equal( err, null, 'returns null' ); - t.equal( obj.dir, opts.dir, 'sets dir option' ); - t.equal( obj.mode, opts.mode, 'sets mode option' ); + t.equal( err, null, 'returns expected value' ); + t.equal( obj.dir, opts.dir, 'returns expected value' ); + t.equal( obj.mode, opts.mode, 'returns expected value' ); t.end(); }); @@ -144,8 +144,8 @@ tape( 'the function ignores unsupported/unrecognized options', function test( t obj = {}; err = validate( obj, opts ); - t.equal( err, null, 'returns null' ); - t.deepEqual( obj, {}, 'does not set any options' ); + t.equal( err, null, 'returns expected value' ); + t.deepEqual( obj, {}, 'returns expected value' ); t.end(); }); From f2b29cfb93c4bc8cf2a05fab3ac03b0d8d2c214b Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:53:31 -0700 Subject: [PATCH 25/33] docs: update copy --- .../@stdlib/fs/resolve-parent-paths/README.md | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md index 300646cd5b0..76c1d14a7ab 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md @@ -18,7 +18,7 @@ limitations under the License. --> -# Resolve Parent Paths +# resolveParentPaths > Resolve paths from a set of paths by walking parent directories. @@ -54,19 +54,38 @@ The function accepts the following `options`: - **mode**: mode of operation. The following modes are supported: - - `first`: first resolved path is returned. - - `some`: first set of paths resolved at a directory level are returned. - - `all`: all paths resolved at a directory level are returned. - - `each`: each path resolved at any directory level is returned. + - `first`: return the first resolved path. + - `some`: return one or more paths resolved within the first directory level containing a match. + - `all`: return all resolved paths within the first directory level containing matches for all provided paths. + - `each`: independently return the first resolved path for each path at any directory level. + + Default: `'all'`. -By default, the function begins walking from the current working directory in `all` mode. To specify an alternative directory, set the `dir` and/or `mode` option. +By default, the function begins walking from the current working directory. To specify an alternative directory, set the `dir` option. + +```javascript +var opts = { + 'dir': __dirname +}; +resolveParentPaths( [ 'package.json' ], opts, onPaths ); + +function onPaths( error, paths ) { + if ( error ) { + throw error; + } + console.log( paths ); + // => '...' +} +``` + +By default, the function requires that a directory contains matches for all provided paths before returning results. To specify an alternative operation mode, set the `mode` option. ```javascript var opts = { 'dir': __dirname, 'mode': 'first' }; -resolveParentPaths( [ 'package.json' ], opts, onPaths ); +resolveParentPaths( [ 'package.json', 'package-lock.json' ], opts, onPaths ); function onPaths( error, paths ) { if ( error ) { @@ -96,7 +115,7 @@ The function accepts the same `options` as [`resolveParentPaths()`](#resolve-par ## Notes -- In `some` mode, the return order of resolved paths is not guaranteed when using asynchronously. +- In `some` mode, the return order of asynchronously resolved paths is not guaranteed. - This implementation is **not** similar in functionality to core [`path.resolve`][node-core-path-resolve]. The latter performs string manipulation to generate a full path. This implementation walks parent directories to perform a **search**, thereby touching the file system. Accordingly, this implementation resolves _real_ absolute file paths and is intended for use when a target's location in a parent directory is unknown relative to a child directory; e.g., when wanting to find a package root from deep within a package directory. @@ -190,8 +209,6 @@ $ resolve-parent-paths package.json package-lock.json From 8b6abeaf2179c41dd789730b1bee2f991bece06e Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 17:55:00 -0700 Subject: [PATCH 26/33] test: fix overwriting of options object --- .../@stdlib/fs/resolve-parent-paths/test/test.sync.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js index 0cb0151b7f4..be329f5cf36 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -162,9 +162,6 @@ tape( 'the function resolves paths from a set of paths by walking parent directo var base; var dir; - opts = { - 'mode': 'first' - }; dir = cwd(); base = basename( dir ); From 94750025d8b2585bf79cfceceeecba3482146b93 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 18:04:11 -0700 Subject: [PATCH 27/33] refactor: allow empty arrays and update tests --- .../fs/resolve-parent-paths/lib/sync.js | 4 + .../fs/resolve-parent-paths/test/test.sync.js | 138 ++++++++++-------- 2 files changed, 79 insertions(+), 63 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js index deca4ac7aa3..0c99f550a81 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -22,6 +22,7 @@ var resolve = require( 'path' ).resolve; var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var isArrayLikeObject = require( '@stdlib/assert/is-array-like-object' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ).sync; var filled = require( '@stdlib/array/base/filled' ); @@ -201,6 +202,9 @@ function resolveParentPaths( paths, options ) { var err; if ( !isStringArray( paths ) ) { + if ( isArrayLikeObject( paths ) && paths.length === 0 ) { + return []; + } throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); } opts = {}; diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js index be329f5cf36..034d91c2e0e 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -24,6 +24,7 @@ var resolve = require( 'path' ).resolve; var basename = require( 'path' ).basename; var tape = require( 'tape' ); var IS_BROWSER = require( '@stdlib/assert/is-browser' ); +var isArray = require( '@stdlib/assert/is-array' ); var cwd = require( '@stdlib/process/cwd' ); var resolveParentPaths = require( './../lib/sync.js' ); @@ -167,8 +168,8 @@ tape( 'the function resolves paths from a set of paths by walking parent directo expected = dir; actual = resolveParentPaths( [ base ] ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); t.end(); }); @@ -182,17 +183,17 @@ tape( 'the function resolves paths from a set of paths by walking parent directo opts = { 'dir': __dirname }; - dir = resolve( __dirname, '../package.json' ); + dir = resolve( __dirname, '..', 'package.json' ); expected = dir; actual = resolveParentPaths( [ 'package.json' ], opts ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); t.end(); }); -tape( 'the function resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { +tape( 'the function resolves the first path match from a set of paths by walking parent directories (mode=first)', opts, function test( t ) { var expected; var actual; var opts; @@ -202,164 +203,175 @@ tape( 'the function resolves the first path match from a set of paths by walking 'dir': __dirname, 'mode': 'first' }; - dir = resolve( __dirname, '../package.json' ); + dir = resolve( __dirname, '..', 'package.json' ); expected = dir; actual = resolveParentPaths( [ 'package.json' ], opts ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); t.end(); }); -tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { +tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (mode=some)', opts, function test( t ) { var actual; var opts; - var dir1; - var dir2; + var v1; + var v2; opts = { 'dir': __dirname, 'mode': 'some' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../README.md' ); + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', 'README.md' ); actual = resolveParentPaths( [ 'package.json' ], opts ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); - t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v2, 'returns expected value' ); t.end(); }); -tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { +tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (mode=all)', opts, function test( t ) { var actual; var opts; - var dir1; - var dir2; + var v1; + var v2; opts = { 'dir': __dirname, 'mode': 'all' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../README.md' ); + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', 'README.md' ); actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); - t.strictEqual( actual.length, 0, 'returns expected number of paths' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); - t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v2, 'returns expected value' ); t.end(); }); -tape( 'the function resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { +tape( 'the function resolves each path from a set of paths by walking parent directories (mode=each)', opts, function test( t ) { var actual; var opts; - var dir1; - var dir2; + var v1; + var v2; opts = { 'dir': __dirname, 'mode': 'each' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../../resolve-parent-paths' ); + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', '..', 'resolve-parent-paths' ); actual = resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts ); - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); t.strictEqual( actual[ 0 ], null, 'returns expected value' ); - t.strictEqual( actual[ 1 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], v1, 'returns expected value' ); actual = resolveParentPaths( [ 'package.json', 'resolve-parent-paths' ], opts ); - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); - t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v2, 'returns expected value' ); t.end(); }); -tape( 'the function returns an empty array if unable to resolve a parent path (`first` mode)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (mode=first)', opts, function test( t ) { var actual; var opts; opts = { 'mode': 'first' }; + + actual = resolveParentPaths( [], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); - t.strictEqual( actual.length, 0, 'returns empty array' ); t.end(); }); -tape( 'the function returns an empty array if unable to resolve a parent path (`some` mode)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (mode=some)', opts, function test( t ) { var actual; var opts; opts = { 'mode': 'some' }; + + actual = resolveParentPaths( [], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); - t.strictEqual( actual.length, 0, 'returns empty array' ); t.end(); }); -tape( 'the function returns an empty array if unable to resolve a parent path (`all` mode)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (mode=all)', opts, function test( t ) { var actual; var opts; opts = { 'mode': 'all' }; + + actual = resolveParentPaths( [], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); + actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); - t.strictEqual( actual.length, 0, 'returns empty array' ); t.end(); }); -tape( 'the function returns a `null` array if unable to resolve a parent path (`each` mode)', opts, function test( t ) { +tape( 'the function returns an array of `null` values if unable to resolve a parent path (mode=each)', opts, function test( t ) { var actual; var opts; opts = { 'mode': 'each' }; - actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); - t.strictEqual( actual[ 0 ], null, 'returns expected value' ); - t.end(); -}); - -tape( 'the function returns an empty array if unable to resolve a parent path (options)', opts, function test( t ) { - var actual; - var opts; + actual = resolveParentPaths( [], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); - opts = { - 'dir': __dirname - }; actual = resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); - t.strictEqual( actual.length, 0, 'returns empty array' ); t.end(); }); From 6362a0693148b5d7f7d831a2e57e0db6d2637ba9 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 18:05:25 -0700 Subject: [PATCH 28/33] refactor: allow empty arrays --- lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js index c34b50435fc..37ed75185df 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js @@ -22,6 +22,7 @@ var resolve = require( 'path' ).resolve; var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var isArrayLikeObject = require( '@stdlib/assert/is-array-like-object' ); var isFunction = require( '@stdlib/assert/is-function' ); var cwd = require( '@stdlib/process/cwd' ); var exists = require( '@stdlib/fs/exists' ); @@ -387,6 +388,9 @@ function resolveParentPaths( paths, options, clbk ) { var err; if ( !isStringArray( paths ) ) { + if ( isArrayLikeObject( paths ) && paths.length === 0 ) { + return []; + } throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', paths ) ); } opts = {}; From 7ea07482ee1aa2dc5f41db07962bf7685fc41e62 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 19:12:47 -0700 Subject: [PATCH 29/33] test: fix overwriting of options --- .../@stdlib/fs/resolve-parent-paths/test/test.main.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js index 0996b8057b5..bfa0faa3a68 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js @@ -217,9 +217,6 @@ tape( 'the function resolves paths from a set of paths by walking parent directo var base; var dir; - opts = { - 'mode': 'first' - }; dir = cwd(); base = basename( dir ); From acb942904bf0af241ce7658d79de991006b7c4e9 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 19:13:43 -0700 Subject: [PATCH 30/33] test: fix invocation --- .../@stdlib/fs/resolve-parent-paths/test/test.main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js index bfa0faa3a68..54dae60b4d1 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js @@ -221,7 +221,7 @@ tape( 'the function resolves paths from a set of paths by walking parent directo base = basename( dir ); expected = dir; - resolveParentPaths( [ base ], opts, onPaths ); + resolveParentPaths( [ base ], onPaths ); function onPaths( error, actual ) { if ( error ) { From bdc42bafadb5e8776256109bd7192bcee5e25fce Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 19:18:48 -0700 Subject: [PATCH 31/33] test: fix overwriting of options --- .../fs/resolve-parent-paths/test/test.main.js | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js index 54dae60b4d1..dae73389922 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js @@ -227,8 +227,8 @@ tape( 'the function resolves paths from a set of paths by walking parent directo if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); t.end(); } }); @@ -240,7 +240,7 @@ tape( 'the function resolves a path from a set of paths by walking parent direct opts = { 'dir': __dirname }; - expected = resolve( __dirname, '../package.json' ); + expected = resolve( __dirname, '..', 'package.json' ); resolveParentPaths( [ 'package.json' ], opts, onPaths ); @@ -248,13 +248,14 @@ tape( 'the function resolves a path from a set of paths by walking parent direct if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], expected, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); t.end(); } }); -tape( 'the function resolves the first path match from a set of paths by walking parent directories (`first` mode)', opts, function test( t ) { +tape( 'the function resolves the first path match from a set of paths by walking parent directories (mode=first)', opts, function test( t ) { + var opts; var dir; var FLG; @@ -263,7 +264,7 @@ tape( 'the function resolves the first path match from a set of paths by walking 'dir': __dirname, 'mode': 'first' }; - dir = resolve( __dirname, '../package.json' ); + dir = resolve( __dirname, '..', 'package.json' ); resolveParentPaths( [ 'package.json' ], opts, onPaths ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths ); @@ -273,8 +274,8 @@ tape( 'the function resolves the first path match from a set of paths by walking if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], dir, 'returns expected value' ); FLG += 1; if ( FLG === 3 ) { @@ -283,18 +284,19 @@ tape( 'the function resolves the first path match from a set of paths by walking } }); -tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (`some` mode)', opts, function test( t ) { - var dir1; - var dir2; +tape( 'the function resolves one or more paths from a set of paths at a directory level by walking parent directories (mode=some)', opts, function test( t ) { + var opts; var FLG; + var v1; + var v2; FLG = 0; opts = { 'dir': __dirname, 'mode': 'some' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../README.md' ); + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', 'README.md' ); resolveParentPaths( [ 'package.json' ], opts, onPaths1 ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths1 ); @@ -304,8 +306,8 @@ tape( 'the function resolves one or more paths from a set of paths at a director if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 1, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); FLG += 1; if ( FLG === 3 ) { @@ -317,9 +319,9 @@ tape( 'the function resolves one or more paths from a set of paths at a director if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( contains( actual, dir1 ), true, 'returns path' ); - t.strictEqual( contains( actual, dir2 ), true, 'returns path' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( contains( actual, v1 ), true, 'returns expected value' ); + t.strictEqual( contains( actual, v2 ), true, 'returns expected value' ); FLG += 1; if ( FLG === 3 ) { @@ -328,18 +330,19 @@ tape( 'the function resolves one or more paths from a set of paths at a director } }); -tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (`all` mode)', opts, function test( t ) { - var dir1; - var dir2; +tape( 'the function resolves all paths from a set of paths at a directory level by walking parent directories (mode=all)', opts, function test( t ) { + var opts; var FLG; + var v1; + var v2; FLG = 0; opts = { 'dir': __dirname, 'mode': 'all' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../README.md' ); + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', 'README.md' ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPathsPositive ); @@ -348,7 +351,7 @@ tape( 'the function resolves all paths from a set of paths at a directory level if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 0, 'returns expected number of paths' ); + t.strictEqual( actual.length, 0, 'returns expected value' ); FLG += 1; if ( FLG === 2 ) { @@ -360,9 +363,9 @@ tape( 'the function resolves all paths from a set of paths at a directory level if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); - t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v2, 'returns expected value' ); FLG += 1; if ( FLG === 2 ) { @@ -371,18 +374,19 @@ tape( 'the function resolves all paths from a set of paths at a directory level } }); -tape( 'the function resolves each path from a set of paths by walking parent directories (`each` mode)', opts, function test( t ) { - var dir1; - var dir2; +tape( 'the function resolves each path from a set of paths by walking parent directories (mode=each)', opts, function test( t ) { + var opts; var FLG; + var v1; + var v2; FLG = 0; opts = { 'dir': __dirname, 'mode': 'each' }; - dir1 = resolve( __dirname, '../package.json' ); - dir2 = resolve( __dirname, '../../resolve-parent-paths' ); + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', '..', 'resolve-parent-paths' ); resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPathsNegative ); resolveParentPaths( [ 'package.json', 'resolve-parent-paths' ], opts, onPathsPositive ); @@ -391,9 +395,9 @@ tape( 'the function resolves each path from a set of paths by walking parent dir if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); t.strictEqual( actual[ 0 ], null, 'returns expected value' ); - t.strictEqual( actual[ 1 ], dir1, 'returns path' ); + t.strictEqual( actual[ 1 ], v1, 'returns expected value' ); FLG += 1; if ( FLG === 2 ) { @@ -405,9 +409,9 @@ tape( 'the function resolves each path from a set of paths by walking parent dir if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 2, 'returns expected number of paths' ); - t.strictEqual( actual[ 0 ], dir1, 'returns path' ); - t.strictEqual( actual[ 1 ], dir2, 'returns path' ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v2, 'returns expected value' ); FLG += 1; if ( FLG === 2 ) { @@ -416,7 +420,7 @@ tape( 'the function resolves each path from a set of paths by walking parent dir } }); -tape( 'the function returns an empty array if unable to resolve a parent path (`first` mode)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (mode=first)', opts, function test( t ) { var opts; opts = { @@ -433,7 +437,7 @@ tape( 'the function returns an empty array if unable to resolve a parent path (` } }); -tape( 'the function returns an empty array if unable to resolve a parent path (`some` mode)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (mode=some)', opts, function test( t ) { var opts; opts = { @@ -450,7 +454,7 @@ tape( 'the function returns an empty array if unable to resolve a parent path (` } }); -tape( 'the function returns an empty array if unable to resolve a parent path (`all` mode)', opts, function test( t ) { +tape( 'the function returns an empty array if unable to resolve a parent path (mode=all)', opts, function test( t ) { var opts; opts = { @@ -467,7 +471,7 @@ tape( 'the function returns an empty array if unable to resolve a parent path (` } }); -tape( 'the function returns a `null` array if unable to resolve a parent path (`each` mode)', opts, function test( t ) { +tape( 'the function returns a `null` array if unable to resolve a parent path (mode=each)', opts, function test( t ) { var opts; opts = { From 60f45ba749b6211112fd5908419e7bb7523c4b03 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 19:23:23 -0700 Subject: [PATCH 32/33] test: add test cases --- .../fs/resolve-parent-paths/test/test.main.js | 100 ++++++++++++++---- 1 file changed, 79 insertions(+), 21 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js index dae73389922..eac3b22e420 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js @@ -422,84 +422,142 @@ tape( 'the function resolves each path from a set of paths by walking parent dir tape( 'the function returns an empty array if unable to resolve a parent path (mode=first)', opts, function test( t ) { var opts; + var FLG; + FLG = 0; opts = { 'mode': 'first' }; - resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + resolveParentPaths( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); + t.end(); - function onPaths( error, actual ) { + function onPaths1( error, actual ) { if ( error ) { t.ok( false, error.message ); } t.strictEqual( actual.length, 0, 'returns empty array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } + } + + function onPaths2( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns empty array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } }); tape( 'the function returns an empty array if unable to resolve a parent path (mode=some)', opts, function test( t ) { var opts; + var FLG; + FLG = 0; opts = { 'mode': 'some' }; - resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + resolveParentPaths( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); t.end(); - function onPaths( error, actual ) { + function onPaths1( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns empty array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } + } + + function onPaths2( error, actual ) { if ( error ) { t.ok( false, error.message ); } t.strictEqual( actual.length, 0, 'returns empty array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } }); tape( 'the function returns an empty array if unable to resolve a parent path (mode=all)', opts, function test( t ) { var opts; + var FLG; + FLG = 0; opts = { 'mode': 'all' }; - resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + resolveParentPaths( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); t.end(); - function onPaths( error, actual ) { + function onPaths1( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns empty array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } + } + + function onPaths2( error, actual ) { if ( error ) { t.ok( false, error.message ); } t.strictEqual( actual.length, 0, 'returns empty array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } }); -tape( 'the function returns a `null` array if unable to resolve a parent path (mode=each)', opts, function test( t ) { +tape( 'the function returns an array of `null` values if unable to resolve a parent path (mode=each)', opts, function test( t ) { var opts; + var FLG; + FLG = 0; opts = { 'mode': 'each' }; - resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths ); + resolveParentPaths( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); t.end(); - function onPaths( error, actual ) { + function onPaths1( error, actual ) { if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 1, 'returns expected array' ); - t.strictEqual( actual[ 0 ], null, 'returns expected value' ); + t.strictEqual( actual.length, 0, 'returns expected array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } -}); - -tape( 'the function returns an empty array if unable to resolve a parent path (options)', opts, function test( t ) { - var opts = { - 'dir': __dirname - }; - resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPath ); - t.end(); - function onPath( error, actual ) { + function onPaths2( error, actual ) { if ( error ) { t.ok( false, error.message ); } - t.strictEqual( actual.length, 0, 'returns empty array' ); + t.strictEqual( actual.length, 1, 'returns expected array' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } } }); From 35c6374728285b02d5a5a09d2580677388bbdb3e Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Thu, 18 Jul 2024 19:27:51 -0700 Subject: [PATCH 33/33] refactor: remove unused code path --- .../@stdlib/fs/resolve-parent-paths/lib/main.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js index 37ed75185df..b7b5b8f2e8c 100644 --- a/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js @@ -278,12 +278,10 @@ function each( paths, dir, done ) { var count; var child; var spath; - var FLG; var out; var i; count = 0; // initialize counter to track if we are done resolving all paths - FLG = 0; // initialize flag to check if we are done resolving all paths out = filled( null, paths.length ); // Start at a base directory and continue moving up through each parent directory... @@ -300,13 +298,7 @@ function each( paths, dir, done ) { */ function next() { count += 1; - - // Check if we have resolved all paths... if ( count === paths.length ) { - if ( FLG ) { - return; - } - FLG = true; return done( null, out ); } }