run npm install to generate a package lock
This commit is contained in:
16
node_modules/tiny-readdir/src/constants.ts
generated
vendored
Normal file
16
node_modules/tiny-readdir/src/constants.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
/* IMPORT */
|
||||
|
||||
import type {Callback} from './types';
|
||||
|
||||
/* MAIN */
|
||||
|
||||
const NOOP_PROMISE_LIKE = {
|
||||
then: ( fn: Callback ) => {
|
||||
fn ();
|
||||
}
|
||||
};
|
||||
|
||||
/* EXPORT */
|
||||
|
||||
export {NOOP_PROMISE_LIKE};
|
||||
257
node_modules/tiny-readdir/src/index.ts
generated
vendored
Executable file
257
node_modules/tiny-readdir/src/index.ts
generated
vendored
Executable file
@@ -0,0 +1,257 @@
|
||||
|
||||
/* IMPORT */
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import makeCounterPromise from 'promise-make-counter';
|
||||
import {NOOP_PROMISE_LIKE} from './constants';
|
||||
import {castArray, isFunction} from './utils';
|
||||
import type {Dirent, Options, ResultDirectory, ResultDirectories, Result} from './types';
|
||||
|
||||
/* MAIN */
|
||||
|
||||
//TODO: Streamline the type of dirmaps
|
||||
|
||||
const readdir = ( rootPath: string, options?: Options ): Promise<Result> => {
|
||||
|
||||
const followSymlinks = options?.followSymlinks ?? false;
|
||||
const maxDepth = options?.depth ?? Infinity;
|
||||
const maxPaths = options?.limit ?? Infinity;
|
||||
const ignore = options?.ignore ?? [];
|
||||
const ignores = castArray ( ignore ).map ( ignore => isFunction ( ignore ) ? ignore : ( targetPath: string ) => ignore.test ( targetPath ) );
|
||||
const isIgnored = ( targetPath: string ) => ignores.some ( ignore => ignore ( targetPath ) );
|
||||
const signal = options?.signal ?? { aborted: false };
|
||||
const onDirents = options?.onDirents || (() => {});
|
||||
const directories: string[] = [];
|
||||
const directoriesNames: Set<string> = new Set ();
|
||||
const directoriesNamesToPaths: Record<string, string[]> = {};
|
||||
const files: string[] = [];
|
||||
const filesNames: Set<string> = new Set ();
|
||||
const filesNamesToPaths: Record<string, string[]> = {};
|
||||
const symlinks: string[] = [];
|
||||
const symlinksNames: Set<string> = new Set ();
|
||||
const symlinksNamesToPaths: Record<string, string[]> = {};
|
||||
const map: ResultDirectories = {};
|
||||
const visited = new Set<string> ();
|
||||
const resultEmpty: Result = { directories: [], directoriesNames: new Set (), directoriesNamesToPaths: {}, files: [], filesNames: new Set (), filesNamesToPaths: {}, symlinks: [], symlinksNames: new Set (), symlinksNamesToPaths: {}, map: {} };
|
||||
const result: Result = { directories, directoriesNames, directoriesNamesToPaths, files, filesNames, filesNamesToPaths, symlinks, symlinksNames, symlinksNamesToPaths, map };
|
||||
const {promise, increment, decrement} = makeCounterPromise ();
|
||||
|
||||
let foundPaths = 0;
|
||||
|
||||
const handleDirectory = ( dirmap: ResultDirectory, subPath: string, name: string, depth: number ): void => {
|
||||
|
||||
if ( visited.has ( subPath ) ) return;
|
||||
|
||||
if ( foundPaths >= maxPaths ) return;
|
||||
|
||||
foundPaths += 1;
|
||||
dirmap.directories.push ( subPath );
|
||||
dirmap.directoriesNames.add ( name );
|
||||
// dirmap.directoriesNamesToPaths.propertyIsEnumerable(name) || ( dirmap.directoriesNamesToPaths[name] = [] );
|
||||
// dirmap.directoriesNamesToPaths[name].push ( subPath );
|
||||
directories.push ( subPath );
|
||||
directoriesNames.add ( name );
|
||||
directoriesNamesToPaths.propertyIsEnumerable(name) || ( directoriesNamesToPaths[name] = [] );
|
||||
directoriesNamesToPaths[name].push ( subPath );
|
||||
visited.add ( subPath );
|
||||
|
||||
if ( depth >= maxDepth ) return;
|
||||
|
||||
if ( foundPaths >= maxPaths ) return;
|
||||
|
||||
populateResultFromPath ( subPath, depth + 1 );
|
||||
|
||||
};
|
||||
|
||||
const handleFile = ( dirmap: ResultDirectory, subPath: string, name: string ): void => {
|
||||
|
||||
if ( visited.has ( subPath ) ) return;
|
||||
|
||||
if ( foundPaths >= maxPaths ) return;
|
||||
|
||||
foundPaths += 1;
|
||||
dirmap.files.push ( subPath );
|
||||
dirmap.filesNames.add ( name );
|
||||
// dirmap.filesNamesToPaths.propertyIsEnumerable(name) || ( dirmap.filesNamesToPaths[name] = [] );
|
||||
// dirmap.filesNamesToPaths[name].push ( subPath );
|
||||
files.push ( subPath );
|
||||
filesNames.add ( name );
|
||||
filesNamesToPaths.propertyIsEnumerable(name) || ( filesNamesToPaths[name] = [] );
|
||||
filesNamesToPaths[name].push ( subPath );
|
||||
visited.add ( subPath );
|
||||
|
||||
};
|
||||
|
||||
const handleSymlink = ( dirmap: ResultDirectory, subPath: string, name: string, depth: number ): void => {
|
||||
|
||||
if ( visited.has ( subPath ) ) return;
|
||||
|
||||
if ( foundPaths >= maxPaths ) return;
|
||||
|
||||
foundPaths += 1;
|
||||
dirmap.symlinks.push ( subPath );
|
||||
dirmap.symlinksNames.add ( name );
|
||||
// dirmap.symlinksNamesToPaths.propertyIsEnumerable(name) || ( dirmap.symlinksNamesToPaths[name] = [] );
|
||||
// dirmap.symlinksNamesToPaths[name].push ( subPath );
|
||||
symlinks.push ( subPath );
|
||||
symlinksNames.add ( name );
|
||||
symlinksNamesToPaths.propertyIsEnumerable(name) || ( symlinksNamesToPaths[name] = [] );
|
||||
symlinksNamesToPaths[name].push ( subPath );
|
||||
visited.add ( subPath );
|
||||
|
||||
if ( !followSymlinks ) return;
|
||||
|
||||
if ( depth >= maxDepth ) return;
|
||||
|
||||
if ( foundPaths >= maxPaths ) return;
|
||||
|
||||
populateResultFromSymlink ( subPath, depth + 1 );
|
||||
|
||||
};
|
||||
|
||||
const handleStat = ( dirmap: ResultDirectory, rootPath: string, name: string, stat: fs.Stats, depth: number ): void => {
|
||||
|
||||
if ( signal.aborted ) return;
|
||||
|
||||
if ( isIgnored ( rootPath ) ) return;
|
||||
|
||||
if ( stat.isDirectory () ) {
|
||||
|
||||
handleDirectory ( dirmap, rootPath, name, depth );
|
||||
|
||||
} else if ( stat.isFile () ) {
|
||||
|
||||
handleFile ( dirmap, rootPath, name );
|
||||
|
||||
} else if ( stat.isSymbolicLink () ) {
|
||||
|
||||
handleSymlink ( dirmap, rootPath, name, depth );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const handleDirent = ( dirmap: ResultDirectory, rootPath: string, dirent: fs.Dirent, depth: number ): void => {
|
||||
|
||||
if ( signal.aborted ) return;
|
||||
|
||||
const separator = ( rootPath === path.sep ) ? '' : path.sep;
|
||||
const name = dirent.name;
|
||||
const subPath = `${rootPath}${separator}${name}`;
|
||||
|
||||
if ( isIgnored ( subPath ) ) return;
|
||||
|
||||
if ( dirent.isDirectory () ) {
|
||||
|
||||
handleDirectory ( dirmap, subPath, name, depth );
|
||||
|
||||
} else if ( dirent.isFile () ) {
|
||||
|
||||
handleFile ( dirmap, subPath, name );
|
||||
|
||||
} else if ( dirent.isSymbolicLink () ) {
|
||||
|
||||
handleSymlink ( dirmap, subPath, name, depth );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const handleDirents = ( dirmap: ResultDirectory, rootPath: string, dirents: fs.Dirent[], depth: number ): void => {
|
||||
|
||||
for ( let i = 0, l = dirents.length; i < l; i++ ) {
|
||||
|
||||
handleDirent ( dirmap, rootPath, dirents[i], depth );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const populateResultFromPath = ( rootPath: string, depth: number ): void => {
|
||||
|
||||
if ( signal.aborted ) return;
|
||||
|
||||
if ( depth > maxDepth ) return;
|
||||
|
||||
if ( foundPaths >= maxPaths ) return;
|
||||
|
||||
increment ();
|
||||
|
||||
fs.readdir ( rootPath, { withFileTypes: true }, ( error, dirents ) => {
|
||||
|
||||
if ( error ) return decrement ();
|
||||
|
||||
if ( signal.aborted ) return decrement ();
|
||||
|
||||
if ( !dirents.length ) return decrement ();
|
||||
|
||||
const promise = onDirents ( dirents ) || NOOP_PROMISE_LIKE;
|
||||
|
||||
promise.then ( () => {
|
||||
|
||||
const dirmap = map[rootPath] = { directories: [], directoriesNames: new Set (), directoriesNamesToPaths: {}, files: [], filesNames: new Set (), filesNamesToPaths: {}, symlinks: [], symlinksNames: new Set (), symlinksNamesToPaths: {} };
|
||||
|
||||
handleDirents ( dirmap, rootPath, dirents, depth );
|
||||
|
||||
decrement ();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const populateResultFromSymlink = ( rootPath: string, depth: number ): void => {
|
||||
|
||||
increment ();
|
||||
|
||||
fs.realpath ( rootPath, ( error, realPath ) => {
|
||||
|
||||
if ( error ) return decrement ();
|
||||
|
||||
if ( signal.aborted ) return decrement ();
|
||||
|
||||
fs.stat ( realPath, ( error, stat ) => {
|
||||
|
||||
if ( error ) return decrement ();
|
||||
|
||||
if ( signal.aborted ) return decrement ();
|
||||
|
||||
const name = path.basename ( realPath );
|
||||
const dirmap = map[rootPath] = { directories: [], directoriesNames: new Set (), directoriesNamesToPaths: {}, files: [], filesNames: new Set (), filesNamesToPaths: {}, symlinks: [], symlinksNames: new Set (), symlinksNamesToPaths: {} };
|
||||
|
||||
handleStat ( dirmap, realPath, name, stat, depth );
|
||||
|
||||
decrement ();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
const getResult = async ( rootPath: string, depth: number = 1 ): Promise<Result> => {
|
||||
|
||||
rootPath = path.normalize ( rootPath );
|
||||
|
||||
visited.add ( rootPath );
|
||||
|
||||
populateResultFromPath ( rootPath, depth );
|
||||
|
||||
await promise;
|
||||
|
||||
if ( signal.aborted ) return resultEmpty;
|
||||
|
||||
return result;
|
||||
|
||||
};
|
||||
|
||||
return getResult ( rootPath );
|
||||
|
||||
};
|
||||
|
||||
/* EXPORT */
|
||||
|
||||
export default readdir;
|
||||
export type {Dirent, Options, ResultDirectory, ResultDirectories, Result};
|
||||
55
node_modules/tiny-readdir/src/types.ts
generated
vendored
Normal file
55
node_modules/tiny-readdir/src/types.ts
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
/* HELPERS */
|
||||
|
||||
type Callback = () => void;
|
||||
|
||||
type ArrayMaybe<T> = T[] | T;
|
||||
|
||||
type PromiseMaybe<T> = Promise<T> | T;
|
||||
|
||||
/* MAIN */
|
||||
|
||||
type Dirent = {
|
||||
isFile: () => boolean,
|
||||
isDirectory: () => boolean,
|
||||
isBlockDevice: () => boolean,
|
||||
isCharacterDevice: () => boolean,
|
||||
isSymbolicLink: () => boolean,
|
||||
isFIFO: () => boolean,
|
||||
isSocket: () => boolean,
|
||||
name: string,
|
||||
path: string
|
||||
};
|
||||
|
||||
type Options = {
|
||||
depth?: number,
|
||||
limit?: number,
|
||||
followSymlinks?: boolean,
|
||||
ignore?: ArrayMaybe<(( targetPath: string ) => boolean) | RegExp>,
|
||||
signal?: { aborted: boolean },
|
||||
onDirents?: ( dirents: Dirent[] ) => PromiseMaybe<undefined>
|
||||
};
|
||||
|
||||
type ResultDirectory = {
|
||||
directories: string[],
|
||||
directoriesNames: Set<string>,
|
||||
directoriesNamesToPaths: Record<string, string[]>,
|
||||
files: string[],
|
||||
filesNames: Set<string>,
|
||||
filesNamesToPaths: Record<string, string[]>,
|
||||
symlinks: string[],
|
||||
symlinksNames: Set<string>,
|
||||
symlinksNamesToPaths: Record<string, string[]>
|
||||
};
|
||||
|
||||
type ResultDirectories = {
|
||||
[path: string]: ResultDirectory
|
||||
};
|
||||
|
||||
type Result = ResultDirectory & {
|
||||
map: ResultDirectories
|
||||
};
|
||||
|
||||
/* EXPORT */
|
||||
|
||||
export type {Callback, PromiseMaybe, Dirent, Options, ResultDirectory, ResultDirectories, Result};
|
||||
18
node_modules/tiny-readdir/src/utils.ts
generated
vendored
Normal file
18
node_modules/tiny-readdir/src/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
/* MAIN */
|
||||
|
||||
const castArray = <T> ( value: T[] | T ): T[] => {
|
||||
|
||||
return Array.isArray ( value ) ? value : [value];
|
||||
|
||||
};
|
||||
|
||||
const isFunction = ( value: unknown ): value is Function => {
|
||||
|
||||
return ( typeof value === 'function' );
|
||||
|
||||
};
|
||||
|
||||
/* EXPORT */
|
||||
|
||||
export {castArray, isFunction};
|
||||
Reference in New Issue
Block a user