| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 | 
							- 'use strict';
 
- const path = require('path');
 
- const globToRegExp = require('glob-to-regexp');
 
- module.exports = normalizeOptions;
 
- let isWindows = /^win/.test(process.platform);
 
- /**
 
-  * @typedef {Object} FSFacade
 
-  * @property {fs.readdir} readdir
 
-  * @property {fs.stat} stat
 
-  * @property {fs.lstat} lstat
 
-  */
 
- /**
 
-  * Validates and normalizes the options argument
 
-  *
 
-  * @param {object} [options] - User-specified options, if any
 
-  * @param {object} internalOptions - Internal options that aren't part of the public API
 
-  *
 
-  * @param {number|boolean|function} [options.deep]
 
-  * The number of directories to recursively traverse. Any falsy value or negative number will
 
-  * default to zero, so only the top-level contents will be returned. Set to `true` or `Infinity`
 
-  * to traverse all subdirectories.  Or provide a function that accepts a {@link fs.Stats} object
 
-  * and returns a truthy value if the directory's contents should be crawled.
 
-  *
 
-  * @param {function|string|RegExp} [options.filter]
 
-  * A function that accepts a {@link fs.Stats} object and returns a truthy value if the data should
 
-  * be returned.  Or a RegExp or glob string pattern, to filter by file name.
 
-  *
 
-  * @param {string} [options.sep]
 
-  * The path separator to use. By default, the OS-specific separator will be used, but this can be
 
-  * set to a specific value to ensure consistency across platforms.
 
-  *
 
-  * @param {string} [options.basePath]
 
-  * The base path to prepend to each result. If empty, then all results will be relative to `dir`.
 
-  *
 
-  * @param {FSFacade} [options.fs]
 
-  * Synchronous or asynchronous facades for Node.js File System module
 
-  *
 
-  * @param {object} [internalOptions.facade]
 
-  * Synchronous or asynchronous facades for various methods, including for the Node.js File System module
 
-  *
 
-  * @param {boolean} [internalOptions.emit]
 
-  * Indicates whether the reader should emit "file", "directory", and "symlink" events
 
-  *
 
-  * @param {boolean} [internalOptions.stats]
 
-  * Indicates whether the reader should emit {@link fs.Stats} objects instead of path strings
 
-  *
 
-  * @returns {object}
 
-  */
 
- function normalizeOptions (options, internalOptions) {
 
-   if (options === null || options === undefined) {
 
-     options = {};
 
-   }
 
-   else if (typeof options !== 'object') {
 
-     throw new TypeError('options must be an object');
 
-   }
 
-   let recurseDepth, recurseFn, recurseRegExp, recurseGlob, deep = options.deep;
 
-   if (deep === null || deep === undefined) {
 
-     recurseDepth = 0;
 
-   }
 
-   else if (typeof deep === 'boolean') {
 
-     recurseDepth = deep ? Infinity : 0;
 
-   }
 
-   else if (typeof deep === 'number') {
 
-     if (deep < 0 || isNaN(deep)) {
 
-       throw new Error('options.deep must be a positive number');
 
-     }
 
-     else if (Math.floor(deep) !== deep) {
 
-       throw new Error('options.deep must be an integer');
 
-     }
 
-     else {
 
-       recurseDepth = deep;
 
-     }
 
-   }
 
-   else if (typeof deep === 'function') {
 
-     recurseDepth = Infinity;
 
-     recurseFn = deep;
 
-   }
 
-   else if (deep instanceof RegExp) {
 
-     recurseDepth = Infinity;
 
-     recurseRegExp = deep;
 
-   }
 
-   else if (typeof deep === 'string' && deep.length > 0) {
 
-     recurseDepth = Infinity;
 
-     recurseGlob = globToRegExp(deep, { extended: true, globstar: true });
 
-   }
 
-   else {
 
-     throw new TypeError('options.deep must be a boolean, number, function, regular expression, or glob pattern');
 
-   }
 
-   let filterFn, filterRegExp, filterGlob, filter = options.filter;
 
-   if (filter !== null && filter !== undefined) {
 
-     if (typeof filter === 'function') {
 
-       filterFn = filter;
 
-     }
 
-     else if (filter instanceof RegExp) {
 
-       filterRegExp = filter;
 
-     }
 
-     else if (typeof filter === 'string' && filter.length > 0) {
 
-       filterGlob = globToRegExp(filter, { extended: true, globstar: true });
 
-     }
 
-     else {
 
-       throw new TypeError('options.filter must be a function, regular expression, or glob pattern');
 
-     }
 
-   }
 
-   let sep = options.sep;
 
-   if (sep === null || sep === undefined) {
 
-     sep = path.sep;
 
-   }
 
-   else if (typeof sep !== 'string') {
 
-     throw new TypeError('options.sep must be a string');
 
-   }
 
-   let basePath = options.basePath;
 
-   if (basePath === null || basePath === undefined) {
 
-     basePath = '';
 
-   }
 
-   else if (typeof basePath === 'string') {
 
-     // Append a path separator to the basePath, if necessary
 
-     if (basePath && basePath.substr(-1) !== sep) {
 
-       basePath += sep;
 
-     }
 
-   }
 
-   else {
 
-     throw new TypeError('options.basePath must be a string');
 
-   }
 
-   // Convert the basePath to POSIX (forward slashes)
 
-   // so that glob pattern matching works consistently, even on Windows
 
-   let posixBasePath = basePath;
 
-   if (posixBasePath && sep !== '/') {
 
-     posixBasePath = posixBasePath.replace(new RegExp('\\' + sep, 'g'), '/');
 
-     /* istanbul ignore if */
 
-     if (isWindows) {
 
-       // Convert Windows root paths (C:\) and UNCs (\\) to POSIX root paths
 
-       posixBasePath = posixBasePath.replace(/^([a-zA-Z]\:\/|\/\/)/, '/');
 
-     }
 
-   }
 
-   // Determine which facade methods to use
 
-   let facade;
 
-   if (options.fs === null || options.fs === undefined) {
 
-     // The user didn't provide their own facades, so use our internal ones
 
-     facade = internalOptions.facade;
 
-   }
 
-   else if (typeof options.fs === 'object') {
 
-     // Merge the internal facade methods with the user-provided `fs` facades
 
-     facade = Object.assign({}, internalOptions.facade);
 
-     facade.fs = Object.assign({}, internalOptions.facade.fs, options.fs);
 
-   }
 
-   else {
 
-     throw new TypeError('options.fs must be an object');
 
-   }
 
-   return {
 
-     recurseDepth,
 
-     recurseFn,
 
-     recurseRegExp,
 
-     recurseGlob,
 
-     filterFn,
 
-     filterRegExp,
 
-     filterGlob,
 
-     sep,
 
-     basePath,
 
-     posixBasePath,
 
-     facade,
 
-     emit: !!internalOptions.emit,
 
-     stats: !!internalOptions.stats,
 
-   };
 
- }
 
 
  |