<commit_before>'use strict';

// MODULES //

var glob = require( 'glob' ).sync;
var resolve = require( 'path' ).resolve;
var getKeys = require( 'object-keys' ).shim();
var cwd = require( '@stdlib/utils/cwd' );
var copy = require( '@stdlib/utils/copy' );
var readJSON = require( '@stdlib/fs/read-json' ).sync;
var isString = require( '@stdlib/utils/is-string' ).isPrimitive;
var hasOwnProp = require( '@stdlib/utils/has-own-property' );
var dirname = require( '@stdlib/utils/dirname' );
var config = require( './config.json' );
var validate = require( './validate.js' );


// MAIN //

/**
* Synchronously find package command-line interfaces (CLIs).
*
* @param {Options} [options] - function options
* @param {string} [options.dir] - root directory from which to search for packages
* @param {string} [options.pattern='**\/package.json'] - glob pattern
* @param {StringArray} [options.ignore] - glob pattern(s) to exclude matches
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
* @throws {Error} `pattern` option must end with `package.json`
* @throws {Error} unable to parse `package.json` as JSON
* @returns {StringArray} list of command-line interfaces
*
* @example
* var files = findCLIs();
* // returns [...]
*/
function findCLIs( options ) {
	var fpath;
	var files;
	var gopts;
	var file;
	var opts;
	var keys;
	var err;
	var dir;
	var out;
	var i;
	var j;

	opts = copy( config );
	if ( arguments.length ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( opts.dir ) {
		dir = resolve( cwd(), opts.dir );
	} else {
		dir = cwd();
	}
	// Find `package.json` files...
	gopts = {
		'cwd': dir,
		'ignore': opts.ignore,
		'realpath': true // return absolute file paths
	};
	files = glob( opts.pattern, gopts );

	// Check for referenced CLI files...
	out = [];
	for ( i = 0; i < files.length; i++ ) {
		file = readJSON( files[ i ] );
		if ( file instanceof Error ) {
			throw file;
		}
		dir = dirname( files[ i ] );
		if ( isString( file.bin ) ) {
			fpath = resolve( dir, file.bin );
			out.push( fpath );
		} else if ( hasOwnProp( file, 'bin' ) ) {
			keys = getKeys( file.bin );
			for ( j = 0; j < keys.length; j++ ) {
				fpath = file.bin[ keys[j] ];
				fpath = resolve( dir, fpath );
				out.push( fpath );
			}
		}
	}
	return out;
} // end FUNCTION findCLIs()


// EXPORTS //

module.exports = findCLIs;
<commit_msg>Fix return type<commit_after>'use strict';

// MODULES //

var glob = require( 'glob' ).sync;
var resolve = require( 'path' ).resolve;
var getKeys = require( 'object-keys' ).shim();
var cwd = require( '@stdlib/utils/cwd' );
var copy = require( '@stdlib/utils/copy' );
var readJSON = require( '@stdlib/fs/read-json' ).sync;
var isString = require( '@stdlib/utils/is-string' ).isPrimitive;
var hasOwnProp = require( '@stdlib/utils/has-own-property' );
var dirname = require( '@stdlib/utils/dirname' );
var config = require( './config.json' );
var validate = require( './validate.js' );


// MAIN //

/**
* Synchronously find package command-line interfaces (CLIs).
*
* @param {Options} [options] - function options
* @param {string} [options.dir] - root directory from which to search for packages
* @param {string} [options.pattern='**\/package.json'] - glob pattern
* @param {StringArray} [options.ignore] - glob pattern(s) to exclude matches
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
* @throws {Error} `pattern` option must end with `package.json`
* @throws {Error} unable to parse `package.json` as JSON
* @returns {(Array|StringArray)} list of command-line interfaces
*
* @example
* var files = findCLIs();
* // returns [...]
*/
function findCLIs( options ) {
	var fpath;
	var files;
	var gopts;
	var file;
	var opts;
	var keys;
	var err;
	var dir;
	var out;
	var i;
	var j;

	opts = copy( config );
	if ( arguments.length ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( opts.dir ) {
		dir = resolve( cwd(), opts.dir );
	} else {
		dir = cwd();
	}
	// Find `package.json` files...
	gopts = {
		'cwd': dir,
		'ignore': opts.ignore,
		'realpath': true // return absolute file paths
	};
	files = glob( opts.pattern, gopts );

	// Check for referenced CLI files...
	out = [];
	for ( i = 0; i < files.length; i++ ) {
		file = readJSON( files[ i ] );
		if ( file instanceof Error ) {
			throw file;
		}
		dir = dirname( files[ i ] );
		if ( isString( file.bin ) ) {
			fpath = resolve( dir, file.bin );
			out.push( fpath );
		} else if ( hasOwnProp( file, 'bin' ) ) {
			keys = getKeys( file.bin );
			for ( j = 0; j < keys.length; j++ ) {
				fpath = file.bin[ keys[j] ];
				fpath = resolve( dir, fpath );
				out.push( fpath );
			}
		}
	}
	return out;
} // end FUNCTION findCLIs()


// EXPORTS //

module.exports = findCLIs;

{'fraction_non_alphanumeric': 0.1680446465481604, 'fraction_numerical': 0.0008267879288962381, 'mean_word_length': 3.196877710320902, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3598800', 'n_tokens_mistral': 1770, 'n_tokens_neox': 1666, 'n_words': 522}