mirror of
https://github.com/titanscouting/tra-analysis.git
synced 2025-09-06 15:07:21 +00:00
push all website files
This commit is contained in:
29
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/async/for-each.js
generated
vendored
Normal file
29
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/async/for-each.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = asyncForEach;
|
||||
|
||||
/**
|
||||
* Simultaneously processes all items in the given array.
|
||||
*
|
||||
* @param {array} array - The array to iterate over
|
||||
* @param {function} iterator - The function to call for each item in the array
|
||||
* @param {function} done - The function to call when all iterators have completed
|
||||
*/
|
||||
function asyncForEach (array, iterator, done) {
|
||||
if (array.length === 0) {
|
||||
// NOTE: Normally a bad idea to mix sync and async, but it's safe here because
|
||||
// of the way that this method is currently used by DirectoryReader.
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Simultaneously process all items in the array.
|
||||
let pending = array.length;
|
||||
array.forEach(item => {
|
||||
iterator(item, () => {
|
||||
if (--pending === 0) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
48
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/async/index.js
generated
vendored
Normal file
48
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/async/index.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = readdirAsync;
|
||||
|
||||
const maybe = require('call-me-maybe');
|
||||
const DirectoryReader = require('../directory-reader');
|
||||
|
||||
let asyncFacade = {
|
||||
fs: require('fs'),
|
||||
forEach: require('./for-each'),
|
||||
async: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the buffered output from an asynchronous {@link DirectoryReader},
|
||||
* via an error-first callback or a {@link Promise}.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @param {function} [callback]
|
||||
* @param {object} internalOptions
|
||||
*/
|
||||
function readdirAsync (dir, options, callback, internalOptions) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = undefined;
|
||||
}
|
||||
|
||||
return maybe(callback, new Promise(((resolve, reject) => {
|
||||
let results = [];
|
||||
|
||||
internalOptions.facade = asyncFacade;
|
||||
|
||||
let reader = new DirectoryReader(dir, options, internalOptions);
|
||||
let stream = reader.stream;
|
||||
|
||||
stream.on('error', err => {
|
||||
reject(err);
|
||||
stream.pause();
|
||||
});
|
||||
stream.on('data', result => {
|
||||
results.push(result);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
resolve(results);
|
||||
});
|
||||
})));
|
||||
}
|
54
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/call.js
generated
vendored
Normal file
54
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/call.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
let call = module.exports = {
|
||||
safe: safeCall,
|
||||
once: callOnce,
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls a function with the given arguments, and ensures that the error-first callback is _always_
|
||||
* invoked exactly once, even if the function throws an error.
|
||||
*
|
||||
* @param {function} fn - The function to invoke
|
||||
* @param {...*} args - The arguments to pass to the function. The final argument must be a callback function.
|
||||
*/
|
||||
function safeCall (fn, args) {
|
||||
// Get the function arguments as an array
|
||||
args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
// Replace the callback function with a wrapper that ensures it will only be called once
|
||||
let callback = call.once(args.pop());
|
||||
args.push(callback);
|
||||
|
||||
try {
|
||||
fn.apply(null, args);
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wrapper function that ensures the given callback function is only called once.
|
||||
* Subsequent calls are ignored, unless the first argument is an Error, in which case the
|
||||
* error is thrown.
|
||||
*
|
||||
* @param {function} fn - The function that should only be called once
|
||||
* @returns {function}
|
||||
*/
|
||||
function callOnce (fn) {
|
||||
let fulfilled = false;
|
||||
|
||||
return function onceWrapper (err) {
|
||||
if (!fulfilled) {
|
||||
fulfilled = true;
|
||||
return fn.apply(this, arguments);
|
||||
}
|
||||
else if (err) {
|
||||
// The callback has already been called, but now an error has occurred
|
||||
// (most likely inside the callback function). So re-throw the error,
|
||||
// so it gets handled further up the call stack
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
380
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/directory-reader.js
generated
vendored
Normal file
380
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/directory-reader.js
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
'use strict';
|
||||
|
||||
const Readable = require('stream').Readable;
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const path = require('path');
|
||||
const normalizeOptions = require('./normalize-options');
|
||||
const stat = require('./stat');
|
||||
const call = require('./call');
|
||||
|
||||
/**
|
||||
* Asynchronously reads the contents of a directory and streams the results
|
||||
* via a {@link stream.Readable}.
|
||||
*/
|
||||
class DirectoryReader {
|
||||
/**
|
||||
* @param {string} dir - The absolute or relative directory path to read
|
||||
* @param {object} [options] - User-specified options, if any (see {@link normalizeOptions})
|
||||
* @param {object} internalOptions - Internal options that aren't part of the public API
|
||||
* @class
|
||||
*/
|
||||
constructor (dir, options, internalOptions) {
|
||||
this.options = options = normalizeOptions(options, internalOptions);
|
||||
|
||||
// Indicates whether we should keep reading
|
||||
// This is set false if stream.Readable.push() returns false.
|
||||
this.shouldRead = true;
|
||||
|
||||
// The directories to read
|
||||
// (initialized with the top-level directory)
|
||||
this.queue = [{
|
||||
path: dir,
|
||||
basePath: options.basePath,
|
||||
posixBasePath: options.posixBasePath,
|
||||
depth: 0
|
||||
}];
|
||||
|
||||
// The number of directories that are currently being processed
|
||||
this.pending = 0;
|
||||
|
||||
// The data that has been read, but not yet emitted
|
||||
this.buffer = [];
|
||||
|
||||
this.stream = new Readable({ objectMode: true });
|
||||
this.stream._read = () => {
|
||||
// Start (or resume) reading
|
||||
this.shouldRead = true;
|
||||
|
||||
// If we have data in the buffer, then send the next chunk
|
||||
if (this.buffer.length > 0) {
|
||||
this.pushFromBuffer();
|
||||
}
|
||||
|
||||
// If we have directories queued, then start processing the next one
|
||||
if (this.queue.length > 0) {
|
||||
if (this.options.facade.sync) {
|
||||
while (this.queue.length > 0) {
|
||||
this.readNextDirectory();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.readNextDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
this.checkForEOF();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next directory in the queue
|
||||
*/
|
||||
readNextDirectory () {
|
||||
let facade = this.options.facade;
|
||||
let dir = this.queue.shift();
|
||||
this.pending++;
|
||||
|
||||
// Read the directory listing
|
||||
call.safe(facade.fs.readdir, dir.path, (err, items) => {
|
||||
if (err) {
|
||||
// fs.readdir threw an error
|
||||
this.emit('error', err);
|
||||
return this.finishedReadingDirectory();
|
||||
}
|
||||
|
||||
try {
|
||||
// Process each item in the directory (simultaneously, if async)
|
||||
facade.forEach(
|
||||
items,
|
||||
this.processItem.bind(this, dir),
|
||||
this.finishedReadingDirectory.bind(this, dir)
|
||||
);
|
||||
}
|
||||
catch (err2) {
|
||||
// facade.forEach threw an error
|
||||
// (probably because fs.readdir returned an invalid result)
|
||||
this.emit('error', err2);
|
||||
this.finishedReadingDirectory();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called after all items in a directory have been processed.
|
||||
*
|
||||
* NOTE: This does not necessarily mean that the reader is finished, since there may still
|
||||
* be other directories queued or pending.
|
||||
*/
|
||||
finishedReadingDirectory () {
|
||||
this.pending--;
|
||||
|
||||
if (this.shouldRead) {
|
||||
// If we have directories queued, then start processing the next one
|
||||
if (this.queue.length > 0 && this.options.facade.async) {
|
||||
this.readNextDirectory();
|
||||
}
|
||||
|
||||
this.checkForEOF();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the reader has finished processing all items in all directories.
|
||||
* If so, then the "end" event is fired (via {@Readable#push})
|
||||
*/
|
||||
checkForEOF () {
|
||||
if (this.buffer.length === 0 && // The stuff we've already read
|
||||
this.pending === 0 && // The stuff we're currently reading
|
||||
this.queue.length === 0) { // The stuff we haven't read yet
|
||||
// There's no more stuff!
|
||||
this.stream.push(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a single item in a directory.
|
||||
*
|
||||
* If the item is a directory, and `option.deep` is enabled, then the item will be added
|
||||
* to the directory queue.
|
||||
*
|
||||
* If the item meets the filter criteria, then it will be emitted to the reader's stream.
|
||||
*
|
||||
* @param {object} dir - A directory object from the queue
|
||||
* @param {string} item - The name of the item (name only, no path)
|
||||
* @param {function} done - A callback function that is called after the item has been processed
|
||||
*/
|
||||
processItem (dir, item, done) {
|
||||
let stream = this.stream;
|
||||
let options = this.options;
|
||||
|
||||
let itemPath = dir.basePath + item;
|
||||
let posixPath = dir.posixBasePath + item;
|
||||
let fullPath = path.join(dir.path, item);
|
||||
|
||||
// If `options.deep` is a number, and we've already recursed to the max depth,
|
||||
// then there's no need to check fs.Stats to know if it's a directory.
|
||||
// If `options.deep` is a function, then we'll need fs.Stats
|
||||
let maxDepthReached = dir.depth >= options.recurseDepth;
|
||||
|
||||
// Do we need to call `fs.stat`?
|
||||
let needStats =
|
||||
!maxDepthReached || // we need the fs.Stats to know if it's a directory
|
||||
options.stats || // the user wants fs.Stats objects returned
|
||||
options.recurseFn || // we need fs.Stats for the recurse function
|
||||
options.filterFn || // we need fs.Stats for the filter function
|
||||
EventEmitter.listenerCount(stream, 'file') || // we need the fs.Stats to know if it's a file
|
||||
EventEmitter.listenerCount(stream, 'directory') || // we need the fs.Stats to know if it's a directory
|
||||
EventEmitter.listenerCount(stream, 'symlink'); // we need the fs.Stats to know if it's a symlink
|
||||
|
||||
// If we don't need stats, then exit early
|
||||
if (!needStats) {
|
||||
if (this.filter(itemPath, posixPath)) {
|
||||
this.pushOrBuffer({ data: itemPath });
|
||||
}
|
||||
return done();
|
||||
}
|
||||
|
||||
// Get the fs.Stats object for this path
|
||||
stat(options.facade.fs, fullPath, (err, stats) => {
|
||||
if (err) {
|
||||
// fs.stat threw an error
|
||||
this.emit('error', err);
|
||||
return done();
|
||||
}
|
||||
|
||||
try {
|
||||
// Add the item's path to the fs.Stats object
|
||||
// The base of this path, and its separators are determined by the options
|
||||
// (i.e. options.basePath and options.sep)
|
||||
stats.path = itemPath;
|
||||
|
||||
// Add depth of the path to the fs.Stats object for use this in the filter function
|
||||
stats.depth = dir.depth;
|
||||
|
||||
if (this.shouldRecurse(stats, posixPath, maxDepthReached)) {
|
||||
// Add this subdirectory to the queue
|
||||
this.queue.push({
|
||||
path: fullPath,
|
||||
basePath: itemPath + options.sep,
|
||||
posixBasePath: posixPath + '/',
|
||||
depth: dir.depth + 1,
|
||||
});
|
||||
}
|
||||
|
||||
// Determine whether this item matches the filter criteria
|
||||
if (this.filter(stats, posixPath)) {
|
||||
this.pushOrBuffer({
|
||||
data: options.stats ? stats : itemPath,
|
||||
file: stats.isFile(),
|
||||
directory: stats.isDirectory(),
|
||||
symlink: stats.isSymbolicLink(),
|
||||
});
|
||||
}
|
||||
|
||||
done();
|
||||
}
|
||||
catch (err2) {
|
||||
// An error occurred while processing the item
|
||||
// (probably during a user-specified function, such as options.deep, options.filter, etc.)
|
||||
this.emit('error', err2);
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes the given chunk of data to the stream, or adds it to the buffer,
|
||||
* depending on the state of the stream.
|
||||
*
|
||||
* @param {object} chunk
|
||||
*/
|
||||
pushOrBuffer (chunk) {
|
||||
// Add the chunk to the buffer
|
||||
this.buffer.push(chunk);
|
||||
|
||||
// If we're still reading, then immediately emit the next chunk in the buffer
|
||||
// (which may or may not be the chunk that we just added)
|
||||
if (this.shouldRead) {
|
||||
this.pushFromBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately pushes the next chunk in the buffer to the reader's stream.
|
||||
* The "data" event will always be fired (via {@link Readable#push}).
|
||||
* In addition, the "file", "directory", and/or "symlink" events may be fired,
|
||||
* depending on the type of properties of the chunk.
|
||||
*/
|
||||
pushFromBuffer () {
|
||||
let stream = this.stream;
|
||||
let chunk = this.buffer.shift();
|
||||
|
||||
// Stream the data
|
||||
try {
|
||||
this.shouldRead = stream.push(chunk.data);
|
||||
}
|
||||
catch (err) {
|
||||
this.emit('error', err);
|
||||
}
|
||||
|
||||
// Also emit specific events, based on the type of chunk
|
||||
chunk.file && this.emit('file', chunk.data);
|
||||
chunk.symlink && this.emit('symlink', chunk.data);
|
||||
chunk.directory && this.emit('directory', chunk.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given directory meets the user-specified recursion criteria.
|
||||
* If the user didn't specify recursion criteria, then this function will default to true.
|
||||
*
|
||||
* @param {fs.Stats} stats - The directory's {@link fs.Stats} object
|
||||
* @param {string} posixPath - The item's POSIX path (used for glob matching)
|
||||
* @param {boolean} maxDepthReached - Whether we've already crawled the user-specified depth
|
||||
* @returns {boolean}
|
||||
*/
|
||||
shouldRecurse (stats, posixPath, maxDepthReached) {
|
||||
let options = this.options;
|
||||
|
||||
if (maxDepthReached) {
|
||||
// We've already crawled to the maximum depth. So no more recursion.
|
||||
return false;
|
||||
}
|
||||
else if (!stats.isDirectory()) {
|
||||
// It's not a directory. So don't try to crawl it.
|
||||
return false;
|
||||
}
|
||||
else if (options.recurseGlob) {
|
||||
// Glob patterns are always tested against the POSIX path, even on Windows
|
||||
// https://github.com/isaacs/node-glob#windows
|
||||
return options.recurseGlob.test(posixPath);
|
||||
}
|
||||
else if (options.recurseRegExp) {
|
||||
// Regular expressions are tested against the normal path
|
||||
// (based on the OS or options.sep)
|
||||
return options.recurseRegExp.test(stats.path);
|
||||
}
|
||||
else if (options.recurseFn) {
|
||||
try {
|
||||
// Run the user-specified recursion criteria
|
||||
return options.recurseFn.call(null, stats);
|
||||
}
|
||||
catch (err) {
|
||||
// An error occurred in the user's code.
|
||||
// In Sync and Async modes, this will return an error.
|
||||
// In Streaming mode, we emit an "error" event, but continue processing
|
||||
this.emit('error', err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No recursion function was specified, and we're within the maximum depth.
|
||||
// So crawl this directory.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given item meets the user-specified filter criteria.
|
||||
* If the user didn't specify a filter, then this function will always return true.
|
||||
*
|
||||
* @param {string|fs.Stats} value - Either the item's path, or the item's {@link fs.Stats} object
|
||||
* @param {string} posixPath - The item's POSIX path (used for glob matching)
|
||||
* @returns {boolean}
|
||||
*/
|
||||
filter (value, posixPath) {
|
||||
let options = this.options;
|
||||
|
||||
if (options.filterGlob) {
|
||||
// Glob patterns are always tested against the POSIX path, even on Windows
|
||||
// https://github.com/isaacs/node-glob#windows
|
||||
return options.filterGlob.test(posixPath);
|
||||
}
|
||||
else if (options.filterRegExp) {
|
||||
// Regular expressions are tested against the normal path
|
||||
// (based on the OS or options.sep)
|
||||
return options.filterRegExp.test(value.path || value);
|
||||
}
|
||||
else if (options.filterFn) {
|
||||
try {
|
||||
// Run the user-specified filter function
|
||||
return options.filterFn.call(null, value);
|
||||
}
|
||||
catch (err) {
|
||||
// An error occurred in the user's code.
|
||||
// In Sync and Async modes, this will return an error.
|
||||
// In Streaming mode, we emit an "error" event, but continue processing
|
||||
this.emit('error', err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No filter was specified, so match everything
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an event. If one of the event listeners throws an error,
|
||||
* then an "error" event is emitted.
|
||||
*
|
||||
* @param {string} eventName
|
||||
* @param {*} data
|
||||
*/
|
||||
emit (eventName, data) {
|
||||
let stream = this.stream;
|
||||
|
||||
try {
|
||||
stream.emit(eventName, data);
|
||||
}
|
||||
catch (err) {
|
||||
if (eventName === 'error') {
|
||||
// Don't recursively emit "error" events.
|
||||
// If the first one fails, then just throw
|
||||
throw err;
|
||||
}
|
||||
else {
|
||||
stream.emit('error', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DirectoryReader;
|
85
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/index.js
generated
vendored
Normal file
85
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
const readdirSync = require('./sync');
|
||||
const readdirAsync = require('./async');
|
||||
const readdirStream = require('./stream');
|
||||
|
||||
module.exports = exports = readdirAsyncPath;
|
||||
exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath;
|
||||
exports.readdirAsyncStat = exports.async.stat = readdirAsyncStat;
|
||||
exports.readdirStream = exports.stream = readdirStreamPath;
|
||||
exports.readdirStreamStat = exports.stream.stat = readdirStreamStat;
|
||||
exports.readdirSync = exports.sync = readdirSyncPath;
|
||||
exports.readdirSyncStat = exports.sync.stat = readdirSyncStat;
|
||||
|
||||
/**
|
||||
* Synchronous readdir that returns an array of string paths.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function readdirSyncPath (dir, options) {
|
||||
return readdirSync(dir, options, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous readdir that returns results as an array of {@link fs.Stats} objects
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @returns {fs.Stats[]}
|
||||
*/
|
||||
function readdirSyncStat (dir, options) {
|
||||
return readdirSync(dir, options, { stats: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Aynchronous readdir (accepts an error-first callback or returns a {@link Promise}).
|
||||
* Results are an array of path strings.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @param {function} [callback]
|
||||
* @returns {Promise<string[]>}
|
||||
*/
|
||||
function readdirAsyncPath (dir, options, callback) {
|
||||
return readdirAsync(dir, options, callback, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Aynchronous readdir (accepts an error-first callback or returns a {@link Promise}).
|
||||
* Results are an array of {@link fs.Stats} objects.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @param {function} [callback]
|
||||
* @returns {Promise<fs.Stats[]>}
|
||||
*/
|
||||
function readdirAsyncStat (dir, options, callback) {
|
||||
return readdirAsync(dir, options, callback, { stats: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Aynchronous readdir that returns a {@link stream.Readable} (which is also an {@link EventEmitter}).
|
||||
* All stream data events ("data", "file", "directory", "symlink") are passed a path string.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @returns {stream.Readable}
|
||||
*/
|
||||
function readdirStreamPath (dir, options) {
|
||||
return readdirStream(dir, options, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Aynchronous readdir that returns a {@link stream.Readable} (which is also an {@link EventEmitter})
|
||||
* All stream data events ("data", "file", "directory", "symlink") are passed an {@link fs.Stats} object.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @returns {stream.Readable}
|
||||
*/
|
||||
function readdirStreamStat (dir, options) {
|
||||
return readdirStream(dir, options, { stats: true });
|
||||
}
|
177
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/normalize-options.js
generated
vendored
Normal file
177
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/normalize-options.js
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
'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,
|
||||
};
|
||||
}
|
74
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/stat.js
generated
vendored
Normal file
74
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/stat.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
const call = require('./call');
|
||||
|
||||
module.exports = stat;
|
||||
|
||||
/**
|
||||
* Retrieves the {@link fs.Stats} for the given path. If the path is a symbolic link,
|
||||
* then the Stats of the symlink's target are returned instead. If the symlink is broken,
|
||||
* then the Stats of the symlink itself are returned.
|
||||
*
|
||||
* @param {object} fs - Synchronous or Asynchronouse facade for the "fs" module
|
||||
* @param {string} path - The path to return stats for
|
||||
* @param {function} callback
|
||||
*/
|
||||
function stat (fs, path, callback) {
|
||||
let isSymLink = false;
|
||||
|
||||
call.safe(fs.lstat, path, (err, lstats) => {
|
||||
if (err) {
|
||||
// fs.lstat threw an eror
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
try {
|
||||
isSymLink = lstats.isSymbolicLink();
|
||||
}
|
||||
catch (err2) {
|
||||
// lstats.isSymbolicLink() threw an error
|
||||
// (probably because fs.lstat returned an invalid result)
|
||||
return callback(err2);
|
||||
}
|
||||
|
||||
if (isSymLink) {
|
||||
// Try to resolve the symlink
|
||||
symlinkStat(fs, path, lstats, callback);
|
||||
}
|
||||
else {
|
||||
// It's not a symlink, so return the stats as-is
|
||||
callback(null, lstats);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@link fs.Stats} for the target of the given symlink.
|
||||
* If the symlink is broken, then the Stats of the symlink itself are returned.
|
||||
*
|
||||
* @param {object} fs - Synchronous or Asynchronouse facade for the "fs" module
|
||||
* @param {string} path - The path of the symlink to return stats for
|
||||
* @param {object} lstats - The stats of the symlink
|
||||
* @param {function} callback
|
||||
*/
|
||||
function symlinkStat (fs, path, lstats, callback) {
|
||||
call.safe(fs.stat, path, (err, stats) => {
|
||||
if (err) {
|
||||
// The symlink is broken, so return the stats for the link itself
|
||||
return callback(null, lstats);
|
||||
}
|
||||
|
||||
try {
|
||||
// Return the stats for the resolved symlink target,
|
||||
// and override the `isSymbolicLink` method to indicate that it's a symlink
|
||||
stats.isSymbolicLink = () => true;
|
||||
}
|
||||
catch (err2) {
|
||||
// Setting stats.isSymbolicLink threw an error
|
||||
// (probably because fs.stat returned an invalid result)
|
||||
return callback(err2);
|
||||
}
|
||||
|
||||
callback(null, stats);
|
||||
});
|
||||
}
|
25
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/stream/index.js
generated
vendored
Normal file
25
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/stream/index.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = readdirStream;
|
||||
|
||||
const DirectoryReader = require('../directory-reader');
|
||||
|
||||
let streamFacade = {
|
||||
fs: require('fs'),
|
||||
forEach: require('../async/for-each'),
|
||||
async: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the {@link stream.Readable} of an asynchronous {@link DirectoryReader}.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @param {object} internalOptions
|
||||
*/
|
||||
function readdirStream (dir, options, internalOptions) {
|
||||
internalOptions.facade = streamFacade;
|
||||
|
||||
let reader = new DirectoryReader(dir, options, internalOptions);
|
||||
return reader.stream;
|
||||
}
|
22
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/sync/for-each.js
generated
vendored
Normal file
22
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/sync/for-each.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = syncForEach;
|
||||
|
||||
/**
|
||||
* A facade that allows {@link Array.forEach} to be called as though it were asynchronous.
|
||||
*
|
||||
* @param {array} array - The array to iterate over
|
||||
* @param {function} iterator - The function to call for each item in the array
|
||||
* @param {function} done - The function to call when all iterators have completed
|
||||
*/
|
||||
function syncForEach (array, iterator, done) {
|
||||
array.forEach(item => {
|
||||
iterator(item, () => {
|
||||
// Note: No error-handling here because this is currently only ever called
|
||||
// by DirectoryReader, which never passes an `error` parameter to the callback.
|
||||
// Instead, DirectoryReader emits an "error" event if an error occurs.
|
||||
});
|
||||
});
|
||||
|
||||
done();
|
||||
}
|
64
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/sync/fs.js
generated
vendored
Normal file
64
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/sync/fs.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const call = require('../call');
|
||||
|
||||
/**
|
||||
* A facade around {@link fs.readdirSync} that allows it to be called
|
||||
* the same way as {@link fs.readdir}.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {function} callback
|
||||
*/
|
||||
exports.readdir = function (dir, callback) {
|
||||
// Make sure the callback is only called once
|
||||
callback = call.once(callback);
|
||||
|
||||
try {
|
||||
let items = fs.readdirSync(dir);
|
||||
callback(null, items);
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A facade around {@link fs.statSync} that allows it to be called
|
||||
* the same way as {@link fs.stat}.
|
||||
*
|
||||
* @param {string} path
|
||||
* @param {function} callback
|
||||
*/
|
||||
exports.stat = function (path, callback) {
|
||||
// Make sure the callback is only called once
|
||||
callback = call.once(callback);
|
||||
|
||||
try {
|
||||
let stats = fs.statSync(path);
|
||||
callback(null, stats);
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A facade around {@link fs.lstatSync} that allows it to be called
|
||||
* the same way as {@link fs.lstat}.
|
||||
*
|
||||
* @param {string} path
|
||||
* @param {function} callback
|
||||
*/
|
||||
exports.lstat = function (path, callback) {
|
||||
// Make sure the callback is only called once
|
||||
callback = call.once(callback);
|
||||
|
||||
try {
|
||||
let stats = fs.lstatSync(path);
|
||||
callback(null, stats);
|
||||
}
|
||||
catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
};
|
34
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/sync/index.js
generated
vendored
Normal file
34
website/functions/node_modules/@mrmlnc/readdir-enhanced/lib/sync/index.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = readdirSync;
|
||||
|
||||
const DirectoryReader = require('../directory-reader');
|
||||
|
||||
let syncFacade = {
|
||||
fs: require('./fs'),
|
||||
forEach: require('./for-each'),
|
||||
sync: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the buffered output from a synchronous {@link DirectoryReader}.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {object} [options]
|
||||
* @param {object} internalOptions
|
||||
*/
|
||||
function readdirSync (dir, options, internalOptions) {
|
||||
internalOptions.facade = syncFacade;
|
||||
|
||||
let reader = new DirectoryReader(dir, options, internalOptions);
|
||||
let stream = reader.stream;
|
||||
|
||||
let results = [];
|
||||
let data = stream.read();
|
||||
while (data !== null) {
|
||||
results.push(data);
|
||||
data = stream.read();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
Reference in New Issue
Block a user