initial add

This commit is contained in:
kake26 2025-06-12 23:43:12 -05:00
commit ccf2b60654
Signed by: kake26
GPG key ID: E0A989B571D1F99F
25 changed files with 4997 additions and 0 deletions

21
node_modules/readdirp/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

120
node_modules/readdirp/README.md generated vendored Normal file
View file

@ -0,0 +1,120 @@
# readdirp [![Weekly downloads](https://img.shields.io/npm/dw/readdirp.svg)](https://github.com/paulmillr/readdirp)
Recursive version of fs.readdir. Exposes a **stream API** (with small RAM & CPU footprint) and a **promise API**.
```sh
npm install readdirp
jsr add jsr:@paulmillr/readdirp
```
```javascript
// Use streams to achieve small RAM & CPU footprint.
// 1) Streams example with for-await.
import readdirp from 'readdirp';
for await (const entry of readdirp('.')) {
const {path} = entry;
console.log(`${JSON.stringify({path})}`);
}
// 2) Streams example, non for-await.
// Print out all JS files along with their size within the current folder & subfolders.
import readdirp from 'readdirp';
readdirp('.', {alwaysStat: true, fileFilter: (f) => f.basename.endsWith('.js')})
.on('data', (entry) => {
const {path, stats: {size}} = entry;
console.log(`${JSON.stringify({path, size})}`);
})
// Optionally call stream.destroy() in `warn()` in order to abort and cause 'close' to be emitted
.on('warn', error => console.error('non-fatal error', error))
.on('error', error => console.error('fatal error', error))
.on('end', () => console.log('done'));
// 3) Promise example. More RAM and CPU than streams / for-await.
import { readdirpPromise } from 'readdirp';
const files = await readdirpPromise('.');
console.log(files.map(file => file.path));
// Other options.
import readdirp from 'readdirp';
readdirp('test', {
fileFilter: (f) => f.basename.endsWith('.js'),
directoryFilter: (d) => d.basename !== '.git',
// directoryFilter: (di) => di.basename.length === 9
type: 'files_directories',
depth: 1
});
```
## API
`const stream = readdirp(root[, options])` — **Stream API**
- Reads given root recursively and returns a `stream` of [entry infos](#entryinfo)
- Optionally can be used like `for await (const entry of stream)` with node.js 10+ (`asyncIterator`).
- `on('data', (entry) => {})` [entry info](#entryinfo) for every file / dir.
- `on('warn', (error) => {})` non-fatal `Error` that prevents a file / dir from being processed. Example: inaccessible to the user.
- `on('error', (error) => {})` fatal `Error` which also ends the stream. Example: illegal options where passed.
- `on('end')` — we are done. Called when all entries were found and no more will be emitted.
- `on('close')` — stream is destroyed via `stream.destroy()`.
Could be useful if you want to manually abort even on a non fatal error.
At that point the stream is no longer `readable` and no more entries, warning or errors are emitted
- To learn more about streams, consult the very detailed [nodejs streams documentation](https://nodejs.org/api/stream.html)
or the [stream-handbook](https://github.com/substack/stream-handbook)
`const entries = await readdirp.promise(root[, options])`**Promise API**. Returns a list of [entry infos](#entryinfo).
First argument is awalys `root`, path in which to start reading and recursing into subdirectories.
### options
- `fileFilter`: filter to include or exclude files
- **Function**: a function that takes an entry info as a parameter and returns true to include or false to exclude the entry
- `directoryFilter`: filter to include/exclude directories found and to recurse into. Directories that do not pass a filter will not be recursed into.
- `depth: 5`: depth at which to stop recursing even if more subdirectories are found
- `type: 'files'`: determines if data events on the stream should be emitted for `'files'` (default), `'directories'`, `'files_directories'`, or `'all'`. Setting to `'all'` will also include entries for other types of file descriptors like character devices, unix sockets and named pipes.
- `alwaysStat: false`: always return `stats` property for every file. Default is `false`, readdirp will return `Dirent` entries. Setting it to `true` can double readdir execution time - use it only when you need file `size`, `mtime` etc. Cannot be enabled on node <10.10.0.
- `lstat: false`: include symlink entries in the stream along with files. When `true`, `fs.lstat` would be used instead of `fs.stat`
### `EntryInfo`
Has the following properties:
- `path: 'assets/javascripts/react.js'`: path to the file/directory (relative to given root)
- `fullPath: '/Users/dev/projects/app/assets/javascripts/react.js'`: full path to the file/directory found
- `basename: 'react.js'`: name of the file/directory
- `dirent: fs.Dirent`: built-in [dir entry object](https://nodejs.org/api/fs.html#fs_class_fs_dirent) - only with `alwaysStat: false`
- `stats: fs.Stats`: built in [stat object](https://nodejs.org/api/fs.html#fs_class_fs_stats) - only with `alwaysStat: true`
## Changelog
- 4.0 (Aug 25, 2024) rewritten in typescript, producing hybrid common.js / esm module.
- Remove glob support and all dependencies
- Make sure you're using `let {readdirp} = require('readdirp')` in common.js
- 3.5 (Oct 13, 2020) disallows recursive directory-based symlinks.
Before, it could have entered infinite loop.
- 3.4 (Mar 19, 2020) adds support for directory-based symlinks.
- 3.3 (Dec 6, 2019) stabilizes RAM consumption and enables perf management with `highWaterMark` option. Fixes race conditions related to `for-await` looping.
- 3.2 (Oct 14, 2019) improves performance by 250% and makes streams implementation more idiomatic.
- 3.1 (Jul 7, 2019) brings `bigint` support to `stat` output on Windows. This is backwards-incompatible for some cases. Be careful. It you use it incorrectly, you'll see "TypeError: Cannot mix BigInt and other types, use explicit conversions".
- 3.0 brings huge performance improvements and stream backpressure support.
- Upgrading 2.x to 3.x:
- Signature changed from `readdirp(options)` to `readdirp(root, options)`
- Replaced callback API with promise API.
- Renamed `entryType` option to `type`
- Renamed `entryType: 'both'` to `'files_directories'`
- `EntryInfo`
- Renamed `stat` to `stats`
- Emitted only when `alwaysStat: true`
- `dirent` is emitted instead of `stats` by default with `alwaysStat: false`
- Renamed `name` to `basename`
- Removed `parentDir` and `fullParentDir` properties
- Supported node.js versions:
- 4.x: node 14+
- 3.x: node 8+
- 2.x: node 0.6+
## License
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (<https://paulmillr.com>)
MIT License, see [LICENSE](LICENSE) file.

108
node_modules/readdirp/esm/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,108 @@
/**
* Recursive version of readdir. Exposes a streaming API and promise API.
* Streaming API allows to use a small amount of RAM.
*
* @module
* @example
```js
import readdirp from 'readdirp';
for await (const entry of readdirp('.')) {
const {path} = entry;
console.log(`${JSON.stringify({path})}`);
}
```
*/
/*! readdirp - MIT License (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com) */
import type { Stats, Dirent } from 'node:fs';
import { Readable } from 'node:stream';
/** Path in file system. */
export type Path = string;
/** Emitted entry. Contains relative & absolute path, basename, and either stats or dirent. */
export interface EntryInfo {
path: string;
fullPath: string;
stats?: Stats;
dirent?: Dirent;
basename: string;
}
/** Path or dir entries (files) */
export type PathOrDirent = Dirent | Path;
/** Filterer for files */
export type Tester = (entryInfo: EntryInfo) => boolean;
export type Predicate = string[] | string | Tester;
export declare const EntryTypes: {
readonly FILE_TYPE: "files";
readonly DIR_TYPE: "directories";
readonly FILE_DIR_TYPE: "files_directories";
readonly EVERYTHING_TYPE: "all";
};
export type EntryType = (typeof EntryTypes)[keyof typeof EntryTypes];
/**
* Options for readdirp.
* * type: files, directories, or both
* * lstat: whether to use symlink-friendly stat
* * depth: max depth
* * alwaysStat: whether to use stat (more resources) or dirent
* * highWaterMark: streaming param, specifies max amount of resources per entry
*/
export type ReaddirpOptions = {
root: string;
fileFilter?: Predicate;
directoryFilter?: Predicate;
type?: EntryType;
lstat?: boolean;
depth?: number;
alwaysStat?: boolean;
highWaterMark?: number;
};
/** Directory entry. Contains path, depth count, and files. */
export interface DirEntry {
files: PathOrDirent[];
depth: number;
path: Path;
}
/** Readable readdir stream, emitting new files as they're being listed. */
export declare class ReaddirpStream extends Readable {
parents: any[];
reading: boolean;
parent?: DirEntry;
_stat: Function;
_maxDepth: number;
_wantsDir: boolean;
_wantsFile: boolean;
_wantsEverything: boolean;
_root: Path;
_isDirent: boolean;
_statsProp: 'dirent' | 'stats';
_rdOptions: {
encoding: 'utf8';
withFileTypes: boolean;
};
_fileFilter: Tester;
_directoryFilter: Tester;
constructor(options?: Partial<ReaddirpOptions>);
_read(batch: number): Promise<void>;
_exploreDir(path: Path, depth: number): Promise<{
files: string[] | undefined;
depth: number;
path: string;
}>;
_formatEntry(dirent: PathOrDirent, path: Path): Promise<EntryInfo | undefined>;
_onError(err: Error): void;
_getEntryType(entry: EntryInfo): Promise<void | '' | 'file' | 'directory'>;
_includeAsFile(entry: EntryInfo): boolean | undefined;
}
/**
* Streaming version: Reads all files and directories in given root recursively.
* Consumes ~constant small amount of RAM.
* @param root Root directory
* @param options Options to specify root (start directory), filters and recursion depth
*/
export declare function readdirp(root: Path, options?: Partial<ReaddirpOptions>): ReaddirpStream;
/**
* Promise version: Reads all files and directories in given root recursively.
* Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.
* @returns array of paths and their entry infos
*/
export declare function readdirpPromise(root: Path, options?: Partial<ReaddirpOptions>): Promise<EntryInfo[]>;
export default readdirp;

257
node_modules/readdirp/esm/index.js generated vendored Normal file
View file

@ -0,0 +1,257 @@
import { stat, lstat, readdir, realpath } from 'node:fs/promises';
import { Readable } from 'node:stream';
import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from 'node:path';
export const EntryTypes = {
FILE_TYPE: 'files',
DIR_TYPE: 'directories',
FILE_DIR_TYPE: 'files_directories',
EVERYTHING_TYPE: 'all',
};
const defaultOptions = {
root: '.',
fileFilter: (_entryInfo) => true,
directoryFilter: (_entryInfo) => true,
type: EntryTypes.FILE_TYPE,
lstat: false,
depth: 2147483648,
alwaysStat: false,
highWaterMark: 4096,
};
Object.freeze(defaultOptions);
const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';
const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);
const ALL_TYPES = [
EntryTypes.DIR_TYPE,
EntryTypes.EVERYTHING_TYPE,
EntryTypes.FILE_DIR_TYPE,
EntryTypes.FILE_TYPE,
];
const DIR_TYPES = new Set([
EntryTypes.DIR_TYPE,
EntryTypes.EVERYTHING_TYPE,
EntryTypes.FILE_DIR_TYPE,
]);
const FILE_TYPES = new Set([
EntryTypes.EVERYTHING_TYPE,
EntryTypes.FILE_DIR_TYPE,
EntryTypes.FILE_TYPE,
]);
const isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);
const wantBigintFsStats = process.platform === 'win32';
const emptyFn = (_entryInfo) => true;
const normalizeFilter = (filter) => {
if (filter === undefined)
return emptyFn;
if (typeof filter === 'function')
return filter;
if (typeof filter === 'string') {
const fl = filter.trim();
return (entry) => entry.basename === fl;
}
if (Array.isArray(filter)) {
const trItems = filter.map((item) => item.trim());
return (entry) => trItems.some((f) => entry.basename === f);
}
return emptyFn;
};
/** Readable readdir stream, emitting new files as they're being listed. */
export class ReaddirpStream extends Readable {
constructor(options = {}) {
super({
objectMode: true,
autoDestroy: true,
highWaterMark: options.highWaterMark,
});
const opts = { ...defaultOptions, ...options };
const { root, type } = opts;
this._fileFilter = normalizeFilter(opts.fileFilter);
this._directoryFilter = normalizeFilter(opts.directoryFilter);
const statMethod = opts.lstat ? lstat : stat;
// Use bigint stats if it's windows and stat() supports options (node 10+).
if (wantBigintFsStats) {
this._stat = (path) => statMethod(path, { bigint: true });
}
else {
this._stat = statMethod;
}
this._maxDepth = opts.depth ?? defaultOptions.depth;
this._wantsDir = type ? DIR_TYPES.has(type) : false;
this._wantsFile = type ? FILE_TYPES.has(type) : false;
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
this._root = presolve(root);
this._isDirent = !opts.alwaysStat;
this._statsProp = this._isDirent ? 'dirent' : 'stats';
this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
// Launch stream with one parent, the root dir.
this.parents = [this._exploreDir(root, 1)];
this.reading = false;
this.parent = undefined;
}
async _read(batch) {
if (this.reading)
return;
this.reading = true;
try {
while (!this.destroyed && batch > 0) {
const par = this.parent;
const fil = par && par.files;
if (fil && fil.length > 0) {
const { path, depth } = par;
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));
const awaited = await Promise.all(slice);
for (const entry of awaited) {
if (!entry)
continue;
if (this.destroyed)
return;
const entryType = await this._getEntryType(entry);
if (entryType === 'directory' && this._directoryFilter(entry)) {
if (depth <= this._maxDepth) {
this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
}
if (this._wantsDir) {
this.push(entry);
batch--;
}
}
else if ((entryType === 'file' || this._includeAsFile(entry)) &&
this._fileFilter(entry)) {
if (this._wantsFile) {
this.push(entry);
batch--;
}
}
}
}
else {
const parent = this.parents.pop();
if (!parent) {
this.push(null);
break;
}
this.parent = await parent;
if (this.destroyed)
return;
}
}
}
catch (error) {
this.destroy(error);
}
finally {
this.reading = false;
}
}
async _exploreDir(path, depth) {
let files;
try {
files = await readdir(path, this._rdOptions);
}
catch (error) {
this._onError(error);
}
return { files, depth, path };
}
async _formatEntry(dirent, path) {
let entry;
const basename = this._isDirent ? dirent.name : dirent;
try {
const fullPath = presolve(pjoin(path, basename));
entry = { path: prelative(this._root, fullPath), fullPath, basename };
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
}
catch (err) {
this._onError(err);
return;
}
return entry;
}
_onError(err) {
if (isNormalFlowError(err) && !this.destroyed) {
this.emit('warn', err);
}
else {
this.destroy(err);
}
}
async _getEntryType(entry) {
// entry may be undefined, because a warning or an error were emitted
// and the statsProp is undefined
if (!entry && this._statsProp in entry) {
return '';
}
const stats = entry[this._statsProp];
if (stats.isFile())
return 'file';
if (stats.isDirectory())
return 'directory';
if (stats && stats.isSymbolicLink()) {
const full = entry.fullPath;
try {
const entryRealPath = await realpath(full);
const entryRealPathStats = await lstat(entryRealPath);
if (entryRealPathStats.isFile()) {
return 'file';
}
if (entryRealPathStats.isDirectory()) {
const len = entryRealPath.length;
if (full.startsWith(entryRealPath) && full.substr(len, 1) === psep) {
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
// @ts-ignore
recursiveError.code = RECURSIVE_ERROR_CODE;
return this._onError(recursiveError);
}
return 'directory';
}
}
catch (error) {
this._onError(error);
return '';
}
}
}
_includeAsFile(entry) {
const stats = entry && entry[this._statsProp];
return stats && this._wantsEverything && !stats.isDirectory();
}
}
/**
* Streaming version: Reads all files and directories in given root recursively.
* Consumes ~constant small amount of RAM.
* @param root Root directory
* @param options Options to specify root (start directory), filters and recursion depth
*/
export function readdirp(root, options = {}) {
// @ts-ignore
let type = options.entryType || options.type;
if (type === 'both')
type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility
if (type)
options.type = type;
if (!root) {
throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
}
else if (typeof root !== 'string') {
throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
}
else if (type && !ALL_TYPES.includes(type)) {
throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
}
options.root = root;
return new ReaddirpStream(options);
}
/**
* Promise version: Reads all files and directories in given root recursively.
* Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.
* @returns array of paths and their entry infos
*/
export function readdirpPromise(root, options = {}) {
return new Promise((resolve, reject) => {
const files = [];
readdirp(root, options)
.on('data', (entry) => files.push(entry))
.on('end', () => resolve(files))
.on('error', (error) => reject(error));
});
}
export default readdirp;

1
node_modules/readdirp/esm/package.json generated vendored Normal file
View file

@ -0,0 +1 @@
{ "type": "module", "sideEffects": false }

108
node_modules/readdirp/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,108 @@
/**
* Recursive version of readdir. Exposes a streaming API and promise API.
* Streaming API allows to use a small amount of RAM.
*
* @module
* @example
```js
import readdirp from 'readdirp';
for await (const entry of readdirp('.')) {
const {path} = entry;
console.log(`${JSON.stringify({path})}`);
}
```
*/
/*! readdirp - MIT License (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com) */
import type { Stats, Dirent } from 'node:fs';
import { Readable } from 'node:stream';
/** Path in file system. */
export type Path = string;
/** Emitted entry. Contains relative & absolute path, basename, and either stats or dirent. */
export interface EntryInfo {
path: string;
fullPath: string;
stats?: Stats;
dirent?: Dirent;
basename: string;
}
/** Path or dir entries (files) */
export type PathOrDirent = Dirent | Path;
/** Filterer for files */
export type Tester = (entryInfo: EntryInfo) => boolean;
export type Predicate = string[] | string | Tester;
export declare const EntryTypes: {
readonly FILE_TYPE: "files";
readonly DIR_TYPE: "directories";
readonly FILE_DIR_TYPE: "files_directories";
readonly EVERYTHING_TYPE: "all";
};
export type EntryType = (typeof EntryTypes)[keyof typeof EntryTypes];
/**
* Options for readdirp.
* * type: files, directories, or both
* * lstat: whether to use symlink-friendly stat
* * depth: max depth
* * alwaysStat: whether to use stat (more resources) or dirent
* * highWaterMark: streaming param, specifies max amount of resources per entry
*/
export type ReaddirpOptions = {
root: string;
fileFilter?: Predicate;
directoryFilter?: Predicate;
type?: EntryType;
lstat?: boolean;
depth?: number;
alwaysStat?: boolean;
highWaterMark?: number;
};
/** Directory entry. Contains path, depth count, and files. */
export interface DirEntry {
files: PathOrDirent[];
depth: number;
path: Path;
}
/** Readable readdir stream, emitting new files as they're being listed. */
export declare class ReaddirpStream extends Readable {
parents: any[];
reading: boolean;
parent?: DirEntry;
_stat: Function;
_maxDepth: number;
_wantsDir: boolean;
_wantsFile: boolean;
_wantsEverything: boolean;
_root: Path;
_isDirent: boolean;
_statsProp: 'dirent' | 'stats';
_rdOptions: {
encoding: 'utf8';
withFileTypes: boolean;
};
_fileFilter: Tester;
_directoryFilter: Tester;
constructor(options?: Partial<ReaddirpOptions>);
_read(batch: number): Promise<void>;
_exploreDir(path: Path, depth: number): Promise<{
files: string[] | undefined;
depth: number;
path: string;
}>;
_formatEntry(dirent: PathOrDirent, path: Path): Promise<EntryInfo | undefined>;
_onError(err: Error): void;
_getEntryType(entry: EntryInfo): Promise<void | '' | 'file' | 'directory'>;
_includeAsFile(entry: EntryInfo): boolean | undefined;
}
/**
* Streaming version: Reads all files and directories in given root recursively.
* Consumes ~constant small amount of RAM.
* @param root Root directory
* @param options Options to specify root (start directory), filters and recursion depth
*/
export declare function readdirp(root: Path, options?: Partial<ReaddirpOptions>): ReaddirpStream;
/**
* Promise version: Reads all files and directories in given root recursively.
* Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.
* @returns array of paths and their entry infos
*/
export declare function readdirpPromise(root: Path, options?: Partial<ReaddirpOptions>): Promise<EntryInfo[]>;
export default readdirp;

263
node_modules/readdirp/index.js generated vendored Normal file
View file

@ -0,0 +1,263 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReaddirpStream = exports.EntryTypes = void 0;
exports.readdirp = readdirp;
exports.readdirpPromise = readdirpPromise;
const promises_1 = require("node:fs/promises");
const node_stream_1 = require("node:stream");
const node_path_1 = require("node:path");
exports.EntryTypes = {
FILE_TYPE: 'files',
DIR_TYPE: 'directories',
FILE_DIR_TYPE: 'files_directories',
EVERYTHING_TYPE: 'all',
};
const defaultOptions = {
root: '.',
fileFilter: (_entryInfo) => true,
directoryFilter: (_entryInfo) => true,
type: exports.EntryTypes.FILE_TYPE,
lstat: false,
depth: 2147483648,
alwaysStat: false,
highWaterMark: 4096,
};
Object.freeze(defaultOptions);
const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';
const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);
const ALL_TYPES = [
exports.EntryTypes.DIR_TYPE,
exports.EntryTypes.EVERYTHING_TYPE,
exports.EntryTypes.FILE_DIR_TYPE,
exports.EntryTypes.FILE_TYPE,
];
const DIR_TYPES = new Set([
exports.EntryTypes.DIR_TYPE,
exports.EntryTypes.EVERYTHING_TYPE,
exports.EntryTypes.FILE_DIR_TYPE,
]);
const FILE_TYPES = new Set([
exports.EntryTypes.EVERYTHING_TYPE,
exports.EntryTypes.FILE_DIR_TYPE,
exports.EntryTypes.FILE_TYPE,
]);
const isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);
const wantBigintFsStats = process.platform === 'win32';
const emptyFn = (_entryInfo) => true;
const normalizeFilter = (filter) => {
if (filter === undefined)
return emptyFn;
if (typeof filter === 'function')
return filter;
if (typeof filter === 'string') {
const fl = filter.trim();
return (entry) => entry.basename === fl;
}
if (Array.isArray(filter)) {
const trItems = filter.map((item) => item.trim());
return (entry) => trItems.some((f) => entry.basename === f);
}
return emptyFn;
};
/** Readable readdir stream, emitting new files as they're being listed. */
class ReaddirpStream extends node_stream_1.Readable {
constructor(options = {}) {
super({
objectMode: true,
autoDestroy: true,
highWaterMark: options.highWaterMark,
});
const opts = { ...defaultOptions, ...options };
const { root, type } = opts;
this._fileFilter = normalizeFilter(opts.fileFilter);
this._directoryFilter = normalizeFilter(opts.directoryFilter);
const statMethod = opts.lstat ? promises_1.lstat : promises_1.stat;
// Use bigint stats if it's windows and stat() supports options (node 10+).
if (wantBigintFsStats) {
this._stat = (path) => statMethod(path, { bigint: true });
}
else {
this._stat = statMethod;
}
this._maxDepth = opts.depth ?? defaultOptions.depth;
this._wantsDir = type ? DIR_TYPES.has(type) : false;
this._wantsFile = type ? FILE_TYPES.has(type) : false;
this._wantsEverything = type === exports.EntryTypes.EVERYTHING_TYPE;
this._root = (0, node_path_1.resolve)(root);
this._isDirent = !opts.alwaysStat;
this._statsProp = this._isDirent ? 'dirent' : 'stats';
this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
// Launch stream with one parent, the root dir.
this.parents = [this._exploreDir(root, 1)];
this.reading = false;
this.parent = undefined;
}
async _read(batch) {
if (this.reading)
return;
this.reading = true;
try {
while (!this.destroyed && batch > 0) {
const par = this.parent;
const fil = par && par.files;
if (fil && fil.length > 0) {
const { path, depth } = par;
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));
const awaited = await Promise.all(slice);
for (const entry of awaited) {
if (!entry)
continue;
if (this.destroyed)
return;
const entryType = await this._getEntryType(entry);
if (entryType === 'directory' && this._directoryFilter(entry)) {
if (depth <= this._maxDepth) {
this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
}
if (this._wantsDir) {
this.push(entry);
batch--;
}
}
else if ((entryType === 'file' || this._includeAsFile(entry)) &&
this._fileFilter(entry)) {
if (this._wantsFile) {
this.push(entry);
batch--;
}
}
}
}
else {
const parent = this.parents.pop();
if (!parent) {
this.push(null);
break;
}
this.parent = await parent;
if (this.destroyed)
return;
}
}
}
catch (error) {
this.destroy(error);
}
finally {
this.reading = false;
}
}
async _exploreDir(path, depth) {
let files;
try {
files = await (0, promises_1.readdir)(path, this._rdOptions);
}
catch (error) {
this._onError(error);
}
return { files, depth, path };
}
async _formatEntry(dirent, path) {
let entry;
const basename = this._isDirent ? dirent.name : dirent;
try {
const fullPath = (0, node_path_1.resolve)((0, node_path_1.join)(path, basename));
entry = { path: (0, node_path_1.relative)(this._root, fullPath), fullPath, basename };
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
}
catch (err) {
this._onError(err);
return;
}
return entry;
}
_onError(err) {
if (isNormalFlowError(err) && !this.destroyed) {
this.emit('warn', err);
}
else {
this.destroy(err);
}
}
async _getEntryType(entry) {
// entry may be undefined, because a warning or an error were emitted
// and the statsProp is undefined
if (!entry && this._statsProp in entry) {
return '';
}
const stats = entry[this._statsProp];
if (stats.isFile())
return 'file';
if (stats.isDirectory())
return 'directory';
if (stats && stats.isSymbolicLink()) {
const full = entry.fullPath;
try {
const entryRealPath = await (0, promises_1.realpath)(full);
const entryRealPathStats = await (0, promises_1.lstat)(entryRealPath);
if (entryRealPathStats.isFile()) {
return 'file';
}
if (entryRealPathStats.isDirectory()) {
const len = entryRealPath.length;
if (full.startsWith(entryRealPath) && full.substr(len, 1) === node_path_1.sep) {
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
// @ts-ignore
recursiveError.code = RECURSIVE_ERROR_CODE;
return this._onError(recursiveError);
}
return 'directory';
}
}
catch (error) {
this._onError(error);
return '';
}
}
}
_includeAsFile(entry) {
const stats = entry && entry[this._statsProp];
return stats && this._wantsEverything && !stats.isDirectory();
}
}
exports.ReaddirpStream = ReaddirpStream;
/**
* Streaming version: Reads all files and directories in given root recursively.
* Consumes ~constant small amount of RAM.
* @param root Root directory
* @param options Options to specify root (start directory), filters and recursion depth
*/
function readdirp(root, options = {}) {
// @ts-ignore
let type = options.entryType || options.type;
if (type === 'both')
type = exports.EntryTypes.FILE_DIR_TYPE; // backwards-compatibility
if (type)
options.type = type;
if (!root) {
throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
}
else if (typeof root !== 'string') {
throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
}
else if (type && !ALL_TYPES.includes(type)) {
throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
}
options.root = root;
return new ReaddirpStream(options);
}
/**
* Promise version: Reads all files and directories in given root recursively.
* Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.
* @returns array of paths and their entry infos
*/
function readdirpPromise(root, options = {}) {
return new Promise((resolve, reject) => {
const files = [];
readdirp(root, options)
.on('data', (entry) => files.push(entry))
.on('end', () => resolve(files))
.on('error', (error) => reject(error));
});
}
exports.default = readdirp;

