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 000000000000..76c1d14a7ab0 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/README.md @@ -0,0 +1,228 @@ + + +# resolveParentPaths + +> Resolve paths 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 paths from a set of paths by walking parent directories. + +```javascript +resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); + +function onPaths( error, paths ) { + if ( error ) { + throw error; + } + console.log( paths ); + // => '...' +} +``` + +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`: 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. 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', 'package-lock.json' ], opts, onPaths ); + +function onPaths( error, paths ) { + if ( error ) { + throw error; + } + console.log( paths ); + // => '...' +} +``` + +#### resolveParentPaths.sync( paths\[, options] ) + +Synchronously resolves paths from a set of paths by walking parent directories. + +```javascript +var paths = resolveParentPaths.sync( [ 'package.json', 'README.md' ] ); +// returns [ '...', '...' ] +``` + +The function accepts the same `options` as [`resolveParentPaths()`](#resolve-parent-paths). + +
+ + + +
+ +## Notes + +- 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. + +
+ + + +
+ +## Examples + + + +```javascript +var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); + +var opts = { + 'dir': __dirname +}; + +/* Sync */ + +var out = resolveParentPaths.sync( [ 'package.json', 'README.md' ], opts ); +// returns [ '...', '...' ] + +out = resolveParentPaths.sync( [ 'non_existent_basename' ], opts ); +// returns [] + +opts.mode = 'first'; +out = resolveParentPaths.sync( [ 'non_existent_basename', 'package.json' ], opts ); +// returns [ '...' ] + +/* Async */ + +resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); +resolveParentPaths( [ './../non_existent_path' ], onPaths ); + +function onPaths( error, paths ) { + if ( error ) { + throw error; + } + console.log( paths ); +} +``` + +
+ + + +* * * + +
+ +## 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. + --mode mode Mode of operation. +``` + +
+ + + +
+ +### 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 000000000000..337cd9726ded --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/benchmark/benchmark.js @@ -0,0 +1,317 @@ +/** +* @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 basename = require( 'path' ).basename; +var bench = require( '@stdlib/bench' ); +var pkg = require( './../package.json' ).name; +var resolveParentPaths = require( './../lib' ); + + +// MAIN // + +bench( pkg+':mode=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' + }; + + 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+':mode=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, + 'mode': 'some' + }; + + 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+':mode=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+':mode=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 ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + next(); + } +}); + +bench( pkg+':sync:mode=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' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':sync:mode=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' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':sync:mode=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' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':sync:mode=each', function benchmark( b ) { + var PATHS; + 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' + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + paths = resolveParentPaths.sync( PATHS[ i % 4 ], opts ); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + } + b.toc(); + if ( paths.length === 0 ) { + b.fail( 'should return a path' ); + } + 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 000000000000..acb2123a871e --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/bin/cli @@ -0,0 +1,93 @@ +#!/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; + } + 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} paths - resolved paths + * @returns {void} + */ + function onPaths( error, paths ) { + var i; + if ( error ) { + return cli.error( error ); + } + for ( i = 0; i < paths.length; i++ ) { + if ( paths[ i ] ) { + console.log( paths[ i ] ); // 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 000000000000..c46cf73a964c --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/repl.txt @@ -0,0 +1,84 @@ + +{{alias}}( paths[, options], clbk ) + Asynchronously resolves paths from a set of paths by walking parent + directories. + + Parameters + ---------- + paths: Array + Paths to resolve. + + options: Object (optional) + Options. + + options.dir: string (optional) + Base directory from which to search. Default: current working directory. + + options.mode: string (optional) + 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. + + Examples + -------- + > function onPaths( error, paths ) { + ... if ( error ) { + ... console.error( error.message ); + ... } else { + ... console.log( paths ); + ... } + ... }; + > {{alias}}( [ 'package.json', 'package-lock.json' ], onPaths ); + + +{{alias}}.sync( paths[, options] ) + Synchronously resolves paths from a set of paths by walking parent + directories. + + Parameters + ---------- + paths: Array + Paths to resolve. + + options: Object (optional) + Options. + + options.dir: string (optional) + Base directory from which to search. Default: current working directory. + + options.mode: string (optional) + 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 + ------- + out: Array + Resolved paths. + + 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 000000000000..43a5b5ddafa5 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/index.d.ts @@ -0,0 +1,145 @@ +/* +* @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; + + /** + * 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?: 'first' | 'some' | 'all' | 'each'; +} + +/** +* Callback invoked after resolving paths. +* +* @param err - error argument +* @param paths - resolved paths +*/ +type Callback = ( err: Error | null, paths: Array ) => void; + +/** +* Interface for resolving paths from a set of paths by walking parent directories. +*/ +interface ResolveParentPaths { + /** + * Asynchronously resolves paths from a set of paths by walking parent directories. + * + * @param paths - path to resolve + * @param options - function options + * @param options.dir - base directory + * @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, 'mode': 'some' }, onPaths ); + * + * function onPaths( error, paths ) { + * if ( error ) { + * throw error; + * } + * console.log( paths ); + * } + */ + ( paths: Array, options: Options, clbk: Callback ): void; + + /** + * Asynchronously resolves paths from a set of paths by walking parent directories. + * + * @param paths - path to resolve + * @param clbk - callback to invoke after resolving paths + * + * @example + * resolveParentPaths( [ 'package.json', 'package-lock.json' ], onPaths ); + * + * function onPaths( error, paths ) { + * if ( error ) { + * throw error; + * } + * console.log( paths ); + * } + */ + ( paths: Array, clbk: Callback ): void; + + /** + * Synchronously resolves paths from a set of paths by walking parent directories. + * + * @param paths - paths to resolve + * @param options - function options + * @param options.dir - base directory + * @param options.mode - mode of operation + * @throws must provide valid options + * @returns resolved paths + * + * @example + * var paths = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ], { 'dir': __dirname, 'mode': 'some' } ); + */ + sync( paths: Array, options?: Options ): Array; +} + +/** +* Asynchronously resolves paths from a set of paths by walking parent directories. +* +* @param paths - paths to resolve +* @param options - function options +* @param options.dir - base directory +* @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' ], onPaths ); +* +* function onPaths( error, paths ) { +* if ( error ) { +* throw error; +* } +* console.log( paths ); +* } +* +* @example +* var paths = 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 000000000000..9ebce5f12af4 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/types/test.ts @@ -0,0 +1,196 @@ +/* +* @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' ); + +/** +* Callback function. +* +* @param error - error object +* @param path - resolved path +*/ +function done( error: Error | null, paths: Array ): void { + if ( error || paths === null ) { + throw error; + } +} + + +// TESTS // + +// 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... +{ + 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 + + 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 + + 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... +{ + 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 `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 + 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 + 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... +{ + 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 + + 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... +{ + 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 `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 + 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 + resolveParentPaths.sync( [ 'package.json' ], {}, {} ); // $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 000000000000..b0b99674f53a --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/docs/usage.txt @@ -0,0 +1,10 @@ + +Usage: resolve-parent-paths [options] [...] + +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 new file mode 100644 index 000000000000..68f423bede76 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/etc/cli_opts.json @@ -0,0 +1,18 @@ +{ + "string": [ + "dir", + "mode" + ], + "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 000000000000..c95bbb380bc8 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/examples/index.js @@ -0,0 +1,52 @@ +/** +* @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', 'README.md' ], opts ); +console.log( out ); +// => [ '...', '...' ] + +out = resolveParentPaths.sync( [ 'non_existent_basename', 'package.json' ], opts ); +console.log( out ); +// => [] + +opts.mode = 'first'; +out = resolveParentPaths.sync( [ 'non_existent_basename', 'package.json' ], opts ); +console.log( out ); +// => [ '...' ] + +/* Async */ + +resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); +resolveParentPaths( [ './../non_existent_path' ], onPaths ); + +function onPaths( error, paths ) { + if ( error ) { + throw error; + } + console.log( paths ); +} 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 000000000000..a118ad53b2d3 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/index.js @@ -0,0 +1,60 @@ +/** +* @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 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' ], onPaths ); +* +* function onPaths( error, paths ) { +* if ( error ) { +* throw error; +* } +* console.log( paths ); +* } +* +* @example +* var resolveParentPaths = require( '@stdlib/fs/resolve-parent-paths' ); +* +* var paths = resolveParentPaths.sync( [ 'package.json', 'package-lock.json' ] ); +*/ + +// MODULES // + +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var main = require( './main.js' ); +var sync = require( './sync.js' ); + + +// MAIN // + +setReadOnly( main, 'sync', sync ); + + +// EXPORTS // + +module.exports = main; + +// exports: { "sync": "main.sync" } 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 new file mode 100644 index 000000000000..b7b5b8f2e8cd --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/main.js @@ -0,0 +1,415 @@ +/** +* @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 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' ); +var filled = require( '@stdlib/array/base/filled' ); +var format = require( '@stdlib/string/format' ); +var validate = require( './validate.js' ); + + +// VARIABLES // + +var MODES = { + 'first': first, + 'some': some, + 'all': all, + 'each': each +}; + + +// FUNCTIONS // + +/** +* Asynchronously resolves the first path match from a set of paths by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths +* @returns {void} +*/ +function first( paths, dir, done ) { + var child; + var spath; + var idx; + var out; + + out = []; + + // Start at a base directory and continue moving up through each parent directory... + spath = resolve( dir, paths[ 0 ] ); + + idx = 1; // index of next path + 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 + 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, '..' ); + + // 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 ] ); + idx += 1; + exists( spath, onExists ); + } +} + +/** +* 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 +* @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 FLG; + var out; + + 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... + 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 ) ); + } + } + + /** + * Returns a callback to be invoked upon checking for path existence. + * + * @private + * @param {string} spath - resolved path + * @returns {Callback} callback + */ + function getCallback( 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 + if ( bool ) { + out.push( spath ); + } + FLG += 1; + if ( FLG === paths.length ) { + // Check if we have resolved any paths... + 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: + return next( dir ); + } + } + } +} + +/** +* Asynchronously resolves all paths from a set of paths at a directory level by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths +* @returns {void} +*/ +function all( paths, dir, done ) { + var count; + var child; + var spath; + var FLG; + var out; + + 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... + 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 ) ); + } + } + + /** + * 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( 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 + if ( bool ) { + out[ idx ] = spath; + count += 1; + } + 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: + return next( dir ); + } + } + } +} + +/** +* Asynchronously resolves each path from a set of paths by walking parent directories. +* +* @private +* @param {Array} paths - paths to resolve +* @param {string} dir - base directory +* @param {Callback} done - callback to invoke after resolving paths +* @returns {void} +*/ +function each( paths, dir, done ) { + var count; + var child; + var spath; + var out; + var i; + + count = 0; // initialize counter to track 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... + for ( i = 0; i < paths.length; i++ ) { + spath = resolve( dir, paths[ i ] ); + exists( spath, getCallback( i, spath, dir ) ); + } + + /** + * Determines whether all paths have been resolved. + * + * @private + * @returns {void} + */ + function next() { + count += 1; + if ( count === paths.length ) { + return done( null, out ); + } + } + + /** + * Returns a callback to be invoked upon checking for path existence. + * + * @private + * @param {NonNegativeInteger} idx - index + * @param {string} spath - resolved path + * @param {string} dir - base directory + * @returns {Callback} callback + */ + function getCallback( idx, spath, dir ) { + 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 + if ( bool ) { + out[ idx ] = spath; + return next(); + } + // Resolve a parent directory: + child = dir; + dir = resolve( dir, '..' ); + + // If we have already reached root, we cannot resolve any higher directories... + if ( child === dir ) { + out[ idx ] = null; + return next(); + } + // Resolve path at next directory level: + spath = resolve( dir, paths[ idx ] ); + exists( spath, getCallback( idx, spath, dir ) ); + } + } +} + + +// MAIN // + +/** +* Asynchronously resolves paths from a set of paths by walking parent directories. +* +* @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 {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 ) ) { + 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 = {}; + 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/sync.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js new file mode 100644 index 000000000000..0c99f550a818 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/sync.js @@ -0,0 +1,231 @@ +/** +* @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 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' ); +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 the first path match from a set of paths by walking parent directories. +* +* @private +* @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 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 ] ); + if ( exists( spath ) ) { + out.push( spath ); + return out; + } + } + child = dir; + dir = resolve( dir, '..' ); + } + return out; +} + +/** +* 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 +* @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... + out = []; + 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 +* @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... + out = []; + 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 +* @param {string} dir - base directory +* @returns {Array} resolved paths +*/ +function each( paths, dir ) { + var count; + var child; + var spath; + 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 ) ) { + out[ i ] = spath; + count += 1; + } + } + if ( count === paths.length ) { + break; + } + child = dir; + dir = resolve( dir, '..' ); + } + return out; +} + + +// MAIN // + +/** +* Synchronously resolves paths from a set of paths by walking parent directories. +* +* @param {Array} paths - paths to resolve +* @param {Options} [options] - function options +* @param {string} [options.dir] - base directory +* @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 +* @returns {Array} resolved paths +* +* @example +* var paths = resolveParentPaths( [ 'package.json', 'package-lock.json' ] ); +*/ +function resolveParentPaths( paths, options ) { + var opts; + var mode; + var dir; + var fcn; + 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 = {}; + if ( arguments.length > 1 ) { + err = validate( opts, options ); + if ( err ) { + throw err; + } + } + if ( opts.dir ) { + dir = resolve( cwd(), opts.dir ); + } else { + dir = cwd(); + } + mode = opts.mode || 'all'; + + fcn = MODES[ mode ]; + return fcn( paths, dir ); +} + + +// 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 000000000000..d9f48c1955b1 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/lib/validate.js @@ -0,0 +1,81 @@ +/** +* @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 contains = require( '@stdlib/array/base/assert/contains' ).factory; +var format = require( '@stdlib/string/format' ); + + +// VARIABLES // + +var isMode = contains( [ 'first', 'some', 'all', 'each' ] ); + + +// MAIN // + +/** +* Validates function options. +* +* @private +* @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', +* 'mode': 'some' +* }; +* +* 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 ) ); + } + } + if ( hasOwnProp( options, 'mode' ) ) { + opts.mode = options.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; +} + + +// 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 000000000000..ef6d39364590 --- /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 paths 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 000000000000..683cbbc2f4cc --- /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.cli.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js new file mode 100644 index 000000000000..5251e6591060 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.cli.js @@ -0,0 +1,311 @@ +/** +* @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 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' ); +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 the first path match from a set of paths by walking parent directories (mode=first)', opts, function test( t ) { + var cmd = [ + EXEC_PATH, + fpath, + '--mode', + 'first', + '--dir', + __dirname, + 'package.json', + 'beep-boop!!!helloWorld!?!' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + if ( error ) { + t.fail( error.message ); + } else { + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 1, 'returns expected value' ); + + 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`' ); + } + t.end(); + } +}); + +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, + '--mode', + 'some', + '--dir', + __dirname, + 'package.json', + 'beep-boop!!!helloWorld!?!', + 'README.md' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + if ( error ) { + t.fail( error.message ); + } else { + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( contains( actual, resolve( __dirname, '..', 'package.json' ) ), true, 'returns expected value' ); + + 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`' ); + } + t.end(); + } +}); + +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, + '--mode', + 'all', + '--dir', + __dirname, + 'package.json', + 'README.md' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + if ( error ) { + t.fail( error.message ); + } else { + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( actual[ 0 ], resolve( __dirname, '..', 'package.json' ), 'returns expected value' ); + + 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`' ); + } + t.end(); + } +}); + +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, + '--mode', + 'each', + '--dir', + __dirname, + 'package.json', + 'resolve-parent-paths' + ]; + exec( cmd.join( ' ' ), done ); + + function done( error, stdout, stderr ) { + var actual; + if ( error ) { + t.fail( error.message ); + } else { + actual = trim( stdout ).split( RE_EOL ); + t.strictEqual( actual.length, 2, 'returns expected value' ); + + t.strictEqual( isAbsolutePath( actual[ 0 ] ), true, 'returns expected value' ); + t.strictEqual( actual[ 0 ], resolve( __dirname, '..', 'package.json' ), 'returns expected value' ); + + t.strictEqual( isAbsolutePath( actual[ 1 ] ), true, 'returns expected value' ); + + 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 000000000000..38ab906fcd48 --- /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 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.main.js b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js new file mode 100644 index 000000000000..eac3b22e420b --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.main.js @@ -0,0 +1,563 @@ +/** +* @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 contains = require( '@stdlib/assert/contains' ); +var noop = require( '@stdlib/utils/noop' ); +var cwd = require( '@stdlib/process/cwd' ); +var resolveParentPaths = require( './../lib/main.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 paths 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 ], onPaths ); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); + 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 opts; + + opts = { + 'dir': __dirname + }; + expected = resolve( __dirname, '..', 'package.json' ); + + resolveParentPaths( [ 'package.json' ], opts, onPaths ); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + 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 (mode=first)', opts, function test( t ) { + var opts; + var dir; + var FLG; + + FLG = 0; + opts = { + 'dir': __dirname, + 'mode': 'first' + }; + dir = resolve( __dirname, '..', 'package.json' ); + + resolveParentPaths( [ 'package.json' ], opts, onPaths ); + resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths ); + resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths ); + + function onPaths( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], dir, 'returns expected value' ); + + FLG += 1; + if ( FLG === 3 ) { + t.end(); + } + } +}); + +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' + }; + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', 'README.md' ); + + resolveParentPaths( [ 'package.json' ], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!helloWorld!?!', 'package.json' ], opts, onPaths1 ); + resolveParentPaths( [ 'package.json', 'README.md' ], opts, onPaths2 ); + + function onPaths1( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + + FLG += 1; + if ( FLG === 3 ) { + t.end(); + } + } + + function onPaths2( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + 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 ) { + t.end(); + } + } +}); + +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' + }; + 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 ); + + function onPathsNegative( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns expected value' ); + + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } + } + + function onPathsPositive( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + 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 ) { + t.end(); + } + } +}); + +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' + }; + 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 ); + + function onPathsNegative( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 2, 'returns expected value' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v1, 'returns expected value' ); + + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } + } + + function onPathsPositive( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + 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 ) { + t.end(); + } + } +}); + +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( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); + + t.end(); + + 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( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); + t.end(); + + 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( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); + t.end(); + + 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 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( [], opts, onPaths1 ); + resolveParentPaths( [ 'beep-boop!!!hello world!?!' ], opts, onPaths2 ); + t.end(); + + function onPaths1( error, actual ) { + if ( error ) { + t.ok( false, error.message ); + } + t.strictEqual( actual.length, 0, 'returns expected array' ); + FLG += 1; + if ( FLG === 2 ) { + t.end(); + } + } + + function onPaths2( 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' ); + FLG += 1; + if ( FLG === 2 ) { + 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 000000000000..034d91c2e0e4 --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.sync.js @@ -0,0 +1,377 @@ +/** +* @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 isArray = require( '@stdlib/assert/is-array' ); +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 paths 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.length, 1, 'returns expected value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); + + 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( [ 'package.json' ], opts ); + 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 (mode=first)', opts, function test( t ) { + var expected; + var actual; + var opts; + var dir; + + opts = { + 'dir': __dirname, + 'mode': 'first' + }; + dir = resolve( __dirname, '..', 'package.json' ); + + expected = dir; + actual = resolveParentPaths( [ 'package.json' ], opts ); + 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 value' ); + t.strictEqual( actual[ 0 ], expected, 'returns expected value' ); + + actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); + 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 (mode=some)', opts, function test( t ) { + var actual; + var opts; + var v1; + var v2; + + opts = { + 'dir': __dirname, + 'mode': 'some' + }; + v1 = resolve( __dirname, '..', 'package.json' ); + v2 = resolve( __dirname, '..', 'README.md' ); + + actual = resolveParentPaths( [ 'package.json' ], opts ); + 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 value' ); + t.strictEqual( actual[ 0 ], v1, 'returns expected value' ); + + actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); + 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 (mode=all)', opts, function test( t ) { + var actual; + var opts; + var v1; + var v2; + + opts = { + 'dir': __dirname, + 'mode': 'all' + }; + 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 value' ); + + actual = resolveParentPaths( [ 'package.json', 'README.md' ], opts ); + 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 (mode=each)', opts, function test( t ) { + var actual; + var opts; + var v1; + var v2; + + opts = { + 'dir': __dirname, + 'mode': 'each' + }; + 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 value' ); + t.strictEqual( actual[ 0 ], null, 'returns expected value' ); + t.strictEqual( actual[ 1 ], v1, 'returns expected value' ); + + actual = resolveParentPaths( [ 'package.json', 'resolve-parent-paths' ], opts ); + 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 (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.end(); +}); + +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.end(); +}); + +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.end(); +}); + +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( [], 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[ 0 ], null, 'returns expected value' ); + + 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 000000000000..fbb6a8425a2f --- /dev/null +++ b/lib/node_modules/@stdlib/fs/resolve-parent-paths/test/test.validate.js @@ -0,0 +1,151 @@ +/** +* @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( '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', + 'mode': 'first' + }; + obj = {}; + err = validate( obj, opts ); + + 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(); +}); + +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 expected value' ); + t.deepEqual( obj, {}, 'returns expected value' ); + + t.end(); +});