70
node_modules/readdirp/package.json generated vendored Normal file
View file

@ -0,0 +1,70 @@
{
"name": "readdirp",
"description": "Recursive version of fs.readdir with small RAM & CPU footprint.",
"version": "4.1.2",
"homepage": "https://github.com/paulmillr/readdirp",
"repository": {
"type": "git",
"url": "git://github.com/paulmillr/readdirp.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/paulmillr/readdirp/issues"
},
"author": "Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
"contributors": [
"Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
"Paul Miller (https://paulmillr.com)"
],
"engines": {
"node": ">= 14.18.0"
},
"files": [
"index.js",
"index.d.ts",
"index.d.ts.map",
"index.js.map",
"esm"
],
"main": "./index.js",
"module": "./esm/index.js",
"types": "./index.d.ts",
"exports": {
".": {
"import": "./esm/index.js",
"require": "./index.js"
}
},
"sideEffects": false,
"keywords": [
"recursive",
"fs",
"stream",
"streams",
"readdir",
"filesystem",
"find",
"filter"
],
"scripts": {
"build": "tsc && tsc -p tsconfig.cjs.json",
"lint": "prettier --check index.ts test/index.test.js",
"format": "prettier --write index.ts test/index.test.js",
"test": "node test/index.test.js",
"test:coverage": "c8 node test/index.test.js"
},
"devDependencies": {
"@paulmillr/jsbt": "0.3.1",
"@types/node": "20.14.8",
"c8": "10.1.3",
"chai": "4.3.4",
"chai-subset": "1.6.0",
"micro-should": "0.5.0",
"prettier": "3.1.1",
"typescript": "5.5.2"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
}