pax_global_header00006660000000000000000000000064144312431670014517gustar00rootroot0000000000000052 comment=e3f947f9341a795d43765f359d13a796053c1619 isaacs-path-scurry-06957ec/000077500000000000000000000000001443124316700156055ustar00rootroot00000000000000isaacs-path-scurry-06957ec/.github/000077500000000000000000000000001443124316700171455ustar00rootroot00000000000000isaacs-path-scurry-06957ec/.github/FUNDING.yml000066400000000000000000000001001443124316700207510ustar00rootroot00000000000000# These are supported funding model platforms github: [isaacs] isaacs-path-scurry-06957ec/.github/workflows/000077500000000000000000000000001443124316700212025ustar00rootroot00000000000000isaacs-path-scurry-06957ec/.github/workflows/ci.yml000066400000000000000000000014241443124316700223210ustar00rootroot00000000000000name: CI on: [push, pull_request] jobs: build: strategy: matrix: node-version: [v14.x, v16.x, v18.x, v19.x] platform: - os: ubuntu-latest shell: bash - os: macos-latest shell: bash - os: windows-latest shell: powershell fail-fast: false runs-on: ${{ matrix.platform.os }} defaults: run: shell: ${{ matrix.platform.shell }} steps: - name: Checkout Repository uses: actions/checkout@v3 - name: Use Nodejs ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Install dependencies run: npm install - name: Run Tests run: npm test -- -c -t0 isaacs-path-scurry-06957ec/.github/workflows/commit-if-modified.sh000066400000000000000000000004321443124316700251770ustar00rootroot00000000000000#!/usr/bin/env bash git config --global user.email "$1" shift git config --global user.name "$1" shift message="$1" shift if [ $(git status --porcelain "$@" | egrep '^ M' | wc -l) -gt 0 ]; then git add "$@" git commit -m "$message" git push || git pull --rebase git push fi isaacs-path-scurry-06957ec/.github/workflows/copyright-year.sh000066400000000000000000000010011443124316700244740ustar00rootroot00000000000000#!/usr/bin/env bash dir=${1:-$PWD} dates=($(git log --date=format:%Y --pretty=format:'%ad' --reverse | sort | uniq)) if [ "${#dates[@]}" -eq 1 ]; then datestr="${dates}" else datestr="${dates}-${dates[${#dates[@]}-1]}" fi stripDate='s/^((.*)Copyright\b(.*?))((?:,\s*)?(([0-9]{4}\s*-\s*[0-9]{4})|(([0-9]{4},\s*)*[0-9]{4})))(?:,)?\s*(.*)\n$/$1$9\n/g' addDate='s/^.*Copyright(?:\s*\(c\))? /Copyright \(c\) '$datestr' /g' for l in $dir/LICENSE*; do perl -pi -e "$stripDate" $l perl -pi -e "$addDate" $l done isaacs-path-scurry-06957ec/.github/workflows/isaacs-makework.yml000066400000000000000000000021461443124316700250110ustar00rootroot00000000000000name: "various tidying up tasks to silence nagging" on: push: branches: - main workflow_dispatch: jobs: makework: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 - name: Use Node.js uses: actions/setup-node@v2.1.4 with: node-version: 16.x - name: put repo in package.json run: node .github/workflows/package-json-repo.js - name: check in package.json if modified run: | bash -x .github/workflows/commit-if-modified.sh \ "package-json-repo-bot@example.com" \ "package.json Repo Bot" \ "chore: add repo to package.json" \ package.json package-lock.json - name: put all dates in license copyright line run: bash .github/workflows/copyright-year.sh - name: check in licenses if modified run: | bash .github/workflows/commit-if-modified.sh \ "license-year-bot@example.com" \ "License Year Bot" \ "chore: add copyright year to license" \ LICENSE* isaacs-path-scurry-06957ec/.github/workflows/package-json-repo.js000066400000000000000000000010561443124316700250470ustar00rootroot00000000000000#!/usr/bin/env node const pf = require.resolve(`${process.cwd()}/package.json`) const pj = require(pf) if (!pj.repository && process.env.GITHUB_REPOSITORY) { const fs = require('fs') const server = process.env.GITHUB_SERVER_URL || 'https://github.com' const repo = `${server}/${process.env.GITHUB_REPOSITORY}` pj.repository = repo const json = fs.readFileSync(pf, 'utf8') const match = json.match(/^\s*\{[\r\n]+([ \t]*)"/) const indent = match[1] const output = JSON.stringify(pj, null, indent || 2) + '\n' fs.writeFileSync(pf, output) } isaacs-path-scurry-06957ec/.github/workflows/static.yml000066400000000000000000000024131443124316700232140ustar00rootroot00000000000000# Simple workflow for deploying static content to GitHub Pages name: Deploy static content to Pages on: # Runs on pushes targeting the default branch push: branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow one concurrent deployment concurrency: group: "pages" cancel-in-progress: true jobs: # Single deploy job since we're just deploying deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Use Nodejs ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: 18.x - name: Install dependencies run: npm install - name: Generate typedocs run: npm run typedoc - name: Setup Pages uses: actions/configure-pages@v3 - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: path: './docs' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v1 isaacs-path-scurry-06957ec/.gitignore000066400000000000000000000004521443124316700175760ustar00rootroot00000000000000# ignore most things, include a handful of others /* /.* !/src !/docs !/package.json !/package-lock.json !/README.md !/CONTRIBUTING.md !/LICENSE{,.*} !/CHANGELOG.md !/example !/scripts !/tap-snapshots !/test !/.gitignore !/.github !/.prettierignore !/.gitattributes !/tsconfig*.json !/typedoc.json isaacs-path-scurry-06957ec/.prettierignore000066400000000000000000000001501443124316700206440ustar00rootroot00000000000000/node_modules /example /.github /dist .env /tap-snapshots /.nyc_output /coverage /benchmark /LICENSE.md isaacs-path-scurry-06957ec/CHANGELOG.md000066400000000000000000000017361443124316700174250ustar00rootroot00000000000000# churnge loog ## 1.9 - Add `path` for compatibility with Node v20 Dirent ## 1.8 - add `PathScurry.chdir` method ## 1.7 - Add `Path.fullpathPosix()`, `Path.relativePosix()`, `PathScurry.resolvePosix()`, `PathScurry.relativePosix()`, for getting posix style paths on Windows. ## 1.6 - Allow overriding the default fs with custom methods - make Stats fields available after lstat() - add depth() method - add declarationMap to tsconfig ## 1.5 - support file:// url as cwd - handle in-flight readdirCB, readdir ## 1.4 - add isNamed() for case and unicode normalization ## 1.3 - expose calledReaddir, isENOENT, and canReadlink methods ## 1.2.0 - Add Path.relative(), PathScurry.relative() ## 1.1 - Properly limit return value types based on withFileTypes - Benchmarks take too long for GHA, sadly - correct benchmark link, provide output while generating - run benchmarks as part of docs build - Support calling blah({opts}) to operate on cwd ## 1.0.0 - Initial version isaacs-path-scurry-06957ec/LICENSE.md000066400000000000000000000030201443124316700172040ustar00rootroot00000000000000# Blue Oak Model License Version 1.0.0 ## Purpose This license gives everyone as much permission to work with this software as possible, while protecting contributors from liability. ## Acceptance In order to receive this license, you must agree to its rules. The rules of this license are both obligations under that agreement and conditions to your license. You must not do anything with this software that triggers a rule that you cannot or will not follow. ## Copyright Each contributor licenses you to do everything with this software that would otherwise infringe that contributor's copyright in it. ## Notices You must ensure that everyone who gets a copy of any part of this software from you, with or without changes, also gets the text of this license or a link to . ## Excuse If anyone notifies you in writing that you have not complied with [Notices](#notices), you can keep your license by taking all practical steps to comply within 30 days after the notice. If you do not do so, your license ends immediately. ## Patent Each contributor licenses you to do everything with this software that would otherwise infringe any patent claims they can license or become able to license. ## Reliability No contributor can revoke this license. ## No Liability ***As far as the law allows, this software comes as is, without any warranty or condition, and no contributor will be liable to anyone for any damages related to this software or this license, under any kind of legal claim.*** isaacs-path-scurry-06957ec/README.md000066400000000000000000000521751443124316700170760ustar00rootroot00000000000000# path-scurry Extremely high performant utility for building tools that read the file system, minimizing filesystem and path string munging operations to the greatest degree possible. ## Ugh, yet another file traversal thing on npm? Yes. None of the existing ones gave me exactly what I wanted. ## Well what is it you wanted? While working on [glob](http://npm.im/glob), I found that I needed a module to very efficiently manage the traversal over a folder tree, such that: 1. No `readdir()` or `stat()` would ever be called on the same file or directory more than one time. 2. No `readdir()` calls would be made if we can be reasonably sure that the path is not a directory. (Ie, a previous `readdir()` or `stat()` covered the path, and `ent.isDirectory()` is false.) 3. `path.resolve()`, `dirname()`, `basename()`, and other string-parsing/munging operations are be minimized. This means it has to track "provisional" child nodes that may not exist (and if we find that they _don't_ exist, store that information as well, so we don't have to ever check again). 4. The API is not limited to use as a stream/iterator/etc. There are many cases where an API like node's `fs` is preferrable. 5. It's more important to prevent excess syscalls than to be up to date, but it should be smart enough to know what it _doesn't_ know, and go get it seamlessly when requested. 6. Do not blow up the JS heap allocation if operating on a directory with a huge number of entries. 7. Handle all the weird aspects of Windows paths, like UNC paths and drive letters and wrongway slashes, so that the consumer can return canonical platform-specific paths without having to parse or join or do any error-prone string munging. ## PERFORMANCE JavaScript people throw around the word "blazing" a lot. I hope that this module doesn't blaze anyone. But it does go very fast, in the cases it's optimized for, if used properly. PathScurry provides ample opportunities to get extremely good performance, as well as several options to trade performance for convenience. Benchmarks can be run by executing `npm run bench`. As is always the case, doing more means going slower, doing less means going faster, and there are trade offs between speed and memory usage. PathScurry makes heavy use of [LRUCache](http://npm.im/lru-cache) to efficiently cache whatever it can, and `Path` objects remain in the graph for the lifetime of the walker, so repeated calls with a single PathScurry object will be extremely fast. However, adding items to a cold cache means "doing more", so in those cases, we pay a price. Nothing is free, but every effort has been made to reduce costs wherever possible. Also, note that a "cache as long as possible" approach means that changes to the filesystem may not be reflected in the results of repeated PathScurry operations. For resolving string paths, `PathScurry` ranges from 5-50 times faster than `path.resolve` on repeated resolutions, but around 100 to 1000 times _slower_ on the first resolution. If your program is spending a lot of time resolving the _same_ paths repeatedly (like, thousands or millions of times), then this can be beneficial. But both implementations are pretty fast, and speeding up an infrequent operation from 4µs to 400ns is not going to move the needle on your app's performance. For walking file system directory trees, a lot depends on how often a given PathScurry object will be used, and also on the walk method used. With default settings on a folder tree of 100,000 items, consisting of around a 10-to-1 ratio of normal files to directories, PathScurry performs comparably to [@nodelib/fs.walk](http://npm.im/@nodelib/fs.walk), which is the fastest and most reliable file system walker I could find. As far as I can tell, it's almost impossible to go much faster in a Node.js program, just based on how fast you can push syscalls out to the fs thread pool. On my machine, that is about 1000-1200 completed walks per second for async or stream walks, and around 500-600 walks per second synchronously. In the warm cache state, PathScurry's performance increases around 4x for async `for await` iteration, 10-15x faster for streams and synchronous `for of` iteration, and anywhere from 30x to 80x faster for the rest. ``` # walk 100,000 fs entries, 10/1 file/dir ratio # operations / ms New PathScurry object | Reuse PathScurry object stream: 1112.589 | 13974.917 sync stream: 492.718 | 15028.343 async walk: 1095.648 | 32706.395 sync walk: 527.632 | 46129.772 async iter: 1288.821 | 5045.510 sync iter: 498.496 | 17920.746 ``` A hand-rolled walk calling `entry.readdir()` and recursing through the entries can benefit even more from caching, with greater flexibility and without the overhead of streams or generators. The cold cache state is still limited by the costs of file system operations, but with a warm cache, the only bottleneck is CPU speed and VM optimizations. Of course, in that case, some care must be taken to ensure that you don't lose performance as a result of silly mistakes, like calling `readdir()` on entries that you know are not directories. ``` # manual recursive iteration functions cold cache | warm cache async: 1164.901 | 17923.320 cb: 1101.127 | 40999.344 zalgo: 1082.240 | 66689.936 sync: 526.935 | 87097.591 ``` In this case, the speed improves by around 10-20x in the async case, 40x in the case of using `entry.readdirCB` with protections against synchronous callbacks, and 50-100x with callback deferrals disabled, and _several hundred times faster_ for synchronous iteration. If you can think of a case that is not covered in these benchmarks, or an implementation that performs significantly better than PathScurry, please [let me know](https://github.com/isaacs/path-scurry/issues). ## USAGE ```ts // hybrid module, load with either method import { PathScurry, Path } from 'path-scurry' // or: const { PathScurry, Path } = require('path-scurry') // very simple example, say we want to find and // delete all the .DS_Store files in a given path // note that the API is very similar to just a // naive walk with fs.readdir() import { unlink } from 'fs/promises' // easy way, iterate over the directory and do the thing const pw = new PathScurry(process.cwd()) for await (const entry of pw) { if (entry.isFile() && entry.name === '.DS_Store') { unlink(entry.fullpath()) } } // here it is as a manual recursive method const walk = async (entry: Path) => { const promises: Promise = [] // readdir doesn't throw on non-directories, it just doesn't // return any entries, to save stack trace costs. // Items are returned in arbitrary unsorted order for (const child of await pw.readdir(entry)) { // each child is a Path object if (child.name === '.DS_Store' && child.isFile()) { // could also do pw.resolve(entry, child.name), // just like fs.readdir walking, but .fullpath is // a *slightly* more efficient shorthand. promises.push(unlink(child.fullpath())) } else if (child.isDirectory()) { promises.push(walk(child)) } } return Promise.all(promises) } walk(pw.cwd).then(() => { console.log('all .DS_Store files removed') }) const pw2 = new PathScurry('/a/b/c') // pw2.cwd is the Path for /a/b/c const relativeDir = pw2.cwd.resolve('../x') // Path entry for '/a/b/x' const relative2 = pw2.cwd.resolve('/a/b/d/../x') // same path, same entry assert.equal(relativeDir, relative2) ``` ## API [Full TypeDoc API](https://isaacs.github.io/path-scurry) There are platform-specific classes exported, but for the most part, the default `PathScurry` and `Path` exports are what you most likely need, unless you are testing behavior for other platforms. Intended public API is documented here, but the full documentation does include internal types, which should not be accessed directly. ### Interface `PathScurryOpts` The type of the `options` argument passed to the `PathScurry` constructor. - `nocase`: Boolean indicating that file names should be compared case-insensitively. Defaults to `true` on darwin and win32 implementations, `false` elsewhere. **Warning** Performing case-insensitive matching on a case-sensitive filesystem will result in occasionally very bizarre behavior. Performing case-sensitive matching on a case-insensitive filesystem may negatively impact performance. - `childrenCacheSize`: Number of child entries to cache, in order to speed up `resolve()` and `readdir()` calls. Defaults to `16 * 1024` (ie, `16384`). Setting it to a higher value will run the risk of JS heap allocation errors on large directory trees. Setting it to `256` or smaller will significantly reduce the construction time and data consumption overhead, but with the downside of operations being slower on large directory trees. Setting it to `0` will mean that effectively no operations are cached, and this module will be roughly the same speed as `fs` for file system operations, and _much_ slower than `path.resolve()` for repeated path resolution. - `fs` An object that will be used to override the default `fs` methods. Any methods that are not overridden will use Node's built-in implementations. - lstatSync - readdir (callback `withFileTypes` Dirent variant, used for readdirCB and most walks) - readdirSync - readlinkSync - realpathSync - promises: Object containing the following async methods: - lstat - readdir (Dirent variant only) - readlink - realpath ### Interface `WalkOptions` The options object that may be passed to all walk methods. - `withFileTypes`: Boolean, default true. Indicates that `Path` objects should be returned. Set to `false` to get string paths instead. - `follow`: Boolean, default false. Attempt to read directory entries from symbolic links. Otherwise, only actual directories are traversed. Regardless of this setting, a given target path will only ever be walked once, meaning that a symbolic link to a previously traversed directory will never be followed. Setting this imposes a slight performance penalty, because `readlink` must be called on all symbolic links encountered, in order to avoid infinite cycles. - `filter`: Function `(entry: Path) => boolean`. If provided, will prevent the inclusion of any entry for which it returns a falsey value. This will not prevent directories from being traversed if they do not pass the filter, though it will prevent the directories themselves from being included in the results. By default, if no filter is provided, then all entries are included in the results. - `walkFilter`: Function `(entry: Path) => boolean`. If provided, will prevent the traversal of any directory (or in the case of `follow:true` symbolic links to directories) for which the function returns false. This will not prevent the directories themselves from being included in the result set. Use `filter` for that. Note that TypeScript return types will only be inferred properly from static analysis if the `withFileTypes` option is omitted, or a constant `true` or `false` value. ### Class `PathScurry` The main interface. Defaults to an appropriate class based on the current platform. Use `PathScurryWin32`, `PathScurryDarwin`, or `PathScurryPosix` if implementation-specific behavior is desired. All walk methods may be called with a `WalkOptions` argument to walk over the object's current working directory with the supplied options. #### `async pw.walk(entry?: string | Path | WalkOptions, opts?: WalkOptions)` Walk the directory tree according to the options provided, resolving to an array of all entries found. #### `pw.walkSync(entry?: string | Path | WalkOptions, opts?: WalkOptions)` Walk the directory tree according to the options provided, returning an array of all entries found. #### `pw.iterate(entry?: string | Path | WalkOptions, opts?: WalkOptions)` Iterate over the directory asynchronously, for use with `for await of`. This is also the default async iterator method. #### `pw.iterateSync(entry?: string | Path | WalkOptions, opts?: WalkOptions)` Iterate over the directory synchronously, for use with `for of`. This is also the default sync iterator method. #### `pw.stream(entry?: string | Path | WalkOptions, opts?: WalkOptions)` Return a [Minipass](http://npm.im/minipass) stream that emits each entry or path string in the walk. Results are made available asynchronously. #### `pw.streamSync(entry?: string | Path | WalkOptions, opts?: WalkOptions)` Return a [Minipass](http://npm.im/minipass) stream that emits each entry or path string in the walk. Results are made available synchronously, meaning that the walk will complete in a single tick if the stream is fully consumed. #### `pw.cwd` Path object representing the current working directory for the PathScurry. #### `pw.chdir(path: string)` Set the new effective current working directory for the scurry object, so that `path.relative()` and `path.relativePosix()` return values relative to the new cwd path. #### `pw.depth(path?: Path | string): number` Return the depth of the specified path (or the PathScurry cwd) within the directory tree. Root entries have a depth of `0`. #### `pw.resolve(...paths: string[])` Caching `path.resolve()`. Significantly faster than `path.resolve()` if called repeatedly with the same paths. Significantly slower otherwise, as it builds out the cached Path entries. To get a `Path` object resolved from the `PathScurry`, use `pw.cwd.resolve(path)`. Note that `Path.resolve` only takes a single string argument, not multiple. #### `pw.resolvePosix(...paths: string[])` Caching `path.resolve()`, but always using posix style paths. This is identical to `pw.resolve(...paths)` on posix systems (ie, everywhere except Windows). On Windows, it returns the full absolute UNC path using `/` separators. Ie, instead of `'C:\\foo\\bar`, it would return `//?/C:/foo/bar`. #### `pw.relative(path: string | Path): string` Return the relative path from the PathWalker cwd to the supplied path string or entry. If the nearest common ancestor is the root, then an absolute path is returned. #### `pw.relativePosix(path: string | Path): string` Return the relative path from the PathWalker cwd to the supplied path string or entry, using `/` path separators. If the nearest common ancestor is the root, then an absolute path is returned. On posix platforms (ie, all platforms except Windows), this is identical to `pw.relative(path)`. On Windows systems, it returns the resulting string as a `/`-delimited path. If an absolute path is returned (because the target does not share a common ancestor with `pw.cwd`), then a full absolute UNC path will be returned. Ie, instead of `'C:\\foo\\bar`, it would return `//?/C:/foo/bar`. #### `pw.basename(path: string | Path): string` Return the basename of the provided string or Path. #### `pw.dirname(path: string | Path): string` Return the parent directory of the supplied string or Path. #### `async pw.readdir(dir = pw.cwd, opts = { withFileTypes: true })` Read the directory and resolve to an array of strings if `withFileTypes` is explicitly set to `false` or Path objects otherwise. Can be called as `pw.readdir({ withFileTypes: boolean })` as well. Returns `[]` if no entries are found, or if any error occurs. Note that TypeScript return types will only be inferred properly from static analysis if the `withFileTypes` option is omitted, or a constant `true` or `false` value. #### `pw.readdirSync(dir = pw.cwd, opts = { withFileTypes: true })` Synchronous `pw.readdir()` #### `async pw.readlink(link = pw.cwd, opts = { withFileTypes: false })` Call `fs.readlink` on the supplied string or Path object, and return the result. Can be called as `pw.readlink({ withFileTypes: boolean })` as well. Returns `undefined` if any error occurs (for example, if the argument is not a symbolic link), or a `Path` object if `withFileTypes` is explicitly set to `true`, or a string otherwise. Note that TypeScript return types will only be inferred properly from static analysis if the `withFileTypes` option is omitted, or a constant `true` or `false` value. #### `pw.readlinkSync(link = pw.cwd, opts = { withFileTypes: false })` Synchronous `pw.readlink()` #### `async pw.lstat(entry = pw.cwd)` Call `fs.lstat` on the supplied string or Path object, and fill in as much information as possible, returning the updated `Path` object. Returns `undefined` if the entry does not exist, or if any error is encountered. Note that some `Stats` data (such as `ino`, `dev`, and `mode`) will not be supplied. For those things, you'll need to call `fs.lstat` yourself. #### `pw.lstatSync(entry = pw.cwd)` Synchronous `pw.lstat()` #### `pw.realpath(entry = pw.cwd, opts = { withFileTypes: false })` Call `fs.realpath` on the supplied string or Path object, and return the realpath if available. Returns `undefined` if any error occurs. May be called as `pw.realpath({ withFileTypes: boolean })` to run on `pw.cwd`. #### `pw.realpathSync(entry = pw.cwd, opts = { withFileTypes: false })` Synchronous `pw.realpath()` ### Class `Path` implements [fs.Dirent](https://nodejs.org/docs/latest/api/fs.html#class-fsdirent) Object representing a given path on the filesystem, which may or may not exist. Note that the actual class in use will be either `PathWin32` or `PathPosix`, depending on the implementation of `PathScurry` in use. They differ in the separators used to split and join path strings, and the handling of root paths. In `PathPosix` implementations, paths are split and joined using the `'/'` character, and `'/'` is the only root path ever in use. In `PathWin32` implementations, paths are split using either `'/'` or `'\\'` and joined using `'\\'`, and multiple roots may be in use based on the drives and UNC paths encountered. UNC paths such as `//?/C:/` that identify a drive letter, will be treated as an alias for the same root entry as their associated drive letter (in this case `'C:\\'`). #### `path.name` Name of this file system entry. **Important**: _always_ test the path name against any test string using the `isNamed` method, and not by directly comparing this string. Otherwise, unicode path strings that the system sees as identical will not be properly treated as the same path, leading to incorrect behavior and possible security issues. #### `path.isNamed(s: string)` Return true if the path is a match for the given path name. This handles case sensitivity and unicode normalization. Note: even on case-sensitive systems, it is **not** safe to test the equality of the `.name` property to determine whether a given pathname matches, due to unicode normalization mismatches. Always use this method instead of testing the `path.name` property directly. #### `path.depth()` Return the depth of the Path entry within the directory tree. Root paths have a depth of `0`. #### `path.fullpath()` The fully resolved path to the entry. #### `path.fullpathPosix()` The fully resolved path to the entry, using `/` separators. On posix systems, this is identical to `path.fullpath()`. On windows, this will return a fully resolved absolute UNC path using `/` separators. Eg, instead of `'C:\\foo\\bar'`, it will return `'//?/C:/foo/bar'`. #### `path.isFile()`, `path.isDirectory()`, etc. Same as the identical `fs.Dirent.isX()` methods. #### `path.isUnknown()` Returns true if the path's type is unknown. Always returns true when the path is known to not exist. #### `path.resolve(p: string)` Return a `Path` object associated with the provided path string as resolved from the current Path object. #### `path.relative(): string` Return the relative path from the PathWalker cwd to the supplied path string or entry. If the nearest common ancestor is the root, then an absolute path is returned. #### `path.relativePosix(): string` Return the relative path from the PathWalker cwd to the supplied path string or entry, using `/` path separators. If the nearest common ancestor is the root, then an absolute path is returned. On posix platforms (ie, all platforms except Windows), this is identical to `pw.relative(path)`. On Windows systems, it returns the resulting string as a `/`-delimited path. If an absolute path is returned (because the target does not share a common ancestor with `pw.cwd`), then a full absolute UNC path will be returned. Ie, instead of `'C:\\foo\\bar`, it would return `//?/C:/foo/bar`. #### `async path.readdir()` Return an array of `Path` objects found by reading the associated path entry. If path is not a directory, or if any error occurs, returns `[]`, and marks all children as provisional and non-existent. #### `path.readdirSync()` Synchronous `path.readdir()` #### `async path.readlink()` Return the `Path` object referenced by the `path` as a symbolic link. If the `path` is not a symbolic link, or any error occurs, returns `undefined`. #### `path.readlinkSync()` Synchronous `path.readlink()` #### `async path.lstat()` Call `lstat` on the path object, and fill it in with details determined. If path does not exist, or any other error occurs, returns `undefined`, and marks the path as "unknown" type. #### `path.lstatSync()` Synchronous `path.lstat()` #### `async path.realpath()` Call `realpath` on the path, and return a Path object corresponding to the result, or `undefined` if any error occurs. #### `path.realpathSync()` Synchornous `path.realpath()` isaacs-path-scurry-06957ec/package-lock.json000066400000000000000000005627251443124316700210420ustar00rootroot00000000000000{ "name": "path-scurry", "version": "1.9.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "path-scurry", "version": "1.9.2", "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^9.1.1", "minipass": "^5.0.0 || ^6.0.2" }, "devDependencies": { "@nodelib/fs.walk": "^1.2.8", "@types/node": "^20.1.4", "@types/tap": "^15.0.7", "c8": "^7.12.0", "eslint-config-prettier": "^8.6.0", "mkdirp": "^3.0.0", "prettier": "^2.8.3", "rimraf": "^4.1.2", "tap": "^16.3.4", "ts-node": "^10.9.1", "typedoc": "^0.23.24", "typescript": "^5.0.4" }, "engines": { "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { "version": "7.21.7", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.7.tgz", "integrity": "sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.21.8", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", "@babel/generator": "^7.21.5", "@babel/helper-compilation-targets": "^7.21.5", "@babel/helper-module-transforms": "^7.21.5", "@babel/helpers": "^7.21.5", "@babel/parser": "^7.21.8", "@babel/template": "^7.20.7", "@babel/traverse": "^7.21.5", "@babel/types": "^7.21.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/babel" } }, "node_modules/@babel/generator": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.5.tgz", "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==", "dev": true, "dependencies": { "@babel/types": "^7.21.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", "dev": true, "dependencies": { "@babel/compat-data": "^7.21.5", "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { "yallist": "^3.0.2" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "dev": true, "dependencies": { "@babel/types": "^7.21.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.21.5", "@babel/helper-module-imports": "^7.21.4", "@babel/helper-simple-access": "^7.21.5", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", "@babel/traverse": "^7.21.5", "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", "dev": true, "dependencies": { "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", "@babel/traverse": "^7.21.5", "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/parser": { "version": "7.21.8", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/template": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.21.4", "@babel/generator": "^7.21.5", "@babel/helper-environment-visitor": "^7.21.5", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/parser": "^7.21.5", "@babel/types": "^7.21.5", "debug": "^4.1.0", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/@babel/types": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" } }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "peer": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", "dev": true, "peer": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/js": { "version": "8.40.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", "dev": true, "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "peer": true, "engines": { "node": ">=12.22" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true, "peer": true }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.18", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" }, "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" }, "engines": { "node": ">= 8" } }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, "node_modules/@types/node": { "version": "20.1.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz", "integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==", "dev": true }, "node_modules/@types/tap": { "version": "15.0.8", "resolved": "https://registry.npmjs.org/@types/tap/-/tap-15.0.8.tgz", "integrity": "sha512-ZfeoiZlLIaFi4t6wccwbTEicrHREkP0bOq8dZVi/nWvG5F8O7LlS2cSUZBiOW/D4cgWS/p2uhM3lJoyzFAl80w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/ansi-sequence-parser": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", "dev": true }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, "dependencies": { "default-require-extensions": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "peer": true }, "node_modules/async-hook-domain": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-2.0.4.tgz", "integrity": "sha512-14LjCmlK1PK8eDtTezR6WX8TMaYNIzBIsd2D1sGoGjgx0BuNMMoSdk7i/drlbtamy0AWv9yv2tkB+ASdmeqFIw==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/bind-obj-methods": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-3.0.0.tgz", "integrity": "sha512-nLEaaz3/sEzNSyPWRsN9HNsqwk1AUyECtGj+XwGdIi3xABnEqecvXtIJ0wehQXuuER5uZ/5fTs2usONgYjG+iw==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { "version": "4.21.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" } ], "dependencies": { "caniuse-lite": "^1.0.30001449", "electron-to-chromium": "^1.4.284", "node-releases": "^2.0.8", "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "node_modules/c8": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/c8/-/c8-7.13.0.tgz", "integrity": "sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@istanbuljs/schema": "^0.1.3", "find-up": "^5.0.0", "foreground-child": "^2.0.0", "istanbul-lib-coverage": "^3.2.0", "istanbul-lib-report": "^3.0.0", "istanbul-reports": "^3.1.4", "rimraf": "^3.0.2", "test-exclude": "^6.0.0", "v8-to-istanbul": "^9.0.0", "yargs": "^16.2.0", "yargs-parser": "^20.2.9" }, "bin": { "c8": "bin/c8.js" }, "engines": { "node": ">=10.12.0" } }, "node_modules/c8/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/c8/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", "package-hash": "^4.0.0", "write-file-atomic": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "peer": true, "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { "version": "1.0.30001487", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001487.tgz", "integrity": "sha512-83564Z3yWGqXsh2vaH/mhXfEM0wX+NlBCm1jYHOb97TrTWJEmPTccZgeLTPBUUb0PNVo+oomb7wkimZBIERClA==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ] }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, "bin": { "color-support": "bin.js" } }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "peer": true }, "node_modules/default-require-extensions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, "dependencies": { "strip-bom": "^4.0.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "engines": { "node": ">=0.3.1" } }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "peer": true, "dependencies": { "esutils": "^2.0.2" }, "engines": { "node": ">=6.0.0" } }, "node_modules/electron-to-chromium": { "version": "1.4.394", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.394.tgz", "integrity": "sha512-0IbC2cfr8w5LxTz+nmn2cJTGafsK9iauV2r5A5scfzyovqLrxuLoxOHE5OBobP3oVIggJT+0JfKnw9sm87c8Hw==", "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "peer": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { "version": "8.40.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", "@eslint/js": "8.40.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-prettier": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-scope": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { "version": "9.5.2", "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "peer": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "peer": true, "dependencies": { "estraverse": "^5.1.0" }, "engines": { "node": ">=0.10" } }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "peer": true, "dependencies": { "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "peer": true, "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/events-to-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", "integrity": "sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA==", "dev": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "peer": true }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "peer": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "peer": true }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "peer": true, "dependencies": { "flat-cache": "^3.0.4" }, "engines": { "node": "^10.12.0 || >=12.0.0" } }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/findit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz", "integrity": "sha512-ENZS237/Hr8bjczn5eKuBohLgaD0JyUd0arxretR1f9RO46vZHA1b2y0VorgGV3WaOT3c+78P8h7v4JGJ1i/rg==", "dev": true }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "peer": true, "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" }, "engines": { "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flat-cache/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/flat-cache/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "peer": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/flatted": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true, "peer": true }, "node_modules/foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" }, "engines": { "node": ">=8.0.0" } }, "node_modules/fromentries": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/fs-exists-cached": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz", "integrity": "sha512-kSxoARUDn4F2RPXX48UXnaFKwVU7Ivd/6qpzZL29MCDmr9sTvybv4gFCp+qaI4fM9m0z9fgz/yJvi56GAz+BZg==", "dev": true }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/function-loop": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-2.0.1.tgz", "integrity": "sha512-ktIR+O6i/4h+j/ZhZJNdzeI4i9lEPeEK6UPR2EVyTVBqOwcU3Za9xYKLH64ZR9HmcROyRrOkizNyjjtWJzDDkQ==", "dev": true }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "engines": { "node": ">=8.0.0" } }, "node_modules/glob": { "version": "9.3.5", "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" }, "engines": { "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "peer": true, "dependencies": { "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" } }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/glob/node_modules/minimatch": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob/node_modules/minipass": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "peer": true, "dependencies": { "type-fest": "^0.20.2" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true, "peer": true }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "peer": true, "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "peer": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "peer": true, "engines": { "node": ">=8" } }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "dependencies": { "append-transform": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "dependencies": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.3", "istanbul-lib-coverage": "^3.2.0", "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^8.3.2" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-processinfo/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" }, "engines": { "node": ">=10" } }, "node_modules/istanbul-reports": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/jackspeak": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-1.4.2.tgz", "integrity": "sha512-GHeGTmnuaHnvS+ZctRB01bfxARuu9wW83ENbuiweu07SFcVlZrJpcshSre/keGT7YGBhLHg/+rXCNSrsEHKU4Q==", "dev": true, "dependencies": { "cliui": "^7.0.4" }, "engines": { "node": ">=8" } }, "node_modules/js-sdsl": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", "dev": true, "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "peer": true, "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=4" } }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "peer": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "peer": true }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "peer": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/libtap": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/libtap/-/libtap-1.4.0.tgz", "integrity": "sha512-STLFynswQ2A6W14JkabgGetBNk6INL1REgJ9UeNKw5llXroC2cGLgKTqavv0sl8OLVztLLipVKMcQ7yeUcqpmg==", "dev": true, "dependencies": { "async-hook-domain": "^2.0.4", "bind-obj-methods": "^3.0.0", "diff": "^4.0.2", "function-loop": "^2.0.1", "minipass": "^3.1.5", "own-or": "^1.0.0", "own-or-env": "^1.0.2", "signal-exit": "^3.0.4", "stack-utils": "^2.0.4", "tap-parser": "^11.0.0", "tap-yaml": "^1.0.0", "tcompare": "^5.0.6", "trivial-deferred": "^1.0.1" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/libtap/node_modules/minipass": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/libtap/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "peer": true }, "node_modules/lru-cache": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", "engines": { "node": "14 || >=16.14" } }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { "semver": "^6.0.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "bin": { "marked": "bin/marked.js" }, "engines": { "node": ">= 12" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/minipass": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "bin": { "mkdirp": "dist/cjs/src/bin.js" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "peer": true }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "dependencies": { "process-on-spawn": "^1.0.0" }, "engines": { "node": ">=8" } }, "node_modules/node-releases": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "caching-transform": "^4.0.0", "convert-source-map": "^1.7.0", "decamelize": "^1.2.0", "find-cache-dir": "^3.2.0", "find-up": "^4.1.0", "foreground-child": "^2.0.0", "get-package-type": "^0.1.0", "glob": "^7.1.6", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-hook": "^3.0.0", "istanbul-lib-instrument": "^4.0.0", "istanbul-lib-processinfo": "^2.0.2", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", "make-dir": "^3.0.0", "node-preload": "^0.2.1", "p-map": "^3.0.0", "process-on-spawn": "^1.0.0", "resolve-from": "^5.0.0", "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "spawn-wrap": "^2.0.0", "test-exclude": "^6.0.0", "yargs": "^15.0.2" }, "bin": { "nyc": "bin/nyc.js" }, "engines": { "node": ">=8.9" } }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "node_modules/nyc/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/nyc/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" }, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" }, "engines": { "node": ">=6" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { "wrappy": "1" } }, "node_modules/opener": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, "bin": { "opener": "bin/opener-bin.js" } }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "peer": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.3" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/own-or": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz", "integrity": "sha512-NfZr5+Tdf6MB8UI9GLvKRs4cXY8/yB0w3xtt84xFdWy8hkGjn+JFc60VhzS/hFRfbyxFcGYMTjnF4Me+RbbqrA==", "dev": true }, "node_modules/own-or-env": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/own-or-env/-/own-or-env-1.0.2.tgz", "integrity": "sha512-NQ7v0fliWtK7Lkb+WdFqe6ky9XAzYmlkXthQrBbzlYbmFKoAYbDDcwmOm6q8kOuwSRXW8bdL5ORksploUJmWgw==", "dev": true, "dependencies": { "own-or": "^1.0.0" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/package-hash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", "lodash.flattendeep": "^4.4.0", "release-zalgo": "^1.0.0" }, "engines": { "node": ">=8" } }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "peer": true, "dependencies": { "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-scurry": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.0.tgz", "integrity": "sha512-KLejx+14koDZLnb3JNDZbjcmHC/IO2Imd3rNoyt5mynieVd+MT4b1aaGaXAHw06H3P+aZ3Q+56VKJ6BCHMO3WA==", "dev": true, "dependencies": { "lru-cache": "^9.1.1", "minipass": "^5.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { "find-up": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/pkg-dir/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "peer": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, "dependencies": { "fromentries": "^1.2.0" }, "engines": { "node": ">=8" } }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.0" } }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, "dependencies": { "es6-error": "^4.0.1" }, "engines": { "node": ">=4" } }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "peer": true, "engines": { "node": ">=4" } }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rimraf": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, "dependencies": { "glob": "^9.2.0" }, "bin": { "rimraf": "dist/cjs/src/bin.js" }, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/shiki": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", "vscode-oniguruma": "^1.7.0", "vscode-textmate": "^8.0.0" } }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "node_modules/spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", "make-dir": "^3.0.0", "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "which": "^2.0.1" }, "engines": { "node": ">=8" } }, "node_modules/spawn-wrap/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/spawn-wrap/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" }, "engines": { "node": ">=10" } }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "peer": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap": { "version": "16.3.4", "resolved": "https://registry.npmjs.org/tap/-/tap-16.3.4.tgz", "integrity": "sha512-SAexdt2ZF4XBgye6TPucFI2y7VE0qeFXlXucJIV1XDPCs+iJodk0MYacr1zR6Ycltzz7PYg8zrblDXKbAZM2LQ==", "bundleDependencies": [ "ink", "treport", "@types/react", "@isaacs/import-jsx", "react" ], "dev": true, "dependencies": { "@isaacs/import-jsx": "^4.0.1", "@types/react": "^17.0.52", "chokidar": "^3.3.0", "findit": "^2.0.0", "foreground-child": "^2.0.0", "fs-exists-cached": "^1.0.0", "glob": "^7.2.3", "ink": "^3.2.0", "isexe": "^2.0.0", "istanbul-lib-processinfo": "^2.0.3", "jackspeak": "^1.4.2", "libtap": "^1.4.0", "minipass": "^3.3.4", "mkdirp": "^1.0.4", "nyc": "^15.1.0", "opener": "^1.5.1", "react": "^17.0.2", "rimraf": "^3.0.0", "signal-exit": "^3.0.6", "source-map-support": "^0.5.16", "tap-mocha-reporter": "^5.0.3", "tap-parser": "^11.0.2", "tap-yaml": "^1.0.2", "tcompare": "^5.0.7", "treport": "^3.0.4", "which": "^2.0.2" }, "bin": { "tap": "bin/run.js" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" }, "peerDependencies": { "coveralls": "^3.1.1", "flow-remove-types": ">=2.112.0", "ts-node": ">=8.5.2", "typescript": ">=3.7.2" }, "peerDependenciesMeta": { "coveralls": { "optional": true }, "flow-remove-types": { "optional": true }, "ts-node": { "optional": true }, "typescript": { "optional": true } } }, "node_modules/tap-mocha-reporter": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-5.0.3.tgz", "integrity": "sha512-6zlGkaV4J+XMRFkN0X+yuw6xHbE9jyCZ3WUKfw4KxMyRGOpYSRuuQTRJyWX88WWuLdVTuFbxzwXhXuS2XE6o0g==", "dev": true, "dependencies": { "color-support": "^1.1.0", "debug": "^4.1.1", "diff": "^4.0.1", "escape-string-regexp": "^2.0.0", "glob": "^7.0.5", "tap-parser": "^11.0.0", "tap-yaml": "^1.0.0", "unicode-length": "^2.0.2" }, "bin": { "tap-mocha-reporter": "index.js" }, "engines": { "node": ">= 8" } }, "node_modules/tap-mocha-reporter/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/tap-mocha-reporter/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/tap-parser": { "version": "11.0.2", "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-11.0.2.tgz", "integrity": "sha512-6qGlC956rcORw+fg7Fv1iCRAY8/bU9UabUAhs3mXRH6eRmVZcNPLheSXCYaVaYeSwx5xa/1HXZb1537YSvwDZg==", "dev": true, "dependencies": { "events-to-array": "^1.0.1", "minipass": "^3.1.6", "tap-yaml": "^1.0.0" }, "bin": { "tap-parser": "bin/cmd.js" }, "engines": { "node": ">= 8" } }, "node_modules/tap-parser/node_modules/minipass": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap-parser/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/tap-yaml": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.2.tgz", "integrity": "sha512-GegASpuqBnRNdT1U+yuUPZ8rEU64pL35WPBpCISWwff4dErS2/438barz7WFJl4Nzh3Y05tfPidZnH+GaV1wMg==", "dev": true, "dependencies": { "yaml": "^1.10.2" } }, "node_modules/tap/node_modules/@ampproject/remapping": { "version": "2.1.2", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/trace-mapping": "^0.3.0" }, "engines": { "node": ">=6.0.0" } }, "node_modules/tap/node_modules/@babel/code-frame": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/highlight": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/compat-data": { "version": "7.17.7", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/core": { "version": "7.17.8", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.7", "@babel/helper-compilation-targets": "^7.17.7", "@babel/helper-module-transforms": "^7.17.7", "@babel/helpers": "^7.17.8", "@babel/parser": "^7.17.8", "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/babel" } }, "node_modules/tap/node_modules/@babel/generator": { "version": "7.17.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-annotate-as-pure": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-compilation-targets": { "version": "7.17.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.17.7", "@babel/helper-validator-option": "^7.16.7", "browserslist": "^4.17.5", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/tap/node_modules/@babel/helper-environment-visitor": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-function-name": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-get-function-arity": "^7.16.7", "@babel/template": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-get-function-arity": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-hoist-variables": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-module-imports": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-module-transforms": { "version": "7.17.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", "@babel/helper-simple-access": "^7.17.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-plugin-utils": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-simple-access": { "version": "7.17.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-split-export-declaration": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-validator-identifier": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helper-validator-option": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/helpers": { "version": "7.17.8", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/highlight": { "version": "7.16.10", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/parser": { "version": "7.17.8", "dev": true, "inBundle": true, "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/tap/node_modules/@babel/plugin-proposal-object-rest-spread": { "version": "7.17.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.17.0", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-transform-parameters": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/tap/node_modules/@babel/plugin-syntax-jsx": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/tap/node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/tap/node_modules/@babel/plugin-transform-destructuring": { "version": "7.17.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/tap/node_modules/@babel/plugin-transform-parameters": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/tap/node_modules/@babel/plugin-transform-react-jsx": { "version": "7.17.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-jsx": "^7.16.7", "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/tap/node_modules/@babel/template": { "version": "7.16.7", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/traverse": { "version": "7.17.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.3", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/parser": "^7.17.3", "@babel/types": "^7.17.0", "debug": "^4.1.0", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@babel/types": { "version": "7.17.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/@isaacs/import-jsx": { "version": "4.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@babel/core": "^7.5.5", "@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/plugin-transform-destructuring": "^7.5.0", "@babel/plugin-transform-react-jsx": "^7.3.0", "caller-path": "^3.0.1", "find-cache-dir": "^3.2.0", "make-dir": "^3.0.2", "resolve-from": "^3.0.0", "rimraf": "^3.0.0" }, "engines": { "node": ">=10" } }, "node_modules/tap/node_modules/@jridgewell/resolve-uri": { "version": "3.0.5", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/tap/node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.11", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/@jridgewell/trace-mapping": { "version": "0.3.4", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/tap/node_modules/@types/prop-types": { "version": "15.7.4", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/@types/react": { "version": "17.0.52", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/tap/node_modules/@types/scheduler": { "version": "0.16.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/@types/yoga-layout": { "version": "1.9.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/ansi-escapes": { "version": "4.3.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", "dev": true, "inBundle": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/ansi-regex": { "version": "5.0.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/ansi-styles": { "version": "3.2.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/ansicolors": { "version": "0.3.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/astral-regex": { "version": "2.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/auto-bind": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/balanced-match": { "version": "1.0.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/brace-expansion": { "version": "1.1.11", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/tap/node_modules/browserslist": { "version": "4.20.2", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" } ], "inBundle": true, "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001317", "electron-to-chromium": "^1.4.84", "escalade": "^3.1.1", "node-releases": "^2.0.2", "picocolors": "^1.0.0" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/tap/node_modules/caller-callsite": { "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "callsites": "^3.1.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/caller-path": { "version": "3.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "caller-callsite": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/callsites": { "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tap/node_modules/caniuse-lite": { "version": "1.0.30001319", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" } ], "inBundle": true, "license": "CC-BY-4.0" }, "node_modules/tap/node_modules/cardinal": { "version": "2.1.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansicolors": "~0.3.2", "redeyed": "~2.1.0" }, "bin": { "cdl": "bin/cdl.js" } }, "node_modules/tap/node_modules/chalk": { "version": "2.4.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/ci-info": { "version": "2.0.0", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/cli-boxes": { "version": "2.2.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/cli-cursor": { "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/cli-truncate": { "version": "2.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/code-excerpt": { "version": "3.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "convert-to-spaces": "^1.0.1" }, "engines": { "node": ">=10" } }, "node_modules/tap/node_modules/color-convert": { "version": "1.9.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/tap/node_modules/color-name": { "version": "1.1.3", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/commondir": { "version": "1.0.1", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/concat-map": { "version": "0.0.1", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/convert-source-map": { "version": "1.8.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/tap/node_modules/convert-to-spaces": { "version": "1.0.2", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/tap/node_modules/csstype": { "version": "3.0.11", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/debug": { "version": "4.3.4", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/tap/node_modules/electron-to-chromium": { "version": "1.4.89", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/emoji-regex": { "version": "8.0.0", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/escalade": { "version": "3.1.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tap/node_modules/escape-string-regexp": { "version": "1.0.5", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/tap/node_modules/esprima": { "version": "4.0.1", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/events-to-array": { "version": "1.1.2", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/find-cache-dir": { "version": "3.3.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, "node_modules/tap/node_modules/find-up": { "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/fs.realpath": { "version": "1.0.0", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/gensync": { "version": "1.0.0-beta.2", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/tap/node_modules/glob": { "version": "7.2.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/tap/node_modules/globals": { "version": "11.12.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/has-flag": { "version": "3.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/indent-string": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/inflight": { "version": "1.0.6", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/tap/node_modules/inherits": { "version": "2.0.4", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/ink": { "version": "3.2.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "auto-bind": "4.0.0", "chalk": "^4.1.0", "cli-boxes": "^2.2.0", "cli-cursor": "^3.1.0", "cli-truncate": "^2.1.0", "code-excerpt": "^3.0.0", "indent-string": "^4.0.0", "is-ci": "^2.0.0", "lodash": "^4.17.20", "patch-console": "^1.0.0", "react-devtools-core": "^4.19.1", "react-reconciler": "^0.26.2", "scheduler": "^0.20.2", "signal-exit": "^3.0.2", "slice-ansi": "^3.0.0", "stack-utils": "^2.0.2", "string-width": "^4.2.2", "type-fest": "^0.12.0", "widest-line": "^3.1.0", "wrap-ansi": "^6.2.0", "ws": "^7.5.5", "yoga-layout-prebuilt": "^1.9.6" }, "engines": { "node": ">=10" }, "peerDependencies": { "@types/react": ">=16.8.0", "react": ">=16.8.0" }, "peerDependenciesMeta": { "@types/react": { "optional": true } } }, "node_modules/tap/node_modules/ink/node_modules/ansi-styles": { "version": "4.3.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/tap/node_modules/ink/node_modules/chalk": { "version": "4.1.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/tap/node_modules/ink/node_modules/color-convert": { "version": "2.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/tap/node_modules/ink/node_modules/color-name": { "version": "1.1.4", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/ink/node_modules/has-flag": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/ink/node_modules/supports-color": { "version": "7.2.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/is-ci": { "version": "2.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ci-info": "^2.0.0" }, "bin": { "is-ci": "bin.js" } }, "node_modules/tap/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/js-tokens": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/jsesc": { "version": "2.5.2", "dev": true, "inBundle": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/json5": { "version": "2.2.3", "dev": true, "inBundle": true, "license": "MIT", "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/tap/node_modules/locate-path": { "version": "5.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/lodash": { "version": "4.17.21", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/loose-envify": { "version": "1.4.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "node_modules/tap/node_modules/make-dir": { "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/mimic-fn": { "version": "2.1.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tap/node_modules/minimatch": { "version": "3.1.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/tap/node_modules/minipass": { "version": "3.3.4", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" } }, "node_modules/tap/node_modules/ms": { "version": "2.1.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/node-releases": { "version": "2.0.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/object-assign": { "version": "4.1.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/tap/node_modules/once": { "version": "1.4.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/tap/node_modules/onetime": { "version": "5.1.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/p-limit": { "version": "2.3.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/p-locate": { "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/p-try": { "version": "2.2.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tap/node_modules/patch-console": { "version": "1.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/tap/node_modules/path-exists": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/path-is-absolute": { "version": "1.0.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/tap/node_modules/picocolors": { "version": "1.0.0", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/pkg-dir": { "version": "4.2.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/punycode": { "version": "2.1.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tap/node_modules/react": { "version": "17.0.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/tap/node_modules/react-devtools-core": { "version": "4.24.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "node_modules/tap/node_modules/react-reconciler": { "version": "0.26.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "scheduler": "^0.20.2" }, "engines": { "node": ">=0.10.0" }, "peerDependencies": { "react": "^17.0.2" } }, "node_modules/tap/node_modules/redeyed": { "version": "2.1.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "esprima": "~4.0.0" } }, "node_modules/tap/node_modules/resolve-from": { "version": "3.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/restore-cursor": { "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/rimraf": { "version": "3.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/tap/node_modules/safe-buffer": { "version": "5.1.2", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/scheduler": { "version": "0.20.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "node_modules/tap/node_modules/semver": { "version": "6.3.0", "dev": true, "inBundle": true, "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/tap/node_modules/shell-quote": { "version": "1.7.3", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/signal-exit": { "version": "3.0.7", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/slice-ansi": { "version": "3.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/slice-ansi/node_modules/ansi-styles": { "version": "4.3.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/tap/node_modules/slice-ansi/node_modules/color-convert": { "version": "2.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/tap/node_modules/slice-ansi/node_modules/color-name": { "version": "1.1.4", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/source-map": { "version": "0.5.7", "dev": true, "inBundle": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/tap/node_modules/stack-utils": { "version": "2.0.5", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, "engines": { "node": ">=10" } }, "node_modules/tap/node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/string-width": { "version": "4.2.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/strip-ansi": { "version": "6.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/supports-color": { "version": "5.5.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/tap-parser": { "version": "11.0.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "events-to-array": "^1.0.1", "minipass": "^3.1.6", "tap-yaml": "^1.0.0" }, "bin": { "tap-parser": "bin/cmd.js" }, "engines": { "node": ">= 8" } }, "node_modules/tap/node_modules/tap-yaml": { "version": "1.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "yaml": "^1.10.2" } }, "node_modules/tap/node_modules/to-fast-properties": { "version": "2.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tap/node_modules/treport": { "version": "3.0.4", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@isaacs/import-jsx": "^4.0.1", "cardinal": "^2.1.1", "chalk": "^3.0.0", "ink": "^3.2.0", "ms": "^2.1.2", "tap-parser": "^11.0.0", "tap-yaml": "^1.0.0", "unicode-length": "^2.0.2" }, "peerDependencies": { "react": "^17.0.2" } }, "node_modules/tap/node_modules/treport/node_modules/ansi-styles": { "version": "4.3.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/tap/node_modules/treport/node_modules/chalk": { "version": "3.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/treport/node_modules/color-convert": { "version": "2.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/tap/node_modules/treport/node_modules/color-name": { "version": "1.1.4", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/treport/node_modules/has-flag": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/treport/node_modules/supports-color": { "version": "7.2.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/type-fest": { "version": "0.12.0", "dev": true, "inBundle": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/tap/node_modules/unicode-length": { "version": "2.0.2", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "punycode": "^2.0.0", "strip-ansi": "^3.0.1" } }, "node_modules/tap/node_modules/unicode-length/node_modules/ansi-regex": { "version": "2.1.1", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/tap/node_modules/unicode-length/node_modules/strip-ansi": { "version": "3.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/tap/node_modules/widest-line": { "version": "3.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "string-width": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/wrap-ansi": { "version": "6.2.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tap/node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/tap/node_modules/wrap-ansi/node_modules/color-convert": { "version": "2.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/tap/node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/tap/node_modules/wrappy": { "version": "1.0.2", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/ws": { "version": "7.5.7", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { "bufferutil": { "optional": true }, "utf-8-validate": { "optional": true } } }, "node_modules/tap/node_modules/yallist": { "version": "4.0.0", "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/tap/node_modules/yaml": { "version": "1.10.2", "dev": true, "inBundle": true, "license": "ISC", "engines": { "node": ">= 6" } }, "node_modules/tap/node_modules/yoga-layout-prebuilt": { "version": "1.10.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@types/yoga-layout": "1.9.2" }, "engines": { "node": ">=8" } }, "node_modules/tcompare": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-5.0.7.tgz", "integrity": "sha512-d9iddt6YYGgyxJw5bjsN7UJUO1kGOtjSlNy/4PoGYAjQS5pAT/hzIoLf1bZCw+uUxRmZJh7Yy1aA7xKVRT9B4w==", "dev": true, "dependencies": { "diff": "^4.0.2" }, "engines": { "node": ">=10" } }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, "node_modules/test-exclude/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, "peer": true }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/trivial-deferred": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.1.2.tgz", "integrity": "sha512-vDPiDBC3hyP6O4JrJYMImW3nl3c03Tsj9fEXc7Qc/XKa1O7gf5ZtFfIR/E0dun9SnDHdwjna1Z2rSzYgqpxh/g==", "dev": true, "engines": { "node": ">= 8" } }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "peerDependenciesMeta": { "@swc/core": { "optional": true }, "@swc/wasm": { "optional": true } } }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "peer": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { "version": "0.23.28", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.28.tgz", "integrity": "sha512-9x1+hZWTHEQcGoP7qFmlo4unUoVJLB0H/8vfO/7wqTnZxg4kPuji9y3uRzEu0ZKez63OJAUmiGhUrtukC6Uj3w==", "dev": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.2.12", "minimatch": "^7.1.3", "shiki": "^0.14.1" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { "node": ">= 14.14" }, "peerDependencies": { "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/typedoc/node_modules/minimatch": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=12.20" } }, "node_modules/unicode-length": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.1.0.tgz", "integrity": "sha512-4bV582zTV9Q02RXBxSUMiuN/KHo5w4aTojuKTNT96DIKps/SIawFp7cS5Mu25VuY1AioGXrmYyzKZUzh8OqoUw==", "dev": true, "dependencies": { "punycode": "^2.0.0" } }, "node_modules/update-browserslist-db": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "bin": { "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" } }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "peer": true, "dependencies": { "punycode": "^2.1.0" } }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, "node_modules/v8-to-istanbul": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0" }, "engines": { "node": ">=10.12.0" } }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", "dev": true }, "node_modules/vscode-textmate": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "dev": true }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", "signal-exit": "^3.0.2", "typedarray-to-buffer": "^3.1.5" } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, "engines": { "node": ">= 6" } }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } } } isaacs-path-scurry-06957ec/package.json000066400000000000000000000041431443124316700200750ustar00rootroot00000000000000{ "name": "path-scurry", "version": "1.9.2", "description": "walk paths fast and efficiently", "author": "Isaac Z. Schlueter (https://blog.izs.me)", "main": "./dist/cjs/index.js", "module": "./dist/mjs/index.js", "exports": { ".": { "import": { "types": "./dist/mjs/index.d.ts", "default": "./dist/mjs/index.js" }, "require": { "types": "./dist/cjs/index.d.ts", "default": "./dist/cjs/index.js" } } }, "files": [ "dist" ], "license": "BlueOak-1.0.0", "scripts": { "preversion": "npm test", "postversion": "npm publish", "prepublishOnly": "git push origin --follow-tags", "preprepare": "rm -rf dist", "prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json", "postprepare": "bash ./scripts/fixup.sh", "pretest": "npm run prepare", "presnap": "npm run prepare", "test": "c8 tap", "snap": "c8 tap", "format": "prettier --write . --loglevel warn", "typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts", "bench": "bash ./scripts/bench.sh" }, "prettier": { "semi": false, "printWidth": 75, "tabWidth": 2, "useTabs": false, "singleQuote": true, "jsxSingleQuote": false, "bracketSameLine": true, "arrowParens": "avoid", "endOfLine": "lf" }, "tap": { "coverage": false, "node-arg": [ "--no-warnings", "--loader", "ts-node/esm" ], "ts": false }, "devDependencies": { "@nodelib/fs.walk": "^1.2.8", "@types/node": "^20.1.4", "@types/tap": "^15.0.7", "c8": "^7.12.0", "eslint-config-prettier": "^8.6.0", "mkdirp": "^3.0.0", "prettier": "^2.8.3", "rimraf": "^4.1.2", "tap": "^16.3.4", "ts-node": "^10.9.1", "typedoc": "^0.23.24", "typescript": "^5.0.4" }, "engines": { "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" }, "repository": { "type": "git", "url": "git+https://github.com/isaacs/path-walker" }, "dependencies": { "lru-cache": "^9.1.1", "minipass": "^5.0.0 || ^6.0.2" } } isaacs-path-scurry-06957ec/scripts/000077500000000000000000000000001443124316700172745ustar00rootroot00000000000000isaacs-path-scurry-06957ec/scripts/.gitignore000066400000000000000000000000101443124316700212530ustar00rootroot00000000000000fixture isaacs-path-scurry-06957ec/scripts/bench.sh000077500000000000000000000002041443124316700207060ustar00rootroot00000000000000#!/usr/bin/env bash chmod 0755 scripts/benchmark-* for script in scripts/benchmark-*; do echo ----- $script ----- $script done isaacs-path-scurry-06957ec/scripts/benchmark-path-resolve.ts000077500000000000000000000075051443124316700242170ustar00rootroot00000000000000#!/usr/bin/env node --expose_gc --loader=ts-node/esm --no-warnings console.log('Testing performance compared with path.resolve()') // Test performance against the built-in path.resolve() // // Since PathScurry is optimized for cases where the *same* // paths potentially get resolved repeatedly (as in a glob // walk, or other cases where the paths being resolved refer // to real file system entries), note that the ${RANDOM} case // completely destroys it, because it is always missing the // cache, and thus doing way more work than simple string // munging. // // But, in the cases where the paths are repeatedly resolved, // caching the resolution improves things dramatically. // // Note that the `${RANDOM}` tests are down across all implementations, // because it's taking the hit of calling Math.random() and doing a // string replace in all of them. Numbers should be compared relatively // in those cases, not treated as representative absolute perf metrics, // unless you're doing Math.random() and string.replace() as part of your // path resolution process, in which case, don't do that lol. import { posix } from 'path' import { PathBase, PathScurryPosix, PathScurryWin32 } from '../' const posixResolve = posix.resolve const win32Resolve = posix.resolve const pwp = new PathScurryPosix(process.cwd(), { nocase: false }) const pww = new PathScurryWin32(process.cwd(), { nocase: false }) const N = 1_000 const p = 'a/b/c/../d/e/f////g/h/i/j/../j/k' const abs = '/x/y/z' // completely random each time const rnd = '${RANDOM}' // an incrementing number % 10 const mod = '${MOD}' const replaceRandom = ([s, t]: [s: string, t?: string]): [ string, string | undefined ] => (s && s.includes('${RANDOM}')) || (t && t.includes('${RANDOM}')) ? [ s && s.replace(/\$\{RANDOM\}/, String(Math.random())), t && t.replace(/\$\{RANDOM\}/, String(Math.random())), ] : [s, t] let modInc = 0 const replaceMod = ([s, t]: [s: string, t?: string]): [ string, string | undefined ] => { modInc = (modInc + 1) % 10 return (s && s.includes('${MOD}')) || (t && t.includes('${MOD}')) ? [ s && s.replace(/\$\{MOD\}/, String(modInc)), t && t.replace(/\$\{MOD\}/, String(modInc)), ] : [s, t] } const run = ( r: (s: string, t?: string) => string | PathBase, s: string, t?: string ) => { gc && gc() const start = performance.now() const e = start + 1000 let count = 0 while (performance.now() < e) { for (let i = 0; i < N; i++) { const [ss, tt] = replaceMod(replaceRandom([s, t])) r(ss, tt) } count += N } const end = performance.now() return count / (end - start) } const pathResolve = (s: string, t?: string) => t === undefined ? posixResolve(s) : posixResolve(s, t) const pathWinResolve = (s: string, t?: string) => t === undefined ? win32Resolve(s) : win32Resolve(s, t) const pwpResolve = (s: string, t?: string) => t === undefined ? pwp.resolve(s) : pwp.resolve(s, t) const pwwResolve = (s: string, t?: string) => t === undefined ? pww.resolve(s) : pww.resolve(s, t) console.log('showing results in operations / ms (bigger is better)') const cases = [ [abs], [p], [abs, p], [p, abs], [p, rnd], [rnd, abs], [abs, rnd], [p, mod], [mod, abs], [abs, mod], ] const { format } = new Intl.NumberFormat('en', { maximumFractionDigits: 2, }) for (const [s, t] of cases) { process.stderr.write('.') const prwin = run(pathWinResolve, s, t) process.stderr.write('.') const prnix = run(pathResolve, s, t) process.stderr.write('.') const pwp = run(pwpResolve, s, t) process.stderr.write('.') const pww = run(pwwResolve, s, t) process.stderr.write('.') console.log(`\r(${s}${t ? ',' + t : ''})`, { 'path.win32.resolve()': format(prwin), 'path.posix.resolve()': format(prnix), PathScurryPosix: format(pwp), PathScurryWin32: format(pww), }) } isaacs-path-scurry-06957ec/scripts/benchmark-readdir.ts000077500000000000000000000501601443124316700232130ustar00rootroot00000000000000#!/usr/bin/env node --expose_gc --loader=ts-node/esm --no-warnings console.log(`comparing performance against a naive fs readdir walk`) // note that the "reuse pw" cases are MUCH faster for item counts up // to 150k or so. The sync reuse case is so wildly fast in that case // because it is just benchmarking the LRUCache. The async case is // gated by the speed of Promise resolution. // // Above 200k - 300k entries, the advantage starts to decline, as it // gets further past the default childrenCacheSize value of 16*1024. // // At 500k to 1M entries, PathScurry isn't significantly faster than // the naive fs walk, and the program is gated by syscalls and garbage // collection. The sync case gets noticeably slower than async. // // But, it doesn't crash the JS heap, since old entries are discarded // as new entries keep being added. // // The fs.readdir() walks are commented out because I couldn't figure // out how to make them stop crashing the JS heap, even for relatively // modest fs entry counts. I'm not sure why it would be a problem, // especially since PathScurry uses fs.readdir() rather than opendir. import { walk, walkStream, walkSync } from '@nodelib/fs.walk' import { Dir, Dirent, opendirSync, writeFileSync } from 'fs' import { opendir, readdir } from 'fs/promises' import { mkdirpSync } from 'mkdirp' import { cpus } from 'os' import { resolve } from 'path' // import { rimrafSync } from 'rimraf' // depth to go in const D = 6 // count of items to put in each folder const C = 10 // max number of things to make, in total const max: number = +process.argv[2] || 100_000 let totalCreated = 0 let saidDone = false const sayDone = () => { if (saidDone) { return } saidDone = true console.log(`Creating ${max} file system entries...done! `) } let saidCreating = false const sayCreating = () => { if (saidCreating) return saidCreating = true process.stdout.write(`Creating ${max} file system entries...\r`) } const sayCreated = process.stdout.isTTY ? () => { if (totalCreated % 1000 === 0) { process.stdout.write( `Creating ${max} file system entries...${totalCreated} \r` ) } } : () => {} const setup = ( dir: string, d: number = D, c: number = C, dirs: string[] = [] ) => { if (d === D) sayCreating() mkdirpSync(dir) totalCreated++ if (totalCreated >= max) { sayDone() return } if (totalCreated % 1000 === 0) { sayCreated() } if (d === 0) { for (let i = 0; i < c; i++) { const p = `${dir}/${i}${i}` writeFileSync(p, '') totalCreated++ if (totalCreated >= max) { sayDone() return } if (totalCreated % 1000 === 0) { sayCreated() } } return } for (let i = 0; i < c; i++) { setup(`${dir}/${i}`, d - 1, c, dirs) } } const dir = resolve(__dirname) + '/fixture' process.stdout.write('cleaning fixture...\r') // rimrafSync(dir) console.log('cleaning fixture...done!') import { Path, PathScurry } from '../' const fsWalkStream = (done: () => any) => { const stream = walkStream(dir) stream.on('end', done) stream.resume() } const fsWalkAsync = (done: () => any) => { walk(dir, done) } const fsWalkSync = (done: () => any) => { walkSync(dir) done() } const pwWalkFreshAsync = (done: () => any) => { new PathScurry(dir).walk().then(done) } const pwWalkFreshSync = (done: () => any) => { new PathScurry(dir).walkSync() done() } const pwWalkFreshIterateSync = (done: () => any) => { for (const _ of new PathScurry(dir).iterateSync()) { } done() } const pwWalkFreshStriterateSync = (done: () => any) => { for (const _ of new PathScurry(dir).streamSync()) { } done() } // const pwWalkFreshForOf = (done: () => any) => { // for (const _ of new PathScurry(dir)) { // } // done() // } const pwWalkFreshIterate = (done: () => any) => { const x = async () => { for await (const _ of new PathScurry(dir).iterate()) { } } x().then(done) } const pwWalkFreshStriterate = (done: () => any) => { const x = async () => { for await (const _ of new PathScurry(dir).stream()) { } } x().then(done) } // const pwWalkFreshForAwaitOf = (done: () => any) => { // const x = async () => { // for await (const _ of new PathScurry(dir)) { // } // } // x().then(done) // } const pwWalkFreshStream = (done: () => any) => { new PathScurry(dir).stream().on('end', done).resume() } const pwWalkFreshStreamSync = (done: () => any) => { new PathScurry(dir).streamSync().resume() done() } const pwWalkReuseAsync = (done: () => any) => { pwReuse.walk().then(done) } const pwWalkReuseSync = (done: () => any) => { pwReuse.walkSync() done() } const pwWalkReuseIterateSync = (done: () => any) => { for (const _ of pwReuse.iterateSync()) { } done() } // const pwWalkReuseForOf = (done: () => any) => { // for (const _ of pwReuse) { // } // done() // } const pwWalkReuseIterate = (done: () => any) => { const x = async () => { for await (const _ of pwReuse.iterate()) { } } x().then(done) } // const pwWalkReuseForAwaitOf = (done: () => any) => { // const x = async () => { // for await (const _ of pwReuse) { // } // } // x().then(done) // } const pwWalkReuseStream = (done: () => any) => { pwReuse.stream().on('end', done).resume() } const pwWalkReuseStreamSync = (done: () => any) => { pwReuse.streamSync().resume() done() } const pwWalkReuseStriterate = (done: () => any) => { const x = async () => { for await (const _ of pwReuse.stream()) { } } x().then(done) } const pwWalkReuseStriterateSync = (done: () => any) => { for (const _ of pwReuse.streamSync()) { } done() } const walkFreshPWSyncRecurse = (check: boolean = true) => (done: () => any) => { const pw = new PathScurry(dir) const walk = (p: Path) => { for (const path of pw.readdirSync(p)) { if (!check || path.isDirectory()) { walk(path) } } } walk(pw.cwd) done() } // const walkFreshPWSyncIterate = (done: () => any) => { // const pw = new PathScurry(dir) // const walk = (p: PathBase) => { // const paths: PathBase[] = [p] // let path: PathBase | undefined // while ((path = paths.shift())) { // for (const p of pw.readdirSync(path)) { // paths.push(p) // } // } // } // walk(pw.cwd) // done() // } const walkFreshPWCBRecurse = (check: boolean = true, zalgo: boolean = false) => (done: () => any) => { const pw = new PathScurry(dir) const walk = async (path: Path, cb: () => any) => { path.readdirCB((_er, entries) => { let len = entries.length if (!len) cb() const next = () => { if (--len <= 0) cb() } for (const e of entries) { if (!check || e.isDirectory()) { walk(e, next) } else { next() } } }, zalgo) } walk(pw.cwd, done) } const walkFreshPWAsyncRecurse = (check: boolean = true) => (done: () => any) => { const pw = new PathScurry(dir) const walk = async (p: Path) => { const promises: Promise[] = [] for (const path of await p.readdir()) { if (!check || path.isDirectory()) { promises.push(walk(path)) } } await Promise.all(promises) } walk(pw.cwd).then(done) } // this is consistently slower than not using a stack // const walkFreshPWAsyncRecurseStack = // (check: boolean = true) => // (done: () => any) => { // const stack: Path[] = [] // const pw = new PathScurry(dir) // const walk = async (p: Path) => { // for (const path of await pw.readdir(p)) { // if (!check || path.isDirectory()) { // stack.push(path) // } // } // await process() // } // const limit = cpus().length * 4 // const process = async () => { // let f = stack.pop() // if (f) await walk(f) // } // stack.push(pw.cwd) // const workers: Promise[] = [] // for (let i = 0; i < limit; i++) { // workers.push(process()) // } // Promise.all(workers).then(done) // } // const walkFreshPWAsyncIterate = (done: () => any) => { // const pw = new PathScurry(dir) // const walk = async (p: PathBase) => { // const paths: PathBase[] = [p] // let path: PathBase | undefined // while ((path = paths.shift())) { // for (const p of await pw.readdir(path)) { // paths.push(p) // } // } // } // walk(pw.cwd).then(done) // } const walkReusePWAsyncRecurse = (check: boolean = true) => (done: () => any) => { const walk = async (p: Path) => { const promises: Promise[] = [] for (const path of await p.readdir()) { if (!check || path.isDirectory()) { promises.push(walk(path)) } } await Promise.all(promises) } walk(pwReuse.cwd).then(done) } const walkReusePWCBRecurse = (check: boolean = true, zalgo: boolean = false) => (done: () => any) => { const walk = async (path: Path, cb: () => any) => { path.readdirCB((_er, entries) => { let len = entries.length if (!len) cb() const next = () => { if (--len <= 0) cb() } for (const e of entries) { if (!check || e.isDirectory()) { walk(e, next) } else { next() } } }, zalgo) } walk(pwReuse.cwd, done) } // this is consistently slower than not using a stack // const walkReusePWAsyncRecurseStack = // (check: boolean = true) => // (done: () => any) => { // const stack: Path[] = [] // const pw = pwReuse // const walk = async (p: Path) => { // for (const path of await pw.readdir(p)) { // if (!check || path.isDirectory()) { // stack.push(path) // } // } // await process() // } // const limit = cpus().length // const process = async () => { // let f = stack.pop() // if (f) await walk(f) // } // stack.push(pw.cwd) // const workers: Promise[] = [] // for (let i = 0; i < limit; i++) { // workers.push(process()) // } // Promise.all(workers).then(done) // } // consistently slower than recursive approach // const walkReusePWAsyncIterate = (done: () => any) => { // const walk = async (p: PathBase) => { // const paths: PathBase[] = [p] // let path: PathBase | undefined // while ((path = paths.shift())) { // for (const p of await pwReuse.readdir(path)) { // paths.push(p) // } // } // } // walk(pwReuse.cwd).then(done) // } const walkReusePWSyncRecurse = (check: boolean = true) => (done: () => any) => { const walk = (p: Path) => { for (const path of pwReuse.readdirSync(p)) { if (!check || path.isDirectory()) { walk(path) } } } walk(pwReuse.cwd) done() } // const walkReusePWSyncIterate = (done: () => any) => { // const walk = async (p: PathBase) => { // const paths: PathBase[] = [p] // let path: PathBase | undefined // while ((path = paths.shift())) { // for (const p of pwReuse.readdirSync(path)) { // paths.push(p) // } // } // } // walk(pwReuse.cwd) // done() // } // doing this one without a stack and set of workers // causes the JS heap to overflow, every time. const walkFsReaddirAsyncRecurseStack = (check: boolean = true) => (done: () => any) => { const stack: string[] = [] const walk = async (p: string) => { const entries = await readdir(p, { withFileTypes: true }).catch( () => [] ) for (const entry of entries) { if (!check || entry.isDirectory()) { stack.push(resolve(p, entry.name)) } } await process() } const limit = cpus().length const process = async () => { let f = stack.pop() if (f) await walk(f) } stack.push(dir) const workers: Promise[] = [] for (let i = 0; i < limit; i++) { workers.push(process()) } Promise.all(workers).then(done) } // this one always crashes, very frustrating // const walkFsReaddirAsyncRecurse = (done: () => any) => { // const walk = async (p: string) => { // const entries = await readdir(dir, { withFileTypes: true }) // const promises: Promise[] = [] // for (const entry of entries) { // if (entry.isDirectory()) { // promises.push(walk(resolve(p, entry.name))) // } // } // return await Promise.all(promises).then(() => {}) // } // walk(dir).then(done) // } // // const walkFsReaddirAsyncIterate = (done: () => any) => { // const walk = async (p: string) => { // const paths: string[] = [p] // for (const path of paths) { // const entries = await readdir(dir, { // withFileTypes: true, // }).catch(() => []) // for (const entry of entries) { // paths.push(resolve(path, entry.name)) // } // } // } // walk(dir).then(done) // } // // const walkFsReaddirSyncRecurse = (done: () => any) => { // const walk = (p: string) => { // let entries: Dirent[] // try { // entries = readdirSync(dir, { withFileTypes: true }) // } catch (_) { // entries = [] // } // for (const entry of entries) { // walk(resolve(p, entry.name)) // } // } // walk(dir) // done() // } const walkFsOpendirAsyncRecurse = (check: boolean = true) => (done: () => any) => { const walk = async (p: string) => { const dir = await opendir(p).catch(() => []) const promises: Promise[] = [] for await (const entry of dir) { if (!check || entry.isDirectory()) { promises.push(walk(resolve(p, entry.name))) } } await Promise.all(promises) } walk(dir).then(done) } // const walkFsReaddirSyncIterate = (done: () => any) => { // const walk = (p: string) => { // const paths: string[] = [p] // let path: string | undefined // while ((path = paths.shift())) { // let entries: Dirent[] // try { // entries = readdirSync(path, { withFileTypes: true }) // } catch (_) { // entries = [] // } // for (const p of entries) { // paths.push(resolve(path, p.name)) // } // } // } // walk(dir) // done() // } const walkFsOpendirSyncRecurse = (check: boolean = true) => (done: () => any) => { const walk = (p: string) => { let dir: Dir try { dir = opendirSync(p) try { let e: Dirent | null while ((e = dir.readSync())) { if (!check || e.isDirectory()) { walk(resolve(p, e.name)) } } } finally { dir.closeSync() } } catch (_) {} } walk(dir) done() } // const walkFsOpendirAsyncIterate = (done: () => any) => { // const walk = async (p: string) => { // const paths: string[] = [resolve(dir, p)] // let path: string | undefined // while ((path = paths.shift())) { // const pp = path // const dir = await opendir(pp).catch(() => []) // for await (const entry of dir) { // paths.push(resolve(pp, entry.name)) // } // } // } // walk(dir).then(done) // } // // const walkFsOpendirSyncIterate = (done: () => any) => { // const walk = (p: string) => { // const paths: string[] = [resolve(dir, p)] // let path: string | undefined // while ((path = paths.shift())) { // let entries: Dirent[] // try { // entries = readdirSync(path, { withFileTypes: true }) // } catch (_) { // entries = [] // } // for (const p of entries) { // paths.push(resolve(path, p.name)) // } // } // } // walk(dir) // done() // } const N = 1 const run = async (fn: (done: () => void) => void) => { gc && gc() const start = performance.now() const e = start + 3000 let count = 0 while (performance.now() < e) { for (let i = 0; i < N; i++) { try { await new Promise(res => fn(res)) } catch (er) { console.error(er) return NaN } } count += N * totalCreated } const elapsed = performance.now() - start gc && gc() const score = count / elapsed return score } const cases: () => ( | [string, (done: () => void) => void] | string )[] = () => [ 'Fresh PathScurry.walk()', ['stream', pwWalkFreshStream], ['sync stream', pwWalkFreshStreamSync], ['async walk', pwWalkFreshAsync], [' sync walk', pwWalkFreshSync], ['async iter', pwWalkFreshIterate], [' sync iter', pwWalkFreshIterateSync], ['async stream iter', pwWalkFreshStriterate], [' sync stream iter', pwWalkFreshStriterateSync], // no discernable difference between for/[await/]of and // calling the iterator directly. // [' fao', pwWalkFreshForAwaitOf], // [' fo', pwWalkFreshForOf], 'Reuse PathScurry.walk()', [' stream', pwWalkReuseStream], ['sync stream', pwWalkReuseStreamSync], ['async walk', pwWalkReuseAsync], [' sync walk', pwWalkReuseSync], ['async iter', pwWalkReuseIterate], [' sync iter', pwWalkReuseIterateSync], ['async stream iter', pwWalkReuseStriterate], [' sync stream iter', pwWalkReuseStriterateSync], // [' fao', pwWalkReuseForAwaitOf], // [' fo', pwWalkReuseForOf], 'Reuse PathScurry, manual, check isDirectory()', ['async', walkReusePWAsyncRecurse(true)], [' cb', walkReusePWCBRecurse(true)], ['zalgo', walkReusePWCBRecurse(true, true)], [' sync', walkReusePWSyncRecurse(true)], 'Reuse PathScurry, manual, no isDirectory() check', ['async', walkReusePWAsyncRecurse(false)], [' cb', walkReusePWCBRecurse(false)], ['zalgo', walkReusePWCBRecurse(false, true)], [' sync', walkReusePWSyncRecurse(false)], 'Fresh PathScurry, manual, check isDirectory()', ['async', walkFreshPWAsyncRecurse(true)], [' cb', walkFreshPWCBRecurse(true)], ['zalgo', walkFreshPWCBRecurse(true, true)], [' sync', walkFreshPWSyncRecurse(true)], 'Fresh PathScurry, manual, no isDirectory() check', ['async', walkFreshPWAsyncRecurse(false)], [' cb', walkFreshPWCBRecurse(false)], ['zalgo', walkFreshPWCBRecurse(false, true)], [' sync', walkFreshPWSyncRecurse(false)], '@nodelib/fs.walk', ['stream', fsWalkStream], [' async', fsWalkAsync], [' sync', fsWalkSync], 'stop', 'fs.opendir() iteration, check isDirectory()', [' async', walkFsOpendirAsyncRecurse(true)], [' sync', walkFsOpendirSyncRecurse(true)], 'fs.opendir() iteration, no check', [' async', walkFsOpendirAsyncRecurse(false)], [' sync', walkFsOpendirSyncRecurse(false)], 'fs.readdir() with promise stack, check isDirectory()', [' async', walkFsReaddirAsyncRecurseStack(true)], 'fs.readdir() with promise stack, no check', [' async', walkFsReaddirAsyncRecurseStack(false)], // 'PathScurry async with promise stack, no check', // ['fresh', walkFreshPWAsyncRecurseStack(false)], // ['reuse', walkReusePWAsyncRecurseStack(false)], // the iterative approaches are super slow, don't even bother // ['iterative fresh PW async', walkFreshPWAsyncIterate], // ['iterative fresh PW sync', walkFreshPWSyncIterate], // ['iterative reuse PW async', walkReusePWAsyncIterate], // ['iterative reuse PW sync', walkReusePWSyncIterate], // ['iterative fs opendir async', walkFsOpendirAsyncIterate], // ['iterative fs opendir sync', walkFsOpendirSyncIterate], // these crash with OOM errors because too much GC // ['recursive fs readdir async', walkFsReaddirAsyncRecurse], // ['recursive fs readdir sync', walkFsReaddirSyncRecurse], // ['iterative fs readdir async', walkFsReaddirAsyncIterate], ] const pwReuse = new PathScurry(dir) const main = async () => { setup(dir) console.log('showing results in operations / second (bigger is better)') const allCases = cases() const namelen = allCases .filter(a => Array.isArray(a)) .reduce((a, b) => Math.max(a, b[0].length), 0) for (const entry of cases()) { if (entry === 'stop') break if (typeof entry === 'string') { console.log(entry) continue } const [name, fn] = entry process.stdout.write(` ${name}: `.padStart(namelen + 6)) const score = await run(fn) const r = Math.floor(score) const d = '.' + Math.floor((score - r) * 1000) console.log(`${Math.round(score)}`.padStart(5) + d) } } main() isaacs-path-scurry-06957ec/scripts/fixup.sh000066400000000000000000000002261443124316700207630ustar00rootroot00000000000000#!/usr/bin/env bash cat >dist/cjs/package.json <dist/mjs/package.json < i) function* syncIterate() { for (const i of arr) { yield i } } function syncCaller() { const arr = [] for (const a of syncIterate()) { arr.push(a) } } async function* asyncIterate() { for await (const i of arr) { yield i } } async function asyncCaller() { const arr = [] for await (const i of asyncIterate()) { arr.push(i) } } async function asyncCallerSync() { const arr = [] for (const i of syncIterate()) { arr.push(i) } } const run = async fn => { const s = performance.now() const e = s + 1000 let count = 0 while (performance.now() < e) { await Promise.resolve(fn()) count++ } const dur = performance.now() - s return count / dur } const cases = [ [' async', asyncCaller], [' sync', syncCaller], ['async sync', asyncCallerSync], ] async function main() { for (const [name, fn] of cases) { console.log(name, await run(fn)) } } main() isaacs-path-scurry-06957ec/scripts/ref-array-vs-index-array.ts000077500000000000000000000127351443124316700244160ustar00rootroot00000000000000#!/usr/bin/env node --expose_gc --loader=ts-node/esm --no-warnings // Say that we have K items in a tree, each of which has W subtree links. // // Is it better for each item to store an array of child item references, or to // store all the items in a single array, and have each item store an array of // numeric indexes? // // Conclusion is quite interesting! Using an index array *seems* considerably // faster, but on further investigation, that performance improvment mostly // evaporates (or even flips) if you actually do anything with the children, // like iterating over them calling some function. In all such cases, it's // slightly better for the items to have a direct reference to the array of // items itself, rather than a reference to the Store object. // // So, the bottom line is, for directory walks that are just trivially building // up a tree and throwing it away for a synthetic benchmark, an index array is // much better, but if you're actually doing any relevant work, it's *maybe* // worth doing, but much less of a slam dunk. class ItemOne { children: ItemOne[] = [] parent?: ItemOne getParent() { return this.parent } getChildren() { return this.children.slice() } } class StoreOne { root?: ItemOne length: number = 0 drop() { this.root = undefined this.length = 0 } addItem(parent?: ItemOne) { const i = new ItemOne() i.parent = parent if (!parent) this.root = i else parent.children.push(i) this.length++ return i } getItem(i: ItemOne) { return i } } class ItemTwo { children: number[] = [] parent?: number store: StoreTwo constructor(store: StoreTwo) { this.store = store } getParent() { return this.parent === undefined ? undefined : this.store.items[this.parent] } getChildren() { return this.children.slice() } } class StoreTwo { items: ItemTwo[] = [] root?: number length: number = 0 drop() { this.root = undefined this.items.length = 0 this.length = 0 } addItem(parent?: number) { const i = new ItemTwo(this) if (parent !== undefined) i.parent = parent else this.root = this.items.length const r = this.items.length this.items.push(i) this.length++ return r } getItem(i: number) { return this.items[i] } } // same as 2, but a ref to the list is shared by the members, // rather than items having a reference to the Store object. class ItemThree { children: number[] = [] parent?: number store: ItemThree[] constructor(store: ItemThree[]) { this.store = store } getParent() { return this.parent === undefined ? undefined : this.store[this.parent] } getChildren() { return this.children.slice() } } class StoreThree { items: ItemThree[] = [] root?: number length: number = 0 drop() { this.root = undefined this.items.length = 0 this.length = 0 } addItem(parent?: number) { const i = new ItemThree(this.items) if (parent !== undefined) i.parent = parent else this.root = this.items.length const r = this.items.length this.items.push(i) this.length++ return r } getItem(i: number) { return this.items[i] } } const fill = ( s: StoreOne | StoreTwo | StoreThree, operation: 'none' | 'iterate' | 'walk', count: number, width: number, parent: ItemOne | number ) => { //@ts-ignore const i = s.addItem(parent) // add w items, each with (count - 1)/w sub-children const c = count - 1 const w = Math.min(c, width) for (let j = 0; j < w; j++) { const subc = j === 0 ? Math.ceil(c / w) : Math.floor(c / w) //@ts-ignore fill(s, operation, subc, width, s.addItem(i)) } if (operation === 'iterate') { //@ts-ignore for (const c of s.getItem(i).getChildren()) { //@ts-ignore const item = s.getItem(c) if (item.parent !== i) { throw new Error('broken tree') } } } if (parent === undefined) { if (operation === 'walk') { //@ts-ignore function walk(i: any) { //@ts-ignore for (const c of s.getItem(i).getChildren()) { walk(c) } } walk(s) } if (s.length !== c) { throw new Error(`got=${s.length}, expect=${c}`) } } return i } const N = 100 // runs per iteration loop const run = ( Store: typeof StoreOne | typeof StoreTwo | typeof StoreThree, operation: 'none' | 'iterate' | 'walk', K: number, W: number ) => { let count = 0 const start = performance.now() const e = start + 1000 while (performance.now() < e) { const s = new Store() for (let i = 0; i < N; i++) { fill(s, operation, K - 1, W, s.addItem()) s.drop() count += N } } const end = performance.now() const dur = end - start return count / dur } const cases: [ string, typeof StoreOne | typeof StoreTwo | typeof StoreThree ][] = [ ['item has ref array ', StoreOne], ['store has number array', StoreTwo], ['item has number array ', StoreThree], ] // [keys, width] const KW: [number, number][] = [ [100, 10], [1000, 10], [10_000, 10], [10_000, 10_000], // 1 root node with 9_999 children [100_000, 2], [100_000, 100], ] console.log('putting K items in a tree of W width and then dropping') console.log('scores in operations / ms, higher number is better') for (const it of ['none', 'iterate', 'walk'] as const) { for (const [K, W] of KW) { console.log(`K=${K} W=${W} operation=${it}`) for (const [name, cls] of cases) { console.log(name, run(cls, it, K, W)) } } } export {} isaacs-path-scurry-06957ec/src/000077500000000000000000000000001443124316700163745ustar00rootroot00000000000000isaacs-path-scurry-06957ec/src/index.ts000066400000000000000000002301251443124316700200560ustar00rootroot00000000000000import { LRUCache } from 'lru-cache' import { posix, win32 } from 'path' import { fileURLToPath } from 'url' import * as actualFS from 'fs' import { lstatSync, readdir as readdirCB, readdirSync, readlinkSync, realpathSync as rps, } from 'fs' const realpathSync = rps.native // TODO: test perf of fs/promises realpath vs realpathCB, // since the promises one uses realpath.native import { lstat, readdir, readlink, realpath } from 'fs/promises' import type { Dirent, Stats } from 'fs' import { Minipass } from 'minipass' /** * An object that will be used to override the default `fs` * methods. Any methods that are not overridden will use Node's * built-in implementations. * * - lstatSync * - readdir (callback `withFileTypes` Dirent variant, used for * readdirCB and most walks) * - readdirSync * - readlinkSync * - realpathSync * - promises: Object containing the following async methods: * - lstat * - readdir (Dirent variant only) * - readlink * - realpath */ export interface FSOption { lstatSync?: (path: string) => Stats readdir?: ( path: string, options: { withFileTypes: true }, cb: (er: NodeJS.ErrnoException | null, entries?: Dirent[]) => any ) => void readdirSync?: ( path: string, options: { withFileTypes: true } ) => Dirent[] readlinkSync?: (path: string) => string realpathSync?: (path: string) => string promises?: { lstat?: (path: string) => Promise readdir?: ( path: string, options: { withFileTypes: true } ) => Promise readlink?: (path: string) => Promise realpath?: (path: string) => Promise [k: string]: any } [k: string]: any } interface FSValue { lstatSync: (path: string) => Stats readdir: ( path: string, options: { withFileTypes: true }, cb: (er: NodeJS.ErrnoException | null, entries?: Dirent[]) => any ) => void readdirSync: (path: string, options: { withFileTypes: true }) => Dirent[] readlinkSync: (path: string) => string realpathSync: (path: string) => string promises: { lstat: (path: string) => Promise readdir: ( path: string, options: { withFileTypes: true } ) => Promise readlink: (path: string) => Promise realpath: (path: string) => Promise [k: string]: any } [k: string]: any } const defaultFS: FSValue = { lstatSync, readdir: readdirCB, readdirSync, readlinkSync, realpathSync, promises: { lstat, readdir, readlink, realpath, }, } // if they just gave us require('fs') then use our default const fsFromOption = (fsOption?: FSOption): FSValue => !fsOption || fsOption === defaultFS || fsOption === actualFS ? defaultFS : { ...defaultFS, ...fsOption, promises: { ...defaultFS.promises, ...(fsOption.promises || {}), }, } // turn something like //?/c:/ into c:\ const uncDriveRegexp = /^\\\\\?\\([a-z]:)\\?$/i const uncToDrive = (rootPath: string): string => rootPath.replace(/\//g, '\\').replace(uncDriveRegexp, '$1\\') // windows paths are separated by either / or \ const eitherSep = /[\\\/]/ const UNKNOWN = 0 // may not even exist, for all we know const IFIFO = 0b0001 const IFCHR = 0b0010 const IFDIR = 0b0100 const IFBLK = 0b0110 const IFREG = 0b1000 const IFLNK = 0b1010 const IFSOCK = 0b1100 const IFMT = 0b1111 // mask to unset low 4 bits const IFMT_UNKNOWN = ~IFMT // set after successfully calling readdir() and getting entries. const READDIR_CALLED = 0b0000_0001_0000 // set after a successful lstat() const LSTAT_CALLED = 0b0000_0010_0000 // set if an entry (or one of its parents) is definitely not a dir const ENOTDIR = 0b0000_0100_0000 // set if an entry (or one of its parents) does not exist // (can also be set on lstat errors like EACCES or ENAMETOOLONG) const ENOENT = 0b0000_1000_0000 // cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK // set if we fail to readlink const ENOREADLINK = 0b0001_0000_0000 // set if we know realpath() will fail const ENOREALPATH = 0b0010_0000_0000 const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH const TYPEMASK = 0b0011_1111_1111 const entToType = (s: Dirent | Stats) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN // normalize unicode path names const normalizeCache = new Map() const normalize = (s: string) => { const c = normalizeCache.get(s) if (c) return c const n = s.normalize('NFKD') normalizeCache.set(s, n) return n } const normalizeNocaseCache = new Map() const normalizeNocase = (s: string) => { const c = normalizeNocaseCache.get(s) if (c) return c const n = normalize(s.toLowerCase()) normalizeNocaseCache.set(s, n) return n } /** * Options that may be provided to the Path constructor */ export interface PathOpts { fullpath?: string relative?: string relativePosix?: string parent?: PathBase /** * See {@link FSOption} */ fs?: FSOption } /** * An LRUCache for storing resolved path strings or Path objects. * @internal */ export class ResolveCache extends LRUCache { constructor() { super({ max: 256 }) } } // In order to prevent blowing out the js heap by allocating hundreds of // thousands of Path entries when walking extremely large trees, the "children" // in this tree are represented by storing an array of Path entries in an // LRUCache, indexed by the parent. At any time, Path.children() may return an // empty array, indicating that it doesn't know about any of its children, and // thus has to rebuild that cache. This is fine, it just means that we don't // benefit as much from having the cached entries, but huge directory walks // don't blow out the stack, and smaller ones are still as fast as possible. // //It does impose some complexity when building up the readdir data, because we //need to pass a reference to the children array that we started with. /** * an LRUCache for storing child entries. * @internal */ export class ChildrenCache extends LRUCache { constructor(maxSize: number = 16 * 1024) { super({ maxSize, // parent + children sizeCalculation: a => a.length + 1, }) } } /** * Array of Path objects, plus a marker indicating the first provisional entry * * @internal */ export type Children = PathBase[] & { provisional: number } const setAsCwd = Symbol('PathScurry setAsCwd') /** * Path objects are sort of like a super-powered * {@link https://nodejs.org/docs/latest/api/fs.html#class-fsdirent fs.Dirent} * * Each one represents a single filesystem entry on disk, which may or may not * exist. It includes methods for reading various types of information via * lstat, readlink, and readdir, and caches all information to the greatest * degree possible. * * Note that fs operations that would normally throw will instead return an * "empty" value. This is in order to prevent excessive overhead from error * stack traces. */ export abstract class PathBase implements Dirent { /** * the basename of this path * * **Important**: *always* test the path name against any test string * usingthe {@link isNamed} method, and not by directly comparing this * string. Otherwise, unicode path strings that the system sees as identical * will not be properly treated as the same path, leading to incorrect * behavior and possible security issues. */ name: string /** * the Path entry corresponding to the path root. * * @internal */ root: PathBase /** * All roots found within the current PathScurry family * * @internal */ roots: { [k: string]: PathBase } /** * a reference to the parent path, or undefined in the case of root entries * * @internal */ parent?: PathBase /** * boolean indicating whether paths are compared case-insensitively * @internal */ nocase: boolean /** * the string or regexp used to split paths. On posix, it is `'/'`, and on * windows it is a RegExp matching either `'/'` or `'\\'` */ abstract splitSep: string | RegExp /** * The path separator string to use when joining paths */ abstract sep: string // potential default fs override #fs: FSValue // Stats fields #dev?: number get dev() { return this.#dev } #mode?: number get mode() { return this.#mode } #nlink?: number get nlink() { return this.#nlink } #uid?: number get uid() { return this.#uid } #gid?: number get gid() { return this.#gid } #rdev?: number get rdev() { return this.#rdev } #blksize?: number get blksize() { return this.#blksize } #ino?: number get ino() { return this.#ino } #size?: number get size() { return this.#size } #blocks?: number get blocks() { return this.#blocks } #atimeMs?: number get atimeMs() { return this.#atimeMs } #mtimeMs?: number get mtimeMs() { return this.#mtimeMs } #ctimeMs?: number get ctimeMs() { return this.#ctimeMs } #birthtimeMs?: number get birthtimeMs() { return this.#birthtimeMs } #atime?: Date get atime() { return this.#atime } #mtime?: Date get mtime() { return this.#mtime } #ctime?: Date get ctime() { return this.#ctime } #birthtime?: Date get birthtime() { return this.#birthtime } #matchName: string #depth?: number #fullpath?: string #fullpathPosix?: string #relative?: string #relativePosix?: string #type: number #children: ChildrenCache #linkTarget?: PathBase #realpath?: PathBase /** * This property is for compatibility with the Dirent class as of * Node v20, where Dirent['path'] refers to the path of the directory * that was passed to readdir. So, somewhat counterintuitively, this * property refers to the *parent* path, not the path object itself. * For root entries, it's the path to the entry itself. */ get path(): string { return (this.parent || this).fullpath() } /** * Do not create new Path objects directly. They should always be accessed * via the PathScurry class or other methods on the Path class. * * @internal */ constructor( name: string, type: number = UNKNOWN, root: PathBase | undefined, roots: { [k: string]: PathBase }, nocase: boolean, children: ChildrenCache, opts: PathOpts ) { this.name = name this.#matchName = nocase ? normalizeNocase(name) : normalize(name) this.#type = type & TYPEMASK this.nocase = nocase this.roots = roots this.root = root || this this.#children = children this.#fullpath = opts.fullpath this.#relative = opts.relative this.#relativePosix = opts.relativePosix this.parent = opts.parent if (this.parent) { this.#fs = this.parent.#fs } else { this.#fs = fsFromOption(opts.fs) } } /** * Returns the depth of the Path object from its root. * * For example, a path at `/foo/bar` would have a depth of 2. */ depth(): number { if (this.#depth !== undefined) return this.#depth if (!this.parent) return (this.#depth = 0) return (this.#depth = this.parent.depth() + 1) } /** * @internal */ abstract getRootString(path: string): string /** * @internal */ abstract getRoot(rootPath: string): PathBase /** * @internal */ abstract newChild(name: string, type?: number, opts?: PathOpts): PathBase /** * @internal */ childrenCache() { return this.#children } /** * Get the Path object referenced by the string path, resolved from this Path */ resolve(path?: string): PathBase { if (!path) { return this } const rootPath = this.getRootString(path) const dir = path.substring(rootPath.length) const dirParts = dir.split(this.splitSep) const result: PathBase = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts) return result } #resolveParts(dirParts: string[]) { let p: PathBase = this for (const part of dirParts) { p = p.child(part) } return p } /** * Returns the cached children Path objects, if still available. If they * have fallen out of the cache, then returns an empty array, and resets the * READDIR_CALLED bit, so that future calls to readdir() will require an fs * lookup. * * @internal */ children(): Children { const cached = this.#children.get(this) if (cached) { return cached } const children: Children = Object.assign([], { provisional: 0 }) this.#children.set(this, children) this.#type &= ~READDIR_CALLED return children } /** * Resolves a path portion and returns or creates the child Path. * * Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is * `'..'`. * * This should not be called directly. If `pathPart` contains any path * separators, it will lead to unsafe undefined behavior. * * Use `Path.resolve()` instead. * * @internal */ child(pathPart: string, opts?: PathOpts): PathBase { if (pathPart === '' || pathPart === '.') { return this } if (pathPart === '..') { return this.parent || this } // find the child const children = this.children() const name = this.nocase ? normalizeNocase(pathPart) : normalize(pathPart) for (const p of children) { if (p.#matchName === name) { return p } } // didn't find it, create provisional child, since it might not // actually exist. If we know the parent isn't a dir, then // in fact it CAN'T exist. const s = this.parent ? this.sep : '' const fullpath = this.#fullpath ? this.#fullpath + s + pathPart : undefined const pchild = this.newChild(pathPart, UNKNOWN, { ...opts, parent: this, fullpath, }) if (!this.canReaddir()) { pchild.#type |= ENOENT } // don't have to update provisional, because if we have real children, // then provisional is set to children.length, otherwise a lower number children.push(pchild) return pchild } /** * The relative path from the cwd. If it does not share an ancestor with * the cwd, then this ends up being equivalent to the fullpath() */ relative(): string { if (this.#relative !== undefined) { return this.#relative } const name = this.name const p = this.parent if (!p) { return (this.#relative = this.name) } const pv = p.relative() return pv + (!pv || !p.parent ? '' : this.sep) + name } /** * The relative path from the cwd, using / as the path separator. * If it does not share an ancestor with * the cwd, then this ends up being equivalent to the fullpathPosix() * On posix systems, this is identical to relative(). */ relativePosix(): string { if (this.sep === '/') return this.relative() if (this.#relativePosix !== undefined) return this.#relativePosix const name = this.name const p = this.parent if (!p) { return (this.#relativePosix = this.fullpathPosix()) } const pv = p.relativePosix() return pv + (!pv || !p.parent ? '' : '/') + name } /** * The fully resolved path string for this Path entry */ fullpath(): string { if (this.#fullpath !== undefined) { return this.#fullpath } const name = this.name const p = this.parent if (!p) { return (this.#fullpath = this.name) } const pv = p.fullpath() const fp = pv + (!p.parent ? '' : this.sep) + name return (this.#fullpath = fp) } /** * On platforms other than windows, this is identical to fullpath. * * On windows, this is overridden to return the forward-slash form of the * full UNC path. */ fullpathPosix(): string { if (this.#fullpathPosix !== undefined) return this.#fullpathPosix if (this.sep === '/') return (this.#fullpathPosix = this.fullpath()) if (!this.parent) { const p = this.fullpath().replace(/\\/g, '/') if (/^[a-z]:\//i.test(p)) { return (this.#fullpathPosix = `//?/${p}`) } else { return (this.#fullpathPosix = p) } } const p = this.parent const pfpp = p.fullpathPosix() const fpp = pfpp + (!pfpp || !p.parent ? '' : '/') + this.name return (this.#fullpathPosix = fpp) } /** * Is the Path of an unknown type? * * Note that we might know *something* about it if there has been a previous * filesystem operation, for example that it does not exist, or is not a * link, or whether it has child entries. */ isUnknown(): boolean { return (this.#type & IFMT) === UNKNOWN } /** * Is the Path a regular file? */ isFile(): boolean { return (this.#type & IFMT) === IFREG } /** * Is the Path a directory? */ isDirectory(): boolean { return (this.#type & IFMT) === IFDIR } /** * Is the path a character device? */ isCharacterDevice(): boolean { return (this.#type & IFMT) === IFCHR } /** * Is the path a block device? */ isBlockDevice(): boolean { return (this.#type & IFMT) === IFBLK } /** * Is the path a FIFO pipe? */ isFIFO(): boolean { return (this.#type & IFMT) === IFIFO } /** * Is the path a socket? */ isSocket(): boolean { return (this.#type & IFMT) === IFSOCK } /** * Is the path a symbolic link? */ isSymbolicLink(): boolean { return (this.#type & IFLNK) === IFLNK } /** * Return the entry if it has been subject of a successful lstat, or * undefined otherwise. * * Does not read the filesystem, so an undefined result *could* simply * mean that we haven't called lstat on it. */ lstatCached(): PathBase | undefined { return this.#type & LSTAT_CALLED ? this : undefined } /** * Return the cached link target if the entry has been the subject of a * successful readlink, or undefined otherwise. * * Does not read the filesystem, so an undefined result *could* just mean we * don't have any cached data. Only use it if you are very sure that a * readlink() has been called at some point. */ readlinkCached(): PathBase | undefined { return this.#linkTarget } /** * Returns the cached realpath target if the entry has been the subject * of a successful realpath, or undefined otherwise. * * Does not read the filesystem, so an undefined result *could* just mean we * don't have any cached data. Only use it if you are very sure that a * realpath() has been called at some point. */ realpathCached(): PathBase | undefined { return this.#realpath } /** * Returns the cached child Path entries array if the entry has been the * subject of a successful readdir(), or [] otherwise. * * Does not read the filesystem, so an empty array *could* just mean we * don't have any cached data. Only use it if you are very sure that a * readdir() has been called recently enough to still be valid. */ readdirCached(): PathBase[] { const children = this.children() return children.slice(0, children.provisional) } /** * Return true if it's worth trying to readlink. Ie, we don't (yet) have * any indication that readlink will definitely fail. * * Returns false if the path is known to not be a symlink, if a previous * readlink failed, or if the entry does not exist. */ canReadlink(): boolean { if (this.#linkTarget) return true if (!this.parent) return false // cases where it cannot possibly succeed const ifmt = this.#type & IFMT return !( (ifmt !== UNKNOWN && ifmt !== IFLNK) || this.#type & ENOREADLINK || this.#type & ENOENT ) } /** * Return true if readdir has previously been successfully called on this * path, indicating that cachedReaddir() is likely valid. */ calledReaddir(): boolean { return !!(this.#type & READDIR_CALLED) } /** * Returns true if the path is known to not exist. That is, a previous lstat * or readdir failed to verify its existence when that would have been * expected, or a parent entry was marked either enoent or enotdir. */ isENOENT(): boolean { return !!(this.#type & ENOENT) } /** * Return true if the path is a match for the given path name. This handles * case sensitivity and unicode normalization. * * Note: even on case-sensitive systems, it is **not** safe to test the * equality of the `.name` property to determine whether a given pathname * matches, due to unicode normalization mismatches. * * Always use this method instead of testing the `path.name` property * directly. */ isNamed(n: string): boolean { return !this.nocase ? this.#matchName === normalize(n) : this.#matchName === normalizeNocase(n) } /** * Return the Path object corresponding to the target of a symbolic link. * * If the Path is not a symbolic link, or if the readlink call fails for any * reason, `undefined` is returned. * * Result is cached, and thus may be outdated if the filesystem is mutated. */ async readlink(): Promise { const target = this.#linkTarget if (target) { return target } if (!this.canReadlink()) { return undefined } /* c8 ignore start */ // already covered by the canReadlink test, here for ts grumples if (!this.parent) { return undefined } /* c8 ignore stop */ try { const read = await this.#fs.promises.readlink(this.fullpath()) const linkTarget = this.parent.resolve(read) if (linkTarget) { return (this.#linkTarget = linkTarget) } } catch (er) { this.#readlinkFail((er as NodeJS.ErrnoException).code) return undefined } } /** * Synchronous {@link PathBase.readlink} */ readlinkSync(): PathBase | undefined { const target = this.#linkTarget if (target) { return target } if (!this.canReadlink()) { return undefined } /* c8 ignore start */ // already covered by the canReadlink test, here for ts grumples if (!this.parent) { return undefined } /* c8 ignore stop */ try { const read = this.#fs.readlinkSync(this.fullpath()) const linkTarget = this.parent.resolve(read) if (linkTarget) { return (this.#linkTarget = linkTarget) } } catch (er) { this.#readlinkFail((er as NodeJS.ErrnoException).code) return undefined } } #readdirSuccess(children: Children) { // succeeded, mark readdir called bit this.#type |= READDIR_CALLED // mark all remaining provisional children as ENOENT for (let p = children.provisional; p < children.length; p++) { children[p].#markENOENT() } } #markENOENT() { // mark as UNKNOWN and ENOENT if (this.#type & ENOENT) return this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN this.#markChildrenENOENT() } #markChildrenENOENT() { // all children are provisional and do not exist const children = this.children() children.provisional = 0 for (const p of children) { p.#markENOENT() } } #markENOREALPATH() { this.#type |= ENOREALPATH this.#markENOTDIR() } // save the information when we know the entry is not a dir #markENOTDIR() { // entry is not a directory, so any children can't exist. // this *should* be impossible, since any children created // after it's been marked ENOTDIR should be marked ENOENT, // so it won't even get to this point. /* c8 ignore start */ if (this.#type & ENOTDIR) return /* c8 ignore stop */ let t = this.#type // this could happen if we stat a dir, then delete it, // then try to read it or one of its children. if ((t & IFMT) === IFDIR) t &= IFMT_UNKNOWN this.#type = t | ENOTDIR this.#markChildrenENOENT() } #readdirFail(code: string = '') { // markENOTDIR and markENOENT also set provisional=0 if (code === 'ENOTDIR' || code === 'EPERM') { this.#markENOTDIR() } else if (code === 'ENOENT') { this.#markENOENT() } else { this.children().provisional = 0 } } #lstatFail(code: string = '') { // Windows just raises ENOENT in this case, disable for win CI /* c8 ignore start */ if (code === 'ENOTDIR') { // already know it has a parent by this point const p = this.parent as PathBase p.#markENOTDIR() } else if (code === 'ENOENT') { /* c8 ignore stop */ this.#markENOENT() } } #readlinkFail(code: string = '') { let ter = this.#type ter |= ENOREADLINK if (code === 'ENOENT') ter |= ENOENT // windows gets a weird error when you try to readlink a file if (code === 'EINVAL' || code === 'UNKNOWN') { // exists, but not a symlink, we don't know WHAT it is, so remove // all IFMT bits. ter &= IFMT_UNKNOWN } this.#type = ter // windows just gets ENOENT in this case. We do cover the case, // just disabled because it's impossible on Windows CI /* c8 ignore start */ if (code === 'ENOTDIR' && this.parent) { this.parent.#markENOTDIR() } /* c8 ignore stop */ } #readdirAddChild(e: Dirent, c: Children) { return ( this.#readdirMaybePromoteChild(e, c) || this.#readdirAddNewChild(e, c) ) } #readdirAddNewChild(e: Dirent, c: Children): PathBase { // alloc new entry at head, so it's never provisional const type = entToType(e) const child = this.newChild(e.name, type, { parent: this }) const ifmt = child.#type & IFMT if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) { child.#type |= ENOTDIR } c.unshift(child) c.provisional++ return child } #readdirMaybePromoteChild(e: Dirent, c: Children): PathBase | undefined { for (let p = c.provisional; p < c.length; p++) { const pchild = c[p] const name = this.nocase ? normalizeNocase(e.name) : normalize(e.name) if (name !== pchild.#matchName) { continue } return this.#readdirPromoteChild(e, pchild, p, c) } } #readdirPromoteChild( e: Dirent, p: PathBase, index: number, c: Children ): PathBase { const v = p.name // retain any other flags, but set ifmt from dirent p.#type = (p.#type & IFMT_UNKNOWN) | entToType(e) // case sensitivity fixing when we learn the true name. if (v !== e.name) p.name = e.name // just advance provisional index (potentially off the list), // otherwise we have to splice/pop it out and re-insert at head if (index !== c.provisional) { if (index === c.length - 1) c.pop() else c.splice(index, 1) c.unshift(p) } c.provisional++ return p } /** * Call lstat() on this Path, and update all known information that can be * determined. * * Note that unlike `fs.lstat()`, the returned value does not contain some * information, such as `mode`, `dev`, `nlink`, and `ino`. If that * information is required, you will need to call `fs.lstat` yourself. * * If the Path refers to a nonexistent file, or if the lstat call fails for * any reason, `undefined` is returned. Otherwise the updated Path object is * returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. */ async lstat(): Promise { if ((this.#type & ENOENT) === 0) { try { this.#applyStat(await this.#fs.promises.lstat(this.fullpath())) return this } catch (er) { this.#lstatFail((er as NodeJS.ErrnoException).code) } } } /** * synchronous {@link PathBase.lstat} */ lstatSync(): PathBase | undefined { if ((this.#type & ENOENT) === 0) { try { this.#applyStat(this.#fs.lstatSync(this.fullpath())) return this } catch (er) { this.#lstatFail((er as NodeJS.ErrnoException).code) } } } #applyStat(st: Stats) { const { atime, atimeMs, birthtime, birthtimeMs, blksize, blocks, ctime, ctimeMs, dev, gid, ino, mode, mtime, mtimeMs, nlink, rdev, size, uid, } = st this.#atime = atime this.#atimeMs = atimeMs this.#birthtime = birthtime this.#birthtimeMs = birthtimeMs this.#blksize = blksize this.#blocks = blocks this.#ctime = ctime this.#ctimeMs = ctimeMs this.#dev = dev this.#gid = gid this.#ino = ino this.#mode = mode this.#mtime = mtime this.#mtimeMs = mtimeMs this.#nlink = nlink this.#rdev = rdev this.#size = size this.#uid = uid const ifmt = entToType(st) // retain any other flags, but set the ifmt this.#type = (this.#type & IFMT_UNKNOWN) | ifmt | LSTAT_CALLED if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) { this.#type |= ENOTDIR } } #onReaddirCB: (( er: NodeJS.ErrnoException | null, entries: Path[] ) => any)[] = [] #readdirCBInFlight: boolean = false #callOnReaddirCB(children: Path[]) { this.#readdirCBInFlight = false const cbs = this.#onReaddirCB.slice() this.#onReaddirCB.length = 0 cbs.forEach(cb => cb(null, children)) } /** * Standard node-style callback interface to get list of directory entries. * * If the Path cannot or does not contain any children, then an empty array * is returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. * * @param cb The callback called with (er, entries). Note that the `er` * param is somewhat extraneous, as all readdir() errors are handled and * simply result in an empty set of entries being returned. * @param allowZalgo Boolean indicating that immediately known results should * *not* be deferred with `queueMicrotask`. Defaults to `false`. Release * zalgo at your peril, the dark pony lord is devious and unforgiving. */ readdirCB( cb: (er: NodeJS.ErrnoException | null, entries: PathBase[]) => any, allowZalgo: boolean = false ): void { if (!this.canReaddir()) { if (allowZalgo) cb(null, []) else queueMicrotask(() => cb(null, [])) return } const children = this.children() if (this.calledReaddir()) { const c = children.slice(0, children.provisional) if (allowZalgo) cb(null, c) else queueMicrotask(() => cb(null, c)) return } // don't have to worry about zalgo at this point. this.#onReaddirCB.push(cb) if (this.#readdirCBInFlight) { return } this.#readdirCBInFlight = true // else read the directory, fill up children // de-provisionalize any provisional children. const fullpath = this.fullpath() this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => { if (er) { this.#readdirFail((er as NodeJS.ErrnoException).code) children.provisional = 0 } else { // if we didn't get an error, we always get entries. //@ts-ignore for (const e of entries) { this.#readdirAddChild(e, children) } this.#readdirSuccess(children) } this.#callOnReaddirCB(children.slice(0, children.provisional)) return }) } #asyncReaddirInFlight?: Promise /** * Return an array of known child entries. * * If the Path cannot or does not contain any children, then an empty array * is returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. */ async readdir(): Promise { if (!this.canReaddir()) { return [] } const children = this.children() if (this.calledReaddir()) { return children.slice(0, children.provisional) } // else read the directory, fill up children // de-provisionalize any provisional children. const fullpath = this.fullpath() if (this.#asyncReaddirInFlight) { await this.#asyncReaddirInFlight } else { /* c8 ignore start */ let resolve: () => void = () => {} /* c8 ignore stop */ this.#asyncReaddirInFlight = new Promise( res => (resolve = res) ) try { for (const e of await this.#fs.promises.readdir(fullpath, { withFileTypes: true, })) { this.#readdirAddChild(e, children) } this.#readdirSuccess(children) } catch (er) { this.#readdirFail((er as NodeJS.ErrnoException).code) children.provisional = 0 } this.#asyncReaddirInFlight = undefined resolve() } return children.slice(0, children.provisional) } /** * synchronous {@link PathBase.readdir} */ readdirSync(): PathBase[] { if (!this.canReaddir()) { return [] } const children = this.children() if (this.calledReaddir()) { return children.slice(0, children.provisional) } // else read the directory, fill up children // de-provisionalize any provisional children. const fullpath = this.fullpath() try { for (const e of this.#fs.readdirSync(fullpath, { withFileTypes: true, })) { this.#readdirAddChild(e, children) } this.#readdirSuccess(children) } catch (er) { this.#readdirFail((er as NodeJS.ErrnoException).code) children.provisional = 0 } return children.slice(0, children.provisional) } canReaddir() { if (this.#type & ENOCHILD) return false const ifmt = IFMT & this.#type // we always set ENOTDIR when setting IFMT, so should be impossible /* c8 ignore start */ if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) { return false } /* c8 ignore stop */ return true } shouldWalk( dirs: Set, walkFilter?: (e: PathBase) => boolean ): boolean { return ( (this.#type & IFDIR) === IFDIR && !(this.#type & ENOCHILD) && !dirs.has(this) && (!walkFilter || walkFilter(this)) ) } /** * Return the Path object corresponding to path as resolved * by realpath(3). * * If the realpath call fails for any reason, `undefined` is returned. * * Result is cached, and thus may be outdated if the filesystem is mutated. * On success, returns a Path object. */ async realpath(): Promise { if (this.#realpath) return this.#realpath if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return undefined try { const rp = await this.#fs.promises.realpath(this.fullpath()) return (this.#realpath = this.resolve(rp)) } catch (_) { this.#markENOREALPATH() } } /** * Synchronous {@link realpath} */ realpathSync(): PathBase | undefined { if (this.#realpath) return this.#realpath if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return undefined try { const rp = this.#fs.realpathSync(this.fullpath()) return (this.#realpath = this.resolve(rp)) } catch (_) { this.#markENOREALPATH() } } /** * Internal method to mark this Path object as the scurry cwd, * called by {@link PathScurry#chdir} * * @internal */ [setAsCwd](oldCwd: PathBase): void { if (oldCwd === this) return const changed = new Set([]) let rp = [] let p: PathBase = this while (p && p.parent) { changed.add(p) p.#relative = rp.join(this.sep) p.#relativePosix = rp.join('/') p = p.parent rp.push('..') } // now un-memoize parents of old cwd p = oldCwd while (p && p.parent && !changed.has(p)) { p.#relative = undefined p.#relativePosix = undefined p = p.parent } } } /** * Path class used on win32 systems * * Uses `'\\'` as the path separator for returned paths, either `'\\'` or `'/'` * as the path separator for parsing paths. */ export class PathWin32 extends PathBase { /** * Separator for generating path strings. */ sep: '\\' = '\\' /** * Separator for parsing path strings. */ splitSep: RegExp = eitherSep /** * Do not create new Path objects directly. They should always be accessed * via the PathScurry class or other methods on the Path class. * * @internal */ constructor( name: string, type: number = UNKNOWN, root: PathBase | undefined, roots: { [k: string]: PathBase }, nocase: boolean, children: ChildrenCache, opts: PathOpts ) { super(name, type, root, roots, nocase, children, opts) } /** * @internal */ newChild(name: string, type: number = UNKNOWN, opts: PathOpts = {}) { return new PathWin32( name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts ) } /** * @internal */ getRootString(path: string): string { return win32.parse(path).root } /** * @internal */ getRoot(rootPath: string): PathBase { rootPath = uncToDrive(rootPath.toUpperCase()) if (rootPath === this.root.name) { return this.root } // ok, not that one, check if it matches another we know about for (const [compare, root] of Object.entries(this.roots)) { if (this.sameRoot(rootPath, compare)) { return (this.roots[rootPath] = root) } } // otherwise, have to create a new one. return (this.roots[rootPath] = new PathScurryWin32( rootPath, this ).root) } /** * @internal */ sameRoot(rootPath: string, compare: string = this.root.name): boolean { // windows can (rarely) have case-sensitive filesystem, but // UNC and drive letters are always case-insensitive, and canonically // represented uppercase. rootPath = rootPath .toUpperCase() .replace(/\//g, '\\') .replace(uncDriveRegexp, '$1\\') return rootPath === compare } } /** * Path class used on all posix systems. * * Uses `'/'` as the path separator. */ export class PathPosix extends PathBase { /** * separator for parsing path strings */ splitSep: '/' = '/' /** * separator for generating path strings */ sep: '/' = '/' /** * Do not create new Path objects directly. They should always be accessed * via the PathScurry class or other methods on the Path class. * * @internal */ constructor( name: string, type: number = UNKNOWN, root: PathBase | undefined, roots: { [k: string]: PathBase }, nocase: boolean, children: ChildrenCache, opts: PathOpts ) { super(name, type, root, roots, nocase, children, opts) } /** * @internal */ getRootString(path: string): string { return path.startsWith('/') ? '/' : '' } /** * @internal */ getRoot(_rootPath: string): PathBase { return this.root } /** * @internal */ newChild(name: string, type: number = UNKNOWN, opts: PathOpts = {}) { return new PathPosix( name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts ) } } /** * Options that may be provided to the PathScurry constructor */ export interface PathScurryOpts { /** * perform case-insensitive path matching. Default based on platform * subclass. */ nocase?: boolean /** * Number of Path entries to keep in the cache of Path child references. * * Setting this higher than 65536 will dramatically increase the data * consumption and construction time overhead of each PathScurry. * * Setting this value to 256 or lower will significantly reduce the data * consumption and construction time overhead, but may also reduce resolve() * and readdir() performance on large filesystems. * * Default `16384`. */ childrenCacheSize?: number /** * An object that overrides the built-in functions from the fs and * fs/promises modules. * * See {@link FSOption} */ fs?: FSOption } /** * The base class for all PathScurry classes, providing the interface for path * resolution and filesystem operations. * * Typically, you should *not* instantiate this class directly, but rather one * of the platform-specific classes, or the exported {@link PathScurry} which * defaults to the current platform. */ export abstract class PathScurryBase { /** * The root Path entry for the current working directory of this Scurry */ root: PathBase /** * The string path for the root of this Scurry's current working directory */ rootPath: string /** * A collection of all roots encountered, referenced by rootPath */ roots: { [k: string]: PathBase } /** * The Path entry corresponding to this PathScurry's current working directory. */ cwd: PathBase #resolveCache: ResolveCache #resolvePosixCache: ResolveCache #children: ChildrenCache /** * Perform path comparisons case-insensitively. * * Defaults true on Darwin and Windows systems, false elsewhere. */ nocase: boolean /** * The path separator used for parsing paths * * `'/'` on Posix systems, either `'/'` or `'\\'` on Windows */ abstract sep: string | RegExp #fs: FSValue /** * This class should not be instantiated directly. * * Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry * * @internal */ constructor( cwd: URL | string = process.cwd(), pathImpl: typeof win32 | typeof posix, sep: string | RegExp, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS, }: PathScurryOpts = {} ) { this.#fs = fsFromOption(fs) if (cwd instanceof URL || cwd.startsWith('file://')) { cwd = fileURLToPath(cwd) } // resolve and split root, and then add to the store. // this is the only time we call path.resolve() const cwdPath = pathImpl.resolve(cwd) this.roots = Object.create(null) this.rootPath = this.parseRootPath(cwdPath) this.#resolveCache = new ResolveCache() this.#resolvePosixCache = new ResolveCache() this.#children = new ChildrenCache(childrenCacheSize) const split = cwdPath.substring(this.rootPath.length).split(sep) // resolve('/') leaves '', splits to [''], we don't want that. if (split.length === 1 && !split[0]) { split.pop() } /* c8 ignore start */ if (nocase === undefined) { throw new TypeError( 'must provide nocase setting to PathScurryBase ctor' ) } /* c8 ignore stop */ this.nocase = nocase this.root = this.newRoot(this.#fs) this.roots[this.rootPath] = this.root let prev: PathBase = this.root let len = split.length - 1 const joinSep = pathImpl.sep let abs = this.rootPath let sawFirst = false for (const part of split) { const l = len-- prev = prev.child(part, { relative: new Array(l).fill('..').join(joinSep), relativePosix: new Array(l).fill('..').join('/'), fullpath: (abs += (sawFirst ? '' : joinSep) + part), }) sawFirst = true } this.cwd = prev } /** * Get the depth of a provided path, string, or the cwd */ depth(path: Path | string = this.cwd): number { if (typeof path === 'string') { path = this.cwd.resolve(path) } return path.depth() } /** * Parse the root portion of a path string * * @internal */ abstract parseRootPath(dir: string): string /** * create a new Path to use as root during construction. * * @internal */ abstract newRoot(fs: FSValue): PathBase /** * Determine whether a given path string is absolute */ abstract isAbsolute(p: string): boolean /** * Return the cache of child entries. Exposed so subclasses can create * child Path objects in a platform-specific way. * * @internal */ childrenCache() { return this.#children } /** * Resolve one or more path strings to a resolved string * * Same interface as require('path').resolve. * * Much faster than path.resolve() when called multiple times for the same * path, because the resolved Path objects are cached. Much slower * otherwise. */ resolve(...paths: string[]): string { // first figure out the minimum number of paths we have to test // we always start at cwd, but any absolutes will bump the start let r = '' for (let i = paths.length - 1; i >= 0; i--) { const p = paths[i] if (!p || p === '.') continue r = r ? `${p}/${r}` : p if (this.isAbsolute(p)) { break } } const cached = this.#resolveCache.get(r) if (cached !== undefined) { return cached } const result = this.cwd.resolve(r).fullpath() this.#resolveCache.set(r, result) return result } /** * Resolve one or more path strings to a resolved string, returning * the posix path. Identical to .resolve() on posix systems, but on * windows will return a forward-slash separated UNC path. * * Same interface as require('path').resolve. * * Much faster than path.resolve() when called multiple times for the same * path, because the resolved Path objects are cached. Much slower * otherwise. */ resolvePosix(...paths: string[]): string { // first figure out the minimum number of paths we have to test // we always start at cwd, but any absolutes will bump the start let r = '' for (let i = paths.length - 1; i >= 0; i--) { const p = paths[i] if (!p || p === '.') continue r = r ? `${p}/${r}` : p if (this.isAbsolute(p)) { break } } const cached = this.#resolvePosixCache.get(r) if (cached !== undefined) { return cached } const result = this.cwd.resolve(r).fullpathPosix() this.#resolvePosixCache.set(r, result) return result } /** * find the relative path from the cwd to the supplied path string or entry */ relative(entry: PathBase | string = this.cwd): string { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } return entry.relative() } /** * find the relative path from the cwd to the supplied path string or * entry, using / as the path delimiter, even on Windows. */ relativePosix(entry: PathBase | string = this.cwd): string { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } return entry.relativePosix() } /** * Return the basename for the provided string or Path object */ basename(entry: PathBase | string = this.cwd): string { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } return entry.name } /** * Return the dirname for the provided string or Path object */ dirname(entry: PathBase | string = this.cwd): string { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } return (entry.parent || entry).fullpath() } /** * Return an array of known child entries. * * First argument may be either a string, or a Path object. * * If the Path cannot or does not contain any children, then an empty array * is returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. * * Unlike `fs.readdir()`, the `withFileTypes` option defaults to `true`. Set * `{ withFileTypes: false }` to return strings. */ readdir(): Promise readdir(opts: { withFileTypes: true }): Promise readdir(opts: { withFileTypes: false }): Promise readdir(opts: { withFileTypes: boolean }): Promise readdir(entry: PathBase | string): Promise readdir( entry: PathBase | string, opts: { withFileTypes: true } ): Promise readdir( entry: PathBase | string, opts: { withFileTypes: false } ): Promise readdir( entry: PathBase | string, opts: { withFileTypes: boolean } ): Promise async readdir( entry: PathBase | string | { withFileTypes: boolean } = this.cwd, opts: { withFileTypes: boolean } = { withFileTypes: true, } ): Promise { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes } = opts if (!entry.canReaddir()) { return [] } else { const p = await entry.readdir() return withFileTypes ? p : p.map(e => e.name) } } /** * synchronous {@link PathScurryBase.readdir} */ readdirSync(): PathBase[] readdirSync(opts: { withFileTypes: true }): PathBase[] readdirSync(opts: { withFileTypes: false }): string[] readdirSync(opts: { withFileTypes: boolean }): PathBase[] | string[] readdirSync(entry: PathBase | string): PathBase[] readdirSync( entry: PathBase | string, opts: { withFileTypes: true } ): PathBase[] readdirSync( entry: PathBase | string, opts: { withFileTypes: false } ): string[] readdirSync( entry: PathBase | string, opts: { withFileTypes: boolean } ): PathBase[] | string[] readdirSync( entry: PathBase | string | { withFileTypes: boolean } = this.cwd, opts: { withFileTypes: boolean } = { withFileTypes: true, } ): PathBase[] | string[] { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes = true } = opts if (!entry.canReaddir()) { return [] } else if (withFileTypes) { return entry.readdirSync() } else { return entry.readdirSync().map(e => e.name) } } /** * Call lstat() on the string or Path object, and update all known * information that can be determined. * * Note that unlike `fs.lstat()`, the returned value does not contain some * information, such as `mode`, `dev`, `nlink`, and `ino`. If that * information is required, you will need to call `fs.lstat` yourself. * * If the Path refers to a nonexistent file, or if the lstat call fails for * any reason, `undefined` is returned. Otherwise the updated Path object is * returned. * * Results are cached, and thus may be out of date if the filesystem is * mutated. */ async lstat( entry: string | PathBase = this.cwd ): Promise { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } return entry.lstat() } /** * synchronous {@link PathScurryBase.lstat} */ lstatSync(entry: string | PathBase = this.cwd): PathBase | undefined { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } return entry.lstatSync() } /** * Return the Path object or string path corresponding to the target of a * symbolic link. * * If the path is not a symbolic link, or if the readlink call fails for any * reason, `undefined` is returned. * * Result is cached, and thus may be outdated if the filesystem is mutated. * * `{withFileTypes}` option defaults to `false`. * * On success, returns a Path object if `withFileTypes` option is true, * otherwise a string. */ readlink(): Promise readlink(opt: { withFileTypes: false }): Promise readlink(opt: { withFileTypes: true }): Promise readlink(opt: { withFileTypes: boolean }): Promise readlink( entry: string | PathBase, opt?: { withFileTypes: false } ): Promise readlink( entry: string | PathBase, opt: { withFileTypes: true } ): Promise readlink( entry: string | PathBase, opt: { withFileTypes: boolean } ): Promise async readlink( entry: string | PathBase | { withFileTypes: boolean } = this.cwd, { withFileTypes }: { withFileTypes: boolean } = { withFileTypes: false, } ): Promise { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes entry = this.cwd } const e = await entry.readlink() return withFileTypes ? e : e?.fullpath() } /** * synchronous {@link PathScurryBase.readlink} */ readlinkSync(): string | undefined readlinkSync(opt: { withFileTypes: false }): string | undefined readlinkSync(opt: { withFileTypes: true }): PathBase | undefined readlinkSync(opt: { withFileTypes: boolean }): PathBase | string | undefined readlinkSync( entry: string | PathBase, opt?: { withFileTypes: false } ): string | undefined readlinkSync( entry: string | PathBase, opt: { withFileTypes: true } ): PathBase | undefined readlinkSync( entry: string | PathBase, opt: { withFileTypes: boolean } ): string | PathBase | undefined readlinkSync( entry: string | PathBase | { withFileTypes: boolean } = this.cwd, { withFileTypes }: { withFileTypes: boolean } = { withFileTypes: false, } ): string | PathBase | undefined { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes entry = this.cwd } const e = entry.readlinkSync() return withFileTypes ? e : e?.fullpath() } /** * Return the Path object or string path corresponding to path as resolved * by realpath(3). * * If the realpath call fails for any reason, `undefined` is returned. * * Result is cached, and thus may be outdated if the filesystem is mutated. * * `{withFileTypes}` option defaults to `false`. * * On success, returns a Path object if `withFileTypes` option is true, * otherwise a string. */ realpath(): Promise realpath(opt: { withFileTypes: false }): Promise realpath(opt: { withFileTypes: true }): Promise realpath(opt: { withFileTypes: boolean }): Promise realpath( entry: string | PathBase, opt?: { withFileTypes: false } ): Promise realpath( entry: string | PathBase, opt: { withFileTypes: true } ): Promise realpath( entry: string | PathBase, opt: { withFileTypes: boolean } ): Promise async realpath( entry: string | PathBase | { withFileTypes: boolean } = this.cwd, { withFileTypes }: { withFileTypes: boolean } = { withFileTypes: false, } ): Promise { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes entry = this.cwd } const e = await entry.realpath() return withFileTypes ? e : e?.fullpath() } realpathSync(): string | undefined realpathSync(opt: { withFileTypes: false }): string | undefined realpathSync(opt: { withFileTypes: true }): PathBase | undefined realpathSync(opt: { withFileTypes: boolean }): PathBase | string | undefined realpathSync( entry: string | PathBase, opt?: { withFileTypes: false } ): string | undefined realpathSync( entry: string | PathBase, opt: { withFileTypes: true } ): PathBase | undefined realpathSync( entry: string | PathBase, opt: { withFileTypes: boolean } ): string | PathBase | undefined realpathSync( entry: string | PathBase | { withFileTypes: boolean } = this.cwd, { withFileTypes }: { withFileTypes: boolean } = { withFileTypes: false, } ): string | PathBase | undefined { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { withFileTypes = entry.withFileTypes entry = this.cwd } const e = entry.realpathSync() return withFileTypes ? e : e?.fullpath() } /** * Asynchronously walk the directory tree, returning an array of * all path strings or Path objects found. * * Note that this will be extremely memory-hungry on large filesystems. * In such cases, it may be better to use the stream or async iterator * walk implementation. */ walk(): Promise walk( opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): Promise walk(opts: WalkOptionsWithFileTypesFalse): Promise walk(opts: WalkOptions): Promise walk(entry: string | PathBase): Promise walk( entry: string | PathBase, opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): Promise walk( entry: string | PathBase, opts: WalkOptionsWithFileTypesFalse ): Promise walk( entry: string | PathBase, opts: WalkOptions ): Promise async walk( entry: string | PathBase | WalkOptions = this.cwd, opts: WalkOptions = {} ): Promise { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes = true, follow = false, filter, walkFilter, } = opts const results: (string | PathBase)[] = [] if (!filter || filter(entry)) { results.push(withFileTypes ? entry : entry.fullpath()) } const dirs = new Set() const walk = ( dir: PathBase, cb: (er?: NodeJS.ErrnoException) => void ) => { dirs.add(dir) dir.readdirCB((er, entries) => { /* c8 ignore start */ if (er) { return cb(er) } /* c8 ignore stop */ let len = entries.length if (!len) return cb() const next = () => { if (--len === 0) { cb() } } for (const e of entries) { if (!filter || filter(e)) { results.push(withFileTypes ? e : e.fullpath()) } if (follow && e.isSymbolicLink()) { e.realpath() .then(r => (r?.isUnknown() ? r.lstat() : r)) .then(r => r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next() ) } else { if (e.shouldWalk(dirs, walkFilter)) { walk(e, next) } else { next() } } } }, true) // zalgooooooo } const start = entry return new Promise((res, rej) => { walk(start, er => { /* c8 ignore start */ if (er) return rej(er) /* c8 ignore stop */ res(results as PathBase[] | string[]) }) }) } /** * Synchronously walk the directory tree, returning an array of * all path strings or Path objects found. * * Note that this will be extremely memory-hungry on large filesystems. * In such cases, it may be better to use the stream or async iterator * walk implementation. */ walkSync(): PathBase[] walkSync( opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): PathBase[] walkSync(opts: WalkOptionsWithFileTypesFalse): string[] walkSync(opts: WalkOptions): string[] | PathBase[] walkSync(entry: string | PathBase): PathBase[] walkSync( entry: string | PathBase, opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue ): PathBase[] walkSync( entry: string | PathBase, opts: WalkOptionsWithFileTypesFalse ): string[] walkSync( entry: string | PathBase, opts: WalkOptions ): PathBase[] | string[] walkSync( entry: string | PathBase | WalkOptions = this.cwd, opts: WalkOptions = {} ): PathBase[] | string[] { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes = true, follow = false, filter, walkFilter, } = opts const results: (string | PathBase)[] = [] if (!filter || filter(entry)) { results.push(withFileTypes ? entry : entry.fullpath()) } const dirs = new Set([entry]) for (const dir of dirs) { const entries = dir.readdirSync() for (const e of entries) { if (!filter || filter(e)) { results.push(withFileTypes ? e : e.fullpath()) } let r: PathBase | undefined = e if (e.isSymbolicLink()) { if (!(follow && (r = e.realpathSync()))) continue if (r.isUnknown()) r.lstatSync() } if (r.shouldWalk(dirs, walkFilter)) { dirs.add(r) } } } return results as string[] | PathBase[] } /** * Support for `for await` * * Alias for {@link PathScurryBase.iterate} * * Note: As of Node 19, this is very slow, compared to other methods of * walking. Consider using {@link PathScurryBase.stream} if memory overhead * and backpressure are concerns, or {@link PathScurryBase.walk} if not. */ [Symbol.asyncIterator]() { return this.iterate() } /** * Async generator form of {@link PathScurryBase.walk} * * Note: As of Node 19, this is very slow, compared to other methods of * walking, especially if most/all of the directory tree has been previously * walked. Consider using {@link PathScurryBase.stream} if memory overhead * and backpressure are concerns, or {@link PathScurryBase.walk} if not. */ iterate(): AsyncGenerator iterate( opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): AsyncGenerator iterate( opts: WalkOptionsWithFileTypesFalse ): AsyncGenerator iterate(opts: WalkOptions): AsyncGenerator iterate(entry: string | PathBase): AsyncGenerator iterate( entry: string | PathBase, opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): AsyncGenerator iterate( entry: string | PathBase, opts: WalkOptionsWithFileTypesFalse ): AsyncGenerator iterate( entry: string | PathBase, opts: WalkOptions ): AsyncGenerator iterate( entry: string | PathBase | WalkOptions = this.cwd, options: WalkOptions = {} ): AsyncGenerator { // iterating async over the stream is significantly more performant, // especially in the warm-cache scenario, because it buffers up directory // entries in the background instead of waiting for a yield for each one. if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { options = entry entry = this.cwd } return this.stream(entry, options)[Symbol.asyncIterator]() } /** * Iterating over a PathScurry performs a synchronous walk. * * Alias for {@link PathScurryBase.iterateSync} */ [Symbol.iterator]() { return this.iterateSync() } iterateSync(): Generator iterateSync( opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): Generator iterateSync( opts: WalkOptionsWithFileTypesFalse ): Generator iterateSync(opts: WalkOptions): Generator iterateSync(entry: string | PathBase): Generator iterateSync( entry: string | PathBase, opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): Generator iterateSync( entry: string | PathBase, opts: WalkOptionsWithFileTypesFalse ): Generator iterateSync( entry: string | PathBase, opts: WalkOptions ): Generator *iterateSync( entry: string | PathBase | WalkOptions = this.cwd, opts: WalkOptions = {} ): Generator { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes = true, follow = false, filter, walkFilter, } = opts if (!filter || filter(entry)) { yield withFileTypes ? entry : entry.fullpath() } const dirs = new Set([entry]) for (const dir of dirs) { const entries = dir.readdirSync() for (const e of entries) { if (!filter || filter(e)) { yield withFileTypes ? e : e.fullpath() } let r: PathBase | undefined = e if (e.isSymbolicLink()) { if (!(follow && (r = e.realpathSync()))) continue if (r.isUnknown()) r.lstatSync() } if (r.shouldWalk(dirs, walkFilter)) { dirs.add(r) } } } } /** * Stream form of {@link PathScurryBase.walk} * * Returns a Minipass stream that emits {@link PathBase} objects by default, * or strings if `{ withFileTypes: false }` is set in the options. */ stream(): Minipass stream( opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): Minipass stream(opts: WalkOptionsWithFileTypesFalse): Minipass stream(opts: WalkOptions): Minipass stream(entry: string | PathBase): Minipass stream( entry: string | PathBase, opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue ): Minipass stream( entry: string | PathBase, opts: WalkOptionsWithFileTypesFalse ): Minipass stream( entry: string | PathBase, opts: WalkOptions ): Minipass | Minipass stream( entry: string | PathBase | WalkOptions = this.cwd, opts: WalkOptions = {} ): Minipass | Minipass { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes = true, follow = false, filter, walkFilter, } = opts const results = new Minipass({ objectMode: true }) if (!filter || filter(entry)) { results.write(withFileTypes ? entry : entry.fullpath()) } const dirs = new Set() const queue: PathBase[] = [entry] let processing = 0 const process = () => { let paused = false while (!paused) { const dir = queue.shift() if (!dir) { if (processing === 0) results.end() return } processing++ dirs.add(dir) const onReaddir = ( er: null | NodeJS.ErrnoException, entries: PathBase[], didRealpaths: boolean = false ) => { /* c8 ignore start */ if (er) return results.emit('error', er) /* c8 ignore stop */ if (follow && !didRealpaths) { const promises: Promise[] = [] for (const e of entries) { if (e.isSymbolicLink()) { promises.push( e .realpath() .then((r: PathBase | undefined) => r?.isUnknown() ? r.lstat() : r ) ) } } if (promises.length) { Promise.all(promises).then(() => onReaddir(null, entries, true) ) return } } for (const e of entries) { if (e && (!filter || filter(e))) { if (!results.write(withFileTypes ? e : e.fullpath())) { paused = true } } } processing-- for (const e of entries) { const r = e.realpathCached() || e if (r.shouldWalk(dirs, walkFilter)) { queue.push(r) } } if (paused && !results.flowing) { results.once('drain', process) } else if (!sync) { process() } } // zalgo containment let sync = true dir.readdirCB(onReaddir, true) sync = false } } process() return results as Minipass | Minipass } /** * Synchronous form of {@link PathScurryBase.stream} * * Returns a Minipass stream that emits {@link PathBase} objects by default, * or strings if `{ withFileTypes: false }` is set in the options. * * Will complete the walk in a single tick if the stream is consumed fully. * Otherwise, will pause as needed for stream backpressure. */ streamSync(): Minipass streamSync( opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset ): Minipass streamSync(opts: WalkOptionsWithFileTypesFalse): Minipass streamSync(opts: WalkOptions): Minipass streamSync(entry: string | PathBase): Minipass streamSync( entry: string | PathBase, opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue ): Minipass streamSync( entry: string | PathBase, opts: WalkOptionsWithFileTypesFalse ): Minipass streamSync( entry: string | PathBase, opts: WalkOptions ): Minipass | Minipass streamSync( entry: string | PathBase | WalkOptions = this.cwd, opts: WalkOptions = {} ): Minipass | Minipass { if (typeof entry === 'string') { entry = this.cwd.resolve(entry) } else if (!(entry instanceof PathBase)) { opts = entry entry = this.cwd } const { withFileTypes = true, follow = false, filter, walkFilter, } = opts const results = new Minipass({ objectMode: true }) const dirs = new Set() if (!filter || filter(entry)) { results.write(withFileTypes ? entry : entry.fullpath()) } const queue: PathBase[] = [entry] let processing = 0 const process = () => { let paused = false while (!paused) { const dir = queue.shift() if (!dir) { if (processing === 0) results.end() return } processing++ dirs.add(dir) const entries = dir.readdirSync() for (const e of entries) { if (!filter || filter(e)) { if (!results.write(withFileTypes ? e : e.fullpath())) { paused = true } } } processing-- for (const e of entries) { let r: PathBase | undefined = e if (e.isSymbolicLink()) { if (!(follow && (r = e.realpathSync()))) continue if (r.isUnknown()) r.lstatSync() } if (r.shouldWalk(dirs, walkFilter)) { queue.push(r) } } } if (paused && !results.flowing) results.once('drain', process) } process() return results as Minipass | Minipass } chdir(path: string | Path = this.cwd) { const oldCwd = this.cwd this.cwd = typeof path === 'string' ? this.cwd.resolve(path) : path this.cwd[setAsCwd](oldCwd) } } /** * Options provided to all walk methods. */ export interface WalkOptions { /** * Return results as {@link PathBase} objects rather than strings. * When set to false, results are fully resolved paths, as returned by * {@link PathBase.fullpath}. * @default true */ withFileTypes?: boolean /** * Attempt to read directory entries from symbolic links. Otherwise, only * actual directories are traversed. Regardless of this setting, a given * target path will only ever be walked once, meaning that a symbolic link * to a previously traversed directory will never be followed. * * Setting this imposes a slight performance penalty, because `readlink` * must be called on all symbolic links encountered, in order to avoid * infinite cycles. * @default false */ follow?: boolean /** * Only return entries where the provided function returns true. * * This will not prevent directories from being traversed, even if they do * not pass the filter, though it will prevent directories themselves from * being included in the result set. See {@link walkFilter} * * Asynchronous functions are not supported here. * * By default, if no filter is provided, all entries and traversed * directories are included. */ filter?: (entry: PathBase) => boolean /** * Only traverse directories (and in the case of {@link follow} being set to * true, symbolic links to directories) if the provided function returns * true. * * This will not prevent directories from being included in the result set, * even if they do not pass the supplied filter function. See {@link filter} * to do that. * * Asynchronous functions are not supported here. */ walkFilter?: (entry: PathBase) => boolean } export type WalkOptionsWithFileTypesUnset = WalkOptions & { withFileTypes?: undefined } export type WalkOptionsWithFileTypesTrue = WalkOptions & { withFileTypes: true } export type WalkOptionsWithFileTypesFalse = WalkOptions & { withFileTypes: false } /** * Windows implementation of {@link PathScurryBase} * * Defaults to case insensitve, uses `'\\'` to generate path strings. Uses * {@link PathWin32} for Path objects. */ export class PathScurryWin32 extends PathScurryBase { /** * separator for generating path strings */ sep: '\\' = '\\' constructor( cwd: URL | string = process.cwd(), opts: PathScurryOpts = {} ) { const { nocase = true } = opts super(cwd, win32, '\\', { ...opts, nocase }) this.nocase = nocase for (let p: PathBase | undefined = this.cwd; p; p = p.parent) { p.nocase = this.nocase } } /** * @internal */ parseRootPath(dir: string): string { // if the path starts with a single separator, it's not a UNC, and we'll // just get separator as the root, and driveFromUNC will return \ // In that case, mount \ on the root from the cwd. return win32.parse(dir).root.toUpperCase() } /** * @internal */ newRoot(fs: FSValue) { return new PathWin32( this.rootPath, IFDIR, undefined, this.roots, this.nocase, this.childrenCache(), { fs } ) } /** * Return true if the provided path string is an absolute path */ isAbsolute(p: string): boolean { return ( p.startsWith('/') || p.startsWith('\\') || /^[a-z]:(\/|\\)/i.test(p) ) } } /** * {@link PathScurryBase} implementation for all posix systems other than Darwin. * * Defaults to case-sensitive matching, uses `'/'` to generate path strings. * * Uses {@link PathPosix} for Path objects. */ export class PathScurryPosix extends PathScurryBase { /** * separator for generating path strings */ sep: '/' = '/' constructor( cwd: URL | string = process.cwd(), opts: PathScurryOpts = {} ) { const { nocase = false } = opts super(cwd, posix, '/', { ...opts, nocase }) this.nocase = nocase } /** * @internal */ parseRootPath(_dir: string): string { return '/' } /** * @internal */ newRoot(fs: FSValue) { return new PathPosix( this.rootPath, IFDIR, undefined, this.roots, this.nocase, this.childrenCache(), { fs } ) } /** * Return true if the provided path string is an absolute path */ isAbsolute(p: string): boolean { return p.startsWith('/') } } /** * {@link PathScurryBase} implementation for Darwin (macOS) systems. * * Defaults to case-insensitive matching, uses `'/'` for generating path * strings. * * Uses {@link PathPosix} for Path objects. */ export class PathScurryDarwin extends PathScurryPosix { constructor( cwd: URL | string = process.cwd(), opts: PathScurryOpts = {} ) { const { nocase = true } = opts super(cwd, { ...opts, nocase }) } } /** * Default {@link PathBase} implementation for the current platform. * * {@link PathWin32} on Windows systems, {@link PathPosix} on all others. */ export const Path = process.platform === 'win32' ? PathWin32 : PathPosix export type Path = PathBase | InstanceType /** * Default {@link PathScurryBase} implementation for the current platform. * * {@link PathScurryWin32} on Windows systems, {@link PathScurryDarwin} on * Darwin (macOS) systems, {@link PathScurryPosix} on all others. */ export const PathScurry: | typeof PathScurryWin32 | typeof PathScurryDarwin | typeof PathScurryPosix = process.platform === 'win32' ? PathScurryWin32 : process.platform === 'darwin' ? PathScurryDarwin : PathScurryPosix export type PathScurry = PathScurryBase | InstanceType isaacs-path-scurry-06957ec/tap-snapshots/000077500000000000000000000000001443124316700204115ustar00rootroot00000000000000isaacs-path-scurry-06957ec/tap-snapshots/test/000077500000000000000000000000001443124316700213705ustar00rootroot00000000000000isaacs-path-scurry-06957ec/tap-snapshots/test/index.ts.test.cjs000066400000000000000000001111641443124316700246070ustar00rootroot00000000000000/* IMPORTANT * This snapshot file is auto-generated, but designed for humans. * It should be checked into source control and tracked carefully. * Re-generate by setting TAP_SNAPSHOT=1 and running tests. * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' exports[`test/index.ts TAP eloop async > must match snapshot 1`] = ` Object { "a/bb/c/dd/e/ff/g": "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g", "aa/b/cc/d/ee/f/gg": "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g", "bigloop": undefined, "dest": "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/dest", "enoent": undefined, "pivot": undefined, "roundtrip": "{CWD}/test/tap-testdir-index-eloop/home", } ` exports[`test/index.ts TAP eloop sync > must match snapshot 1`] = ` Object { "a/bb/c/dd/e/ff/g": "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g", "aa/b/cc/d/ee/f/gg": "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g", "bigloop": undefined, "dest": "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/dest", "enoent": undefined, "pivot": undefined, "roundtrip": "{CWD}/test/tap-testdir-index-eloop/home", } ` exports[`test/index.ts TAP eloop walk this beast > must match snapshot 1`] = ` Array [ "{CWD}/test/tap-testdir-index-eloop", "{CWD}/test/tap-testdir-index-eloop/a", "{CWD}/test/tap-testdir-index-eloop/a/b", "{CWD}/test/tap-testdir-index-eloop/a/b/c", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/down", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/down", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/down", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/bounce", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/dest", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/down", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/round", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/g/up", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/gg", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/round", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/travel", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/f/up", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/ff", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/round", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/travel", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/e/up", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/ee", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/round", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/travel", "{CWD}/test/tap-testdir-index-eloop/a/b/c/d/up", "{CWD}/test/tap-testdir-index-eloop/a/b/c/dd", "{CWD}/test/tap-testdir-index-eloop/a/b/c/down", "{CWD}/test/tap-testdir-index-eloop/a/b/c/round", "{CWD}/test/tap-testdir-index-eloop/a/b/c/travel", "{CWD}/test/tap-testdir-index-eloop/a/b/c/up", "{CWD}/test/tap-testdir-index-eloop/a/b/cc", "{CWD}/test/tap-testdir-index-eloop/a/b/down", "{CWD}/test/tap-testdir-index-eloop/a/b/round", "{CWD}/test/tap-testdir-index-eloop/a/b/travel", "{CWD}/test/tap-testdir-index-eloop/a/b/up", "{CWD}/test/tap-testdir-index-eloop/a/bb", "{CWD}/test/tap-testdir-index-eloop/a/down", "{CWD}/test/tap-testdir-index-eloop/a/peak", "{CWD}/test/tap-testdir-index-eloop/a/round", "{CWD}/test/tap-testdir-index-eloop/a/travel", "{CWD}/test/tap-testdir-index-eloop/a/up", "{CWD}/test/tap-testdir-index-eloop/aa", "{CWD}/test/tap-testdir-index-eloop/bigloop", "{CWD}/test/tap-testdir-index-eloop/dest", "{CWD}/test/tap-testdir-index-eloop/enoent", "{CWD}/test/tap-testdir-index-eloop/home", "{CWD}/test/tap-testdir-index-eloop/pivot", "{CWD}/test/tap-testdir-index-eloop/roundtrip", ] ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=false initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=false initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=false initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=false initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=true initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=true initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=true initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=false, filter=false, walkFilter=true initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=false initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=false initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=false initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=false initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=true initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=true initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=true initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=false, filter=true, walkFilter=true initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=false initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=false initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=false initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=false initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=true initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=true initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=true initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=false, walkFilter=true initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=false initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=false initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=false initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=false initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=true initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=true initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=true initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=true, filter=true, walkFilter=true initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/x/outside", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=false initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=false initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=false initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=false initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=true initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=true initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=true initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=undefined, filter=false, walkFilter=true initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/d", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/c/d", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=false initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=false initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=false initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=false initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", "{CWD}/test/tap-testdir-index-walking/a/b/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/d/cycle", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/g", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/f", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/e", "{CWD}/test/tap-testdir-index-walking/a/b/c/d/cycle", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=true initial walk, sync > must match snapshot 1`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=true initial walk, sync > must match snapshot 2`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=true initial walk, sync > must match snapshot 3`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` exports[`test/index.ts TAP walking follow=undefined, filter=true, walkFilter=true initial walk, sync > must match snapshot 4`] = ` Set { "{CWD}/test/tap-testdir-index-walking/a", "{CWD}/test/tap-testdir-index-walking/a/x", "{CWD}/test/tap-testdir-index-walking/a/empty", "{CWD}/test/tap-testdir-index-walking/a/deeplink", "{CWD}/test/tap-testdir-index-walking/a/b", "{CWD}/test/tap-testdir-index-walking/a/b/c", } ` isaacs-path-scurry-06957ec/test/000077500000000000000000000000001443124316700165645ustar00rootroot00000000000000isaacs-path-scurry-06957ec/test/fixtures/000077500000000000000000000000001443124316700204355ustar00rootroot00000000000000isaacs-path-scurry-06957ec/test/fixtures/normalize-paths.ts000066400000000000000000000021031443124316700241160ustar00rootroot00000000000000export const normalizePath = ( path: string, replace: { [k: string]: string } = {} ) => { for (const [search, repl] of Object.entries(replace)) { path = path.split(search).join(repl) } return path.replace(/[A-Z]:/, '').replace(/\\/g, '/') } export const normalizePaths = ( obj: any, replace: { [k: string]: string } = {} ): typeof obj => { if ( !obj || typeof obj === 'number' || typeof obj === 'symbol' || typeof obj === 'boolean' || obj instanceof RegExp || typeof obj === 'function' ) { return obj } if (typeof obj === 'string') { return normalizePath(obj, replace) } if (obj instanceof Set) { return new Set(normalizePaths([...obj], replace)) } if (Array.isArray(obj)) { return obj.map(v => normalizePaths(v, replace)) } if (obj instanceof Map) { return new Map( [...obj].map(([name, val]) => [name, normalizePaths(val, replace)]) ) } return Object.fromEntries( Object.entries(obj).map(([k, v]) => [ normalizePaths(k, replace), normalizePaths(v, replace), ]) ) } isaacs-path-scurry-06957ec/test/index.ts000066400000000000000000001430501443124316700202460ustar00rootroot00000000000000import * as fs from 'fs' import { lstatSync, readdirSync, writeFileSync } from 'fs' import * as fsp from 'fs/promises' import { lstat } from 'fs/promises' import { basename, resolve, relative } from 'path' import { rimrafSync } from 'rimraf' import t from 'tap' import { pathToFileURL } from 'url' import { normalizePaths } from './fixtures/normalize-paths' import { FSOption, Path, PathBase, PathPosix, PathScurry, PathScurryDarwin, PathScurryPosix, PathScurryWin32, PathWin32, WalkOptions, } from '../' t.formatSnapshot = (o: any) => normalizePaths(o, { [process.cwd()]: '{CWD}' }) t.test('platform-specific', t => { const { platform, cwd } = process const patchCwd = { win32: () => { return 'c:\\some\\path' }, posix: () => { return '/some/path' }, } const setPlatform = (value: string = platform) => { Object.defineProperty(process, 'platform', { value, configurable: true, enumerable: true, }) } const setCWD = (value?: string) => { if (value === undefined) { Object.defineProperty(process, 'cwd', { value: cwd, configurable: true, enumerable: true, }) } else { Object.defineProperty(process, 'cwd', { value: value === 'win32' ? patchCwd.win32 : patchCwd.posix, configurable: true, enumerable: true, }) } } t.test('default (no override)', t => { if (platform === 'win32') { t.equal(PathScurry, PathScurryWin32, 'expect windows Scurry') t.equal(Path, PathWin32, 'expect windows path') } else if (platform === 'darwin') { t.equal(PathScurry, PathScurryDarwin, 'expect darwin Scurry') t.equal(Path, PathPosix, 'expect posix path') } else { t.equal(PathScurry, PathScurryPosix, 'expect posix') t.equal(Path, PathPosix, 'expect posix path') } t.end() }) t.test('force windows', t => { t.teardown(() => setPlatform()) setPlatform('win32') const { PathScurry, PathScurryWin32, Path, PathWin32 } = t.mock( '../', {} ) t.teardown(() => setCWD()) setCWD('win32') t.equal(PathScurry, PathScurryWin32, 'expect windows Scurry') t.equal(Path, PathWin32, 'expect windows path') const pw = new PathScurry() t.equal(pw.nocase, true, 'nocase on PathScurry') t.equal(pw.cwd.nocase, true, 'nocase on Path') t.equal(pw.resolve(), 'C:\\some\\path') t.equal(pw.resolvePosix(), '//?/C:/some/path') t.equal(pw.relative('c:/some/path/a/b'), 'a\\b') t.equal(pw.relative('c:/some/a/b'), '..\\a\\b') t.equal(pw.relative('/a/b'), 'C:\\a\\b') t.equal(pw.relativePosix('c:/some/path/a/b'), 'a/b') t.equal(pw.relativePosix('c:/some/a/b'), '../a/b') t.equal(pw.relativePosix('/a/b'), '//?/C:/a/b') t.equal(pw.cwd.fullpath(), 'C:\\some\\path') t.equal(pw.cwd.path, pw.cwd.parent.fullpath()) t.equal(pw.cwd.root.path, pw.cwd.root.fullpath()) t.equal(pw.cwd.fullpathPosix(), '//?/C:/some/path') t.equal(pw.cwd.getRoot('\\\\?\\c:\\'), pw.root) t.equal(pw.cwd.getRoot('C:\\'), pw.root) t.equal(pw.resolve('/'), 'C:\\') t.equal(pw.resolvePosix('/'), '//?/C:/') t.equal(pw.resolve('foo'), 'C:\\some\\path\\foo') t.equal(pw.resolvePosix('foo'), '//?/C:/some/path/foo') t.equal( pw.resolve('foo', '//x/y/some/absolute/path'), '\\\\X\\Y\\some\\absolute\\path' ) t.equal( pw.resolvePosix('foo', '//x/y/some/absolute/path'), '//X/Y/some/absolute/path' ) t.equal(pw.dirname(pw.root), 'C:\\') t.equal( pw.resolve('foo', '//?/y:/some/absolute/path'), 'Y:\\some\\absolute\\path' ) t.equal( pw.resolvePosix('foo', '//?/y:/some/absolute/path'), '//?/Y:/some/absolute/path' ) t.equal( pw.resolve('d:\\x/y\\z\\a/../', '', '.', './/b'), 'D:\\x\\y\\z\\b' ) t.equal( pw.resolvePosix('d:\\x/y\\z\\a/../', '', '.', './/b'), '//?/D:/x/y/z/b' ) t.equal(pw.cwd.resolve('//?/C:/some/PATH'), pw.cwd) t.equal(pw.resolve('//?/D:/X/y\\z\\a/../B'), 'D:\\x\\y\\z\\b') t.equal(pw.resolvePosix('//?/D:/X/y\\z\\a/../B'), '//?/D:/x/y/z/b') t.equal(pw.resolve('//prp1/'), 'C:\\prp1') t.equal(pw.resolvePosix('//prp1/'), '//?/C:/prp1') t.equal(pw.cwd.resolve('../../../../../../../'), pw.root) t.equal(new PathScurry('/prp2').cwd.fullpath(), 'C:\\prp2') t.equal(new PathScurry('\\prp3').resolve(), 'C:\\prp3') t.equal(new PathScurry('\\prp3').resolvePosix(), '//?/C:/prp3') t.end() }) t.test('force darwin', t => { t.teardown(() => setPlatform()) setPlatform('darwin') const { PathScurry, PathScurryDarwin, Path, PathPosix } = t.mock( '../', {} ) t.teardown(() => setCWD()) setCWD('posix') t.equal(PathScurry, PathScurryDarwin, 'expect darwin Scurry') t.equal(Path, PathPosix, 'expect posix path') const pw = new PathScurry() t.equal(pw.nocase, true, 'nocase on PathScurry') t.equal(pw.cwd.nocase, true, 'nocase on Path') t.equal(pw.cwd.fullpath(), '/some/path') t.equal(pw.cwd.fullpathPosix(), '/some/path') t.equal(pw.relative('/some/path/a/b'), 'a/b') t.equal(pw.relative('/some/a/b'), '../a/b') t.equal(pw.relative('/a/b'), '/a/b') t.equal(pw.relativePosix('/some/path/a/b'), 'a/b') t.equal(pw.relativePosix('/some/a/b'), '../a/b') t.equal(pw.relativePosix('/a/b'), '/a/b') t.equal(pw.dirname(pw.root), '/') t.equal(pw.resolve('foo'), '/some/path/foo') t.equal(pw.resolvePosix('foo'), '/some/path/foo') t.equal(pw.cwd.resolve('../../../../../../../'), pw.root) t.equal( pw.resolve('foo', '//x/y/some/absolute/path'), '/x/y/some/absolute/path' ) t.equal( pw.resolvePosix('foo', '//x/y/some/absolute/path'), '/x/y/some/absolute/path' ) t.equal(pw.cwd.resolve('foo'), pw.cwd.resolve('x/../FOO')) t.end() }) t.test('force posix', t => { t.teardown(() => setPlatform()) setPlatform('posix') const { PathScurry, PathScurryPosix, Path, PathPosix } = t.mock( '../', {} ) t.teardown(() => setCWD()) setCWD('posix') t.equal(PathScurry, PathScurryPosix, 'expect posix Scurry') t.equal(Path, PathPosix, 'expect posix path') const pw = new PathScurry() t.equal(pw.cwd.fullpath(), '/some/path') t.equal(pw.resolve('foo'), '/some/path/foo') t.equal(pw.resolvePosix('foo'), '/some/path/foo') t.equal(pw.nocase, false, 'nocase on PathScurry') t.equal(pw.cwd.nocase, false, 'nocase on Path') t.equal(pw.cwd.fullpath(), '/some/path') t.equal(pw.resolve('foo'), '/some/path/foo') t.equal(pw.resolvePosix('foo'), '/some/path/foo') t.equal(pw.cwd.resolve('../../../../../../../'), pw.root) t.equal(pw.cwd.resolve('foo'), pw.cwd.resolve('x/../foo')) t.not(pw.cwd.resolve('foo'), pw.cwd.resolve('x/../FOO')) t.end() }) t.end() }) t.test('readlink', async t => { const dir = t.testdir({ hello: 'world', link: t.fixture('symlink', './hello'), dirlink: t.fixture('symlink', 'dir'), dir: { link: t.fixture('symlink', '../hello'), }, another: { file: 'f', }, }) const pw = new PathScurry(dir) const wft = { withFileTypes: true } t.equal(await pw.readlink('link', wft), pw.cwd.resolve('hello')) t.equal(pw.readlinkSync('link', wft), pw.cwd.resolve('hello')) t.equal(pw.readlinkSync('dir/link'), resolve(dir, 'hello')) t.equal(await pw.readlink('dir/link'), resolve(dir, 'hello')) t.equal(pw.readlinkSync('dirlink/link'), resolve(dir, 'hello')) t.equal(await pw.readlink('dirlink/link'), resolve(dir, 'hello')) // root is never a symlink t.equal(await pw.readlink('/'), undefined) t.equal(pw.readlinkSync('/'), undefined) // calling without a path reads cwd const onLink = new PathScurry(dir + '/dir/link') const withFileTypes = true t.equal(await onLink.readlink(), resolve(dir, 'hello')) t.equal( onLink.readlinkSync({ withFileTypes })?.fullpath(), resolve(dir, 'hello') ) t.equal( (await onLink.readlink({ withFileTypes }))?.fullpath(), resolve(dir, 'hello') ) t.equal(await pw.cwd.resolve('link').readlink(), pw.cwd.resolve('hello')) t.equal( await pw.cwd.resolve('dir/link').readlink(), pw.cwd.resolve('hello') ) t.equal(pw.cwd.resolve('link').readlinkSync(), pw.cwd.resolve('hello')) t.equal( pw.cwd.resolve('dir/link').readlinkSync(), pw.cwd.resolve('hello') ) t.equal(await pw.readlink('hello'), undefined) t.equal(pw.readlinkSync('dir'), undefined) t.equal(await pw.readlink('e/no/ent'), undefined) t.equal(pw.readlinkSync('no/ent/e'), undefined) t.equal(await pw.readlink('hello/e/not/dir'), undefined) t.equal(pw.readlinkSync('hello/also/not/dir'), undefined) // a thing we know is not a symlink pw.lstatSync('another/file') t.equal(pw.readlinkSync('another/file'), undefined) // a nested thing, and then we have to mark its parent as enoent t.equal(pw.lstatSync('nope/a/b/c/d/e/f'), undefined) t.equal(pw.cwd.resolve('nope/a/b/c/d/e/f').isENOENT(), true) t.equal(pw.cwd.resolve('nope').isUnknown(), true) t.equal(pw.lstatSync('nope'), undefined) t.end() }) t.test('lstat', async t => { const td = t.testdir({ exists: 'yep', notadir: 'ok', alsonotdir: 'also ok', dir: {}, link: t.fixture('symlink', 'exists'), }) const pw = new PathScurry(td) t.equal(pw.dirname('exists'), resolve(td)) t.equal(pw.basename(resolve(td) + '/exists'), 'exists') t.equal(pw.cwd.resolve('exists').isUnknown(), true) t.equal(await pw.lstat('exists'), pw.cwd.resolve('exists')) t.equal(pw.lstatSync('exists'), pw.cwd.resolve('exists')) t.equal(pw.lstatSync('notadir/notdir'), undefined) t.equal(await pw.lstat('alsonotdir/alsonotdir'), undefined) t.equal(await pw.lstat('not/existing'), undefined) t.equal(pw.lstatSync('not/existing'), undefined) t.equal(pw.lstatSync('also/not/existing'), undefined) t.equal(await pw.lstat('also/not/existing'), undefined) t.equal(pw.cwd.resolve('not/existing')?.isUnknown(), true) const file = pw.lstatSync('exists') if (file == undefined) throw new Error('expect file') t.type(file, Path) t.equal(file.isFile(), true) t.equal(file.isDirectory(), false) t.equal(file.isSymbolicLink(), false) t.equal(file.isCharacterDevice(), false) t.equal(file.isBlockDevice(), false) t.equal(file.isFIFO(), false) t.equal(file.isSocket(), false) t.equal(file.isUnknown(), false) const dir = pw.lstatSync('dir') if (!dir) throw new Error('expect dir to exist') t.type(dir, Path) t.equal(pw.dirname(dir), resolve(td)) t.equal(pw.basename(dir), 'dir') t.equal(dir.isFile(), false) t.equal(dir.isDirectory(), true) t.equal(dir.isSymbolicLink(), false) t.equal(dir.isCharacterDevice(), false) t.equal(dir.isBlockDevice(), false) t.equal(dir.isFIFO(), false) t.equal(dir.isSocket(), false) t.equal(dir.isUnknown(), false) const link = pw.lstatSync('link') if (!link) throw new Error('expect dir to exist') t.type(link, Path) t.equal(link.isFile(), false) t.equal(link.isDirectory(), false) t.equal(link.isSymbolicLink(), true) t.equal(link.isCharacterDevice(), false) t.equal(link.isBlockDevice(), false) t.equal(link.isFIFO(), false) t.equal(link.isSocket(), false) t.equal(link.isUnknown(), false) }) t.test('readdir, simple basic', async t => { const td = t.testdir({ dir: { some: '', entries: '', }, link: t.fixture('symlink', 'dir/some'), file1: '1', file2: '2', }) const pw = new PathScurry(td) t.match( new Set(await pw.readdir('dir')), new Set([{ name: 'some' }, { name: 'entries' }]) ) // gut check t.same( [ pw.cwd.resolve('dir/some').isFile(), pw.cwd.resolve('dir/entries').isFile(), ], [true, true] ) t.match( new Set(await pw.readdir('dir', { withFileTypes: false })), new Set(['some', 'entries']) ) t.match( new Set(pw.readdirSync('dir', { withFileTypes: false })), new Set(['some', 'entries']) ) t.same( new Set(pw.readdirSync('.', { withFileTypes: false })), new Set(['dir', 'link', 'file1', 'file2']) ) t.same( new Set(await pw.readdir('', { withFileTypes: false })), new Set(['dir', 'link', 'file1', 'file2']) ) t.same( new Set(pw.readdirSync({ withFileTypes: false })), new Set(['dir', 'link', 'file1', 'file2']) ) t.same( new Set(await pw.readdir({ withFileTypes: false })), new Set(['dir', 'link', 'file1', 'file2']) ) t.same( new Set(pw.readdirSync().map(e => e.name)), new Set(['dir', 'link', 'file1', 'file2']) ) t.same( new Set((await pw.readdir()).map(e => e.name)), new Set(['dir', 'link', 'file1', 'file2']) ) t.same(pw.cwd.resolve('link').readdirSync(), []) t.same(pw.cwd.resolve('file1').readdirSync(), []) t.same(await pw.cwd.resolve('file2').readdir(), []) for (const e of pw.readdirSync('dir')) { t.equal(e.isFile(), true) t.equal(e.isSymbolicLink(), false) t.same(pw.readdirSync(e), []) t.same(await pw.readdir(e), []) } t.same(await pw.readdir('enoent'), []) t.same(pw.readdirSync('also/enoent'), []) t.test('readdirCB', async t => { t.test('cached, basic', t => { const dir = pw.cwd.resolve('dir') let sync = true dir.readdirCB((er, entries) => { t.equal(er, null) t.match( new Set(entries), new Set([{ name: 'some' }, { name: 'entries' }]) ) t.equal(sync, false, 'did not call cb synchronously') t.end() }) sync = false }) t.test('cached, zalgo', t => { const dir = pw.cwd.resolve('dir') let sync = true dir.readdirCB((er, entries) => { t.equal(er, null) t.match( new Set(entries), new Set([{ name: 'some' }, { name: 'entries' }]) ) t.equal(sync, true, 'called cb synchronously') t.end() }, true) sync = false }) t.test('file', t => { let sync = true pw.cwd.resolve('dir/some').readdirCB((er, entries) => { t.equal(er, null) t.same(entries, []) t.equal(sync, false) t.end() }) sync = false }) t.test('file, zalgo', t => { let sync = true pw.cwd.resolve('dir/some').readdirCB((er, entries) => { t.equal(er, null) t.same(entries, []) t.equal(sync, true) t.end() }, true) sync = false }) t.test('noent', t => { let sync = true pw.cwd.resolve('noent').readdirCB((er, entries) => { t.equal(er, null) t.equal(sync, false) t.same(entries, []) t.end() }) sync = false }) t.test('noent again (cached failure)', t => { let sync = true pw.cwd.resolve('noent').readdirCB((er, entries) => { t.equal(er, null) t.equal(sync, false) t.same(entries, []) t.end() }) sync = false }) t.test('noent again, zalgo (cached failure)', t => { let sync = true pw.cwd.resolve('noent').readdirCB((er, entries) => { t.equal(er, null) t.equal(sync, true) t.same(entries, []) t.end() }, true) sync = false }) }) }) t.test('readdir with provisionals', async t => { const td = t.testdir({ a: '', b: '', c: '', d: '', }) t.test('one provisional', async t => { // play with nocase to show that promotion sets the known name. const pw = new PathScurry(td, { nocase: true }) t.equal(pw.resolve('A'), resolve(td, 'A')) t.equal(pw.resolve('a'), resolve(td, 'A')) t.equal(pw.cwd.resolve('A').isUnknown(), true) t.equal(pw.cwd.resolve('A').isFile(), false) t.equal(pw.cwd.resolve('A').name, 'A') t.same( new Set(pw.readdirSync('', { withFileTypes: false })), new Set(['a', 'b', 'c', 'd']) ) t.equal(pw.cwd.resolve('A').isUnknown(), false) t.equal(pw.cwd.resolve('A').isFile(), true) t.equal(pw.cwd.resolve('A').name, 'a') const pw2 = new PathScurry(td, { nocase: false }) t.equal(pw2.resolve('A'), resolve(td, 'A')) t.not(pw2.resolve('A'), pw2.resolve('a')) t.equal(pw2.cwd.resolve('a').isUnknown(), true) t.equal(pw2.cwd.resolve('a').isFile(), false) t.same( new Set(await pw2.readdir('', { withFileTypes: false })), new Set(['a', 'b', 'c', 'd']) ) t.equal(pw2.cwd.resolve('a').isUnknown(), false) t.equal(pw2.cwd.resolve('a').isFile(), true) }) t.test('two provisional', async t => { const pw = new PathScurry(td) t.equal(pw.resolve('a'), resolve(td, 'a')) t.equal(pw.cwd.resolve('a').isUnknown(), true) t.equal(pw.cwd.resolve('a').isFile(), false) t.equal(pw.resolve('b'), resolve(td, 'b')) t.equal(pw.cwd.resolve('b').isUnknown(), true) t.equal(pw.cwd.resolve('b').isFile(), false) t.same( new Set(pw.readdirSync('', { withFileTypes: false })), new Set(['a', 'b', 'c', 'd']) ) t.equal(pw.cwd.resolve('b').isUnknown(), false) t.equal(pw.cwd.resolve('b').isFile(), true) const pw2 = new PathScurry(td) t.equal(pw2.resolve('a'), resolve(td, 'a')) t.equal(pw2.cwd.resolve('a').isUnknown(), true) t.equal(pw2.cwd.resolve('a').isFile(), false) t.equal(pw2.resolve('b'), resolve(td, 'b')) t.equal(pw2.cwd.resolve('b').isUnknown(), true) t.equal(pw2.cwd.resolve('b').isFile(), false) t.match(pw2.cwd.childrenCache().get(pw2.cwd), { length: 2, provisional: 0, }) t.same( new Set(await pw2.readdir('', { withFileTypes: false })), new Set(['a', 'b', 'c', 'd']) ) t.equal(pw2.cwd.resolve('b').isUnknown(), false) t.equal(pw2.cwd.resolve('b').isFile(), true) t.match(pw2.cwd.childrenCache().get(pw2.cwd), { length: 4, provisional: 4, }) }) t.test('four provisional', async t => { const pw = new PathScurry(td) // do this one in a different order, since some filesystems return sorted // readdir() results. t.equal(pw.resolve('d'), resolve(td, 'd')) t.equal(pw.cwd.resolve('d').isUnknown(), true) t.equal(pw.cwd.resolve('d').isFile(), false) t.equal(pw.resolve('a'), resolve(td, 'a')) t.equal(pw.cwd.resolve('a').isUnknown(), true) t.equal(pw.cwd.resolve('a').isFile(), false) t.equal(pw.resolve('c'), resolve(td, 'c')) t.equal(pw.cwd.resolve('c').isUnknown(), true) t.equal(pw.cwd.resolve('c').isFile(), false) t.equal(pw.resolve('b'), resolve(td, 'b')) t.equal(pw.cwd.resolve('b').isUnknown(), true) t.equal(pw.cwd.resolve('b').isFile(), false) t.match(pw.cwd.childrenCache().get(pw.cwd), { length: 4, provisional: 0, }) t.same( new Set(pw.readdirSync('', { withFileTypes: false })), new Set(['a', 'b', 'c', 'd']) ) t.match(pw.cwd.childrenCache().get(pw.cwd), { length: 4, provisional: 4, }) const pw2 = new PathScurry(td) t.equal(pw2.resolve('d'), resolve(td, 'd')) t.equal(pw2.cwd.resolve('d').isUnknown(), true) t.equal(pw2.cwd.resolve('d').isFile(), false) t.equal(pw2.resolve('a'), resolve(td, 'a')) t.equal(pw2.cwd.resolve('a').isUnknown(), true) t.equal(pw2.cwd.resolve('a').isFile(), false) t.equal(pw2.resolve('c'), resolve(td, 'c')) t.equal(pw2.cwd.resolve('c').isUnknown(), true) t.equal(pw2.cwd.resolve('c').isFile(), false) t.equal(pw2.resolve('b'), resolve(td, 'b')) t.equal(pw2.cwd.resolve('b').isUnknown(), true) t.equal(pw2.cwd.resolve('b').isFile(), false) t.match(pw2.cwd.childrenCache().get(pw2.cwd), { length: 4, provisional: 0, }) t.same( new Set(await pw2.readdir('', { withFileTypes: false })), new Set(['a', 'b', 'c', 'd']) ) t.equal(pw2.cwd.resolve('b').isUnknown(), false) t.equal(pw2.cwd.resolve('b').isFile(), true) t.match(pw2.cwd.childrenCache().get(pw2.cwd), { length: 4, provisional: 4, }) }) t.test('get children, then fail readdir', async t => { t.test('sync', async t => { // give this one not nocase to test the promotion comparison branch const pw = new PathScurry(t.testdir({ dir: { a: '', b: '' } }), { nocase: false, }) pw.resolve('dir', 'a/b') pw.resolve('dir', 'a/c') const children = pw.cwd.childrenCache().get(pw.cwd.resolve('dir/a')) if (!children) throw new Error('no children') t.match(children, { length: 2, provisional: 0 }) // just pretend we learned one was real //@ts-ignore children.provisional++ t.match(children, { length: 2, provisional: 1 }) t.same(pw.readdirSync('dir/a'), []) // nope, now they're all provisional again t.match(children, { length: 2, provisional: 0 }) }) t.test('async', async t => { // give this one nocase to test the promotion comparison branch const pw = new PathScurry(t.testdir({ dir: { a: '', b: '' } }), { nocase: true, }) pw.resolve('dir', 'a/B') pw.resolve('dir', 'a/C') const children = pw.cwd.childrenCache().get(pw.cwd.resolve('dir/a')) if (!children) throw new Error('no children') t.match(children, { length: 2, provisional: 0 }) // just pretend we learned one was real //@ts-ignore children.provisional++ t.match(children, { length: 2, provisional: 1 }) t.same(await pw.readdir('dir/a'), []) // nope, now they're all provisional again t.match(children, { length: 2, provisional: 0 }) }) }) t.test('provisional, known existing, then not', async t => { const td = t.testdir({ a: '', b: { c: '' }, d: { e: '' }, }) const pw = new PathScurry(td) t.equal(pw.lstatSync('b/c')?.isFile(), true) rimrafSync(td + '/b') t.same( new Set(pw.readdirSync('', { withFileTypes: false })), new Set(['a', 'd']) ) t.match(pw.cwd.childrenCache().get(pw.cwd), { length: 3, provisional: 2, }) t.equal(pw.lstatSync('b/c'), undefined) t.equal(pw.lstatSync('b'), undefined) t.equal(pw.cwd.resolve('b/c').isUnknown(), true) const d = pw.cwd.resolve('b/c/d/e') t.equal(d.isUnknown(), true) t.equal(d.lstatSync(), undefined) }) t.test('known dir, then delete it, then read it', async t => { const td = t.testdir({ a: { b: '' } }) const pw = new PathScurry(td) t.equal(pw.lstatSync('a')?.isDirectory(), true) t.equal(pw.lstatSync('a/b')?.isFile(), true) t.equal(pw.cwd.resolve('a').isDirectory(), true) t.equal(pw.cwd.resolve('a/b').isFile(), true) rimrafSync(td + '/a') writeFileSync(td + '/a', '') t.same(pw.readdirSync('a'), []) t.equal(pw.cwd.resolve('a').isDirectory(), false) t.equal(pw.cwd.resolve('a/b').isFile(), false) t.equal(pw.cwd.resolve('a').isUnknown(), true) t.equal(pw.cwd.resolve('a/b').isUnknown(), true) // re-trigger a ENOTDIR for coverage t.equal(pw.lstatSync('a/c'), undefined) }) }) t.test('all the IFMTs!', async t => { const no = () => false const yes = () => true const base = { isFile: no, isDirectory: no, isSymbolicLink: no, isCharacterDevice: no, isBlockDevice: no, isSocket: no, isFIFO: no, isUnknown: no, } const onlyOne = ( t: Tap.Test, e: Path & { [k in keyof typeof base]: () => boolean }, pass: string = '' ) => { for (const k of Object.keys(base) as (keyof typeof base)[]) { t.equal(e[k](), k === pass, `${e.name} ${k} ${k === pass}`) } } const fakeStat = (f: string) => { const b = basename(f) switch (b) { case 'file': return { ...base, name: b, isFile: yes } case 'dir': return { ...base, name: b, isDirectory: yes } case 'link': return { ...base, name: b, isSymbolicLink: yes } case 'chr': return { ...base, name: b, isCharacterDevice: yes } case 'blk': return { ...base, name: b, isBlockDevice: yes } case 'sock': return { ...base, name: b, isSocket: yes } case 'fifo': return { ...base, name: b, isFIFO: yes } case 'nope': return { ...base, name: b } default: return { ...lstatSync(f), name: b } } } const fakeReaddir = (p: string) => { const entries = readdirSync(p) return entries.map(e => fakeStat(resolve(p, e))) } const td = t.testdir({ file: 'file', dir: 'dir', link: 'link', chr: 'chr', blk: 'blk', sock: 'sock', fifo: 'fifo', nope: 'nope', }) const canReaddir = { // of course dirs are worth a shot dir: true, // might be a symlink to a directory link: true, // unknown, worth trying to read it nope: true, file: false, chr: false, blk: false, sock: false, fifo: false, } const mockFsPromises = { ...fsp, lstat: async (f: string) => fakeStat(f), readdir: async (p: string) => fakeReaddir(p), } const mockFs = { ...fs, lstatSync: fakeStat, readdirSync: fakeReaddir, promises: mockFsPromises, } const { PathScurry } = t.mock('../', { fs: mockFs, 'fs/promises': mockFsPromises, }) const pw = new PathScurry(td) t.equal(pw.cwd.resolve('noent').canReaddir(), true) t.equal(pw.cwd.resolve('file').lstatSync()?.canReaddir(), false) const entries = pw.readdirSync() for (const e of entries) { const b = e.name as keyof typeof canReaddir t.equal(e.canReaddir(), canReaddir[b], `${b}.canReaddir`) switch (b) { case 'file': onlyOne(t, e, 'isFile') continue case 'dir': onlyOne(t, e, 'isDirectory') continue case 'link': onlyOne(t, e, 'isSymbolicLink') continue case 'chr': onlyOne(t, e, 'isCharacterDevice') continue case 'blk': onlyOne(t, e, 'isBlockDevice') continue case 'sock': onlyOne(t, e, 'isSocket') continue case 'fifo': onlyOne(t, e, 'isFIFO') continue case 'nope': onlyOne(t, e, 'isUnknown') continue default: onlyOne(t, e, 'should not be here') continue } } }) t.test('weird readdir failure', async t => { // this test is just here for coverage, we return [] for // ALL errors, even those we don't know about. const mockFs = { ...fs, readdirSync: () => { throw Object.assign(new Error('wat'), { code: 'wat' }) }, } const { PathScurry } = t.mock('../', { fs: mockFs }) const pw = new PathScurry(t.testdir({ a: '' })) const a = pw.cwd.resolve('a').lstatSync() t.equal(a.isFile(), true) t.same(pw.readdirSync(), []) t.equal(a.isFile(), true) t.same(pw.cwd.children(), [a]) t.match(pw.cwd.children(), { provisional: 0 }) }) t.test('eloop', async t => { const td = t.testdir({ // ELOOP spin in place pivot: t.fixture('symlink', './pivot'), // what it says on the tin enoent: t.fixture('symlink', 'no thing here'), // a/b/c/d/e/f/g/dest dest: t.fixture('symlink', './a/travel/dest'), // a/b/c/d/e/f/g/round -> ... -> home roundtrip: t.fixture('symlink', './a/travel/round'), home: 'welcome back', // ELOOPs through all the dirs bigloop: t.fixture('symlink', 'a/down'), aa: t.fixture('symlink', 'a'), a: { up: t.fixture('symlink', 'peak'), peak: t.fixture('symlink', 'down'), down: t.fixture('symlink', 'b/down'), travel: t.fixture('symlink', './b/travel'), round: t.fixture('symlink', '../home'), bb: t.fixture('symlink', 'b'), b: { down: t.fixture('symlink', 'c/down'), up: t.fixture('symlink', '../up'), travel: t.fixture('symlink', './c/travel'), round: t.fixture('symlink', '../round'), cc: t.fixture('symlink', 'c'), c: { down: t.fixture('symlink', 'd/down'), up: t.fixture('symlink', '../up'), travel: t.fixture('symlink', './d/travel'), round: t.fixture('symlink', '../round'), dd: t.fixture('symlink', 'd'), d: { down: t.fixture('symlink', 'e/down'), up: t.fixture('symlink', '../up'), travel: t.fixture('symlink', './e/travel'), round: t.fixture('symlink', '../round'), ee: t.fixture('symlink', 'e'), e: { down: t.fixture('symlink', 'f/down'), up: t.fixture('symlink', '../up'), travel: t.fixture('symlink', './f/travel'), round: t.fixture('symlink', '../round'), ff: t.fixture('symlink', 'f'), f: { down: t.fixture('symlink', 'g/down'), up: t.fixture('symlink', '../up'), travel: t.fixture('symlink', './g'), round: t.fixture('symlink', '../round'), gg: t.fixture('symlink', 'g'), g: { down: t.fixture('symlink', 'bounce'), bounce: t.fixture('symlink', 'up'), up: t.fixture('symlink', '../up'), round: t.fixture('symlink', '../round'), dest: 'you have arrived', }, }, }, }, }, }, }, }) const paths = [ 'pivot', 'enoent', 'dest', 'roundtrip', 'bigloop', 'aa/b/cc/d/ee/f/gg', 'a/bb/c/dd/e/ff/g', ] let syncResults: { [k: string]: string | undefined } = {} let asyncResults: { [k: string]: string | undefined } = {} t.test('sync', t => { const pw = new PathScurry(td) // readlink on a noent is for (const p of paths) { syncResults[p] = pw.realpathSync(p) t.equal(pw.cwd.resolve(p).realpathSync()?.fullpath(), syncResults[p]) const onPath = new PathScurry(pw.resolve(p)) t.equal( onPath.realpathSync({ withFileTypes: true })?.fullpath(), syncResults[p] ) } t.matchSnapshot(syncResults) const sr2: typeof syncResults = {} for (const p of paths) { const entry = pw.realpathSync(p, { withFileTypes: true }) if (entry) t.type(entry, Path) sr2[p] = entry?.fullpath() } t.same(sr2, syncResults) t.end() }) t.test('async', async t => { const pw = new PathScurry(td) for (const p of paths) { asyncResults[p] = await pw.realpath(p) } t.matchSnapshot(syncResults) const ar2: typeof asyncResults = {} for (const p of paths) { const entry = await pw.realpath(p, { withFileTypes: true }) if (entry) t.type(entry, Path) ar2[p] = entry?.fullpath() const onPath = new PathScurry(pw.resolve(p)) t.equal( (await onPath.realpath({ withFileTypes: true }))?.fullpath(), ar2[p] ) t.equal(await onPath.realpath(), ar2[p]) } t.same(ar2, asyncResults) }) t.test('walk this beast', async t => { const entries: string[] = [] for await (const entry of new PathScurry(td)) { entries.push(entry.fullpath()) } t.matchSnapshot(entries.sort((a, b) => a.localeCompare(b, 'en'))) }) }) t.test('walking', async t => { const td = t.testdir({ y: t.fixture('symlink', 'x'), x: { outside: '', }, a: { x: t.fixture('symlink', '../y'), deeplink: t.fixture('symlink', 'b/c/d'), empty: {}, b: { c: { d: { e: '', f: '', g: '', cycle: t.fixture('symlink', '../../..'), }, }, d: { e: '', f: '', g: '', cycle: t.fixture('symlink', '../..'), }, }, }, }) + '/a' for (const optFirst of [false, true]) { for (const filter of [undefined, (e: Path) => e.name !== 'd']) { for (const walkFilter of [undefined, (e: Path) => e.name !== 'd']) { for (const follow of [false, undefined, true]) { for (const reuse of [false, true]) { const opts: WalkOptions | undefined = !follow && !walkFilter && !filter && !optFirst ? undefined : { follow, filter, walkFilter, } const name = [ `follow=${follow}`, `filter=${!!filter}`, `walkFilter=${!!walkFilter}`, ].join(', ') t.test(name, async t => { let pw = new PathScurry(td) // if not following, then just take the default args when we // walk to get the entries, to cover that code path. const syncWalk = opts ? optFirst ? pw.walkSync({ ...opts, withFileTypes: true }) : pw.walkSync('', { ...opts, withFileTypes: true }) : pw.walkSync() const entries = new Set() const paths = new Set() t.test('initial walk, sync', async t => { for (const e of syncWalk) { t.type(e, Path) entries.add(e) paths.add(e.fullpath()) } t.matchSnapshot(paths) }) const withFileTypes = false t.test('second walkSync, strings', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() for (const path of pw.walkSync('', { ...(opts || {}), withFileTypes, })) { found.add(path) } t.same(found, paths) }) t.test('async walk, objects', async t => { if (!reuse) pw = new PathScurry(td) const w = opts ? optFirst ? pw.walk({ ...opts, withFileTypes: true }) : pw.walk('', { ...opts, withFileTypes: true }) : pw.walk() const found = new Set() for (const path of await w) { found.add(path) if (reuse && !entries.has(path)) { t.fail('not found in set: ' + path.fullpath()) } } t.match(found, entries) }) t.test('async walk, strings', async t => { const found = new Set() if (!reuse) pw = new PathScurry(td) for (const path of await pw.walk('', { ...(opts || {}), withFileTypes, })) { found.add(path) if (!paths.has(path)) { t.fail('not found in set: ' + path) } } t.same(found, paths) }) if (!opts) { // default iterators never follow, filter, etc. t.test('for [await] of', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() for (const path of pw) { found.add(path) if (reuse && !entries.has(path)) { t.fail('not found in set: ' + path.fullpath()) } } t.same(found, entries) if (!reuse) pw = new PathScurry(td) const found2 = new Set() for await (const path of pw) { found2.add(path) if (reuse && !entries.has(path)) { t.fail('not found in set: ' + path.fullpath()) } } t.same(found2, entries) }) } t.test('iterateSync', async t => { if (!reuse) pw = new PathScurry(td) const f = opts ? optFirst ? pw.iterateSync({ ...opts, withFileTypes: true }) : pw.iterateSync('', { ...opts, withFileTypes: true }) : pw.iterateSync() const found = new Set() for (const path of f) { found.add(path) if (reuse && !entries.has(path)) { t.fail('not found in set: ' + path.fullpath()) } } t.same(found, entries) }) t.test('iterateSync strings', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() for (const path of pw.iterateSync('', { ...(opts || {}), withFileTypes, })) { found.add(path) if (!paths.has(path)) { t.fail('not found: ' + path) } } t.same(found, paths) }) t.test('async iterate', async t => { if (!reuse) pw = new PathScurry(td) const f = opts ? optFirst ? pw.iterate({ ...opts, withFileTypes: true }) : pw.iterate('', { ...opts, withFileTypes: true }) : pw.iterate() let found = new Set() for await (const path of f) { found.add(path) if (reuse && !entries.has(path)) { t.fail('not found in set: ' + path.fullpath()) } } t.same(found, entries) }) t.test('async iterate strings', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() for await (const path of pw.iterate('', { ...(opts || {}), withFileTypes, })) { if (!paths.has(path)) { t.fail('not found in set: ' + path) } found.add(path) if (!paths.has(path)) { t.fail('not found: ' + path) } } t.same(found, paths) }) t.test('stream', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() const stream = opts ? optFirst ? pw.stream({ ...opts, withFileTypes: true }) : pw.stream('', { ...opts, withFileTypes: true }) : pw.stream() stream.on('data', path => { found.add(path) if (reuse && !entries.has(path)) { t.fail('not foundin set: ' + path.fullpath()) } }) await stream.promise() t.same(found, entries) }) t.test('stream, strings', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() const stream = pw.stream('', { ...(opts || {}), withFileTypes, }) stream.on('data', path => { found.add(path) if (reuse && !paths.has(path)) { t.fail('not foundin set: ' + path) } }) await stream.promise() t.same(found, paths) }) t.test('streamSync', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() const stream = opts ? optFirst ? pw.streamSync({ ...opts, withFileTypes: true }) : pw.streamSync('', { ...opts, withFileTypes: true }) : pw.streamSync() stream.on('data', path => { found.add(path) if (reuse && !entries.has(path)) { t.fail('not foundin set: ' + path.fullpath()) } }) t.same(found, entries) }) t.test('streamSync, strings', async t => { if (!reuse) pw = new PathScurry(td) const found = new Set() const stream = pw.streamSync('', { ...(opts || {}), withFileTypes, }) stream.on('data', path => { found.add(path) if (reuse && !paths.has(path)) { t.fail('not foundin set: ' + path) } }) t.same(found, paths) }) }) } } } } } }) t.test('cached methods', t => { const td = t.testdir({ dir: { file: '', }, link: t.fixture('symlink', 'dir/file'), }) const pw = new PathScurry(td) const dir = pw.cwd.resolve('dir') const file = pw.cwd.resolve('dir/file') const noent = pw.cwd.resolve('dir/nope') const link = pw.cwd.resolve('link') t.same(dir.readdirCached(), [], 'has not called readdir') t.equal(dir.readdirSync().length, 1) t.equal(dir.readdirSync()[0], file) t.equal(dir.readdirCached().length, 1) t.equal(dir.readdirCached()[0], file) t.equal(link.readlinkCached(), undefined) t.equal(link.canReadlink(), true) t.equal(link.readlinkSync(), file) t.equal(link.readlinkCached(), file) t.equal(link.canReadlink(), true) t.equal(link.realpathCached(), undefined) t.equal(link.realpathSync(), file) t.equal(link.realpathCached(), file) t.equal(link.lstatCached(), undefined) t.equal(link.lstatSync(), link) t.equal(link.lstatCached(), link) t.equal(noent.lstatCached(), undefined) t.equal(noent.lstatSync(), undefined) t.equal(noent.lstatCached(), undefined) t.end() }) t.test('normalizing unicode pathnames', t => { // café const cafe1 = Buffer.from([0x63, 0x61, 0x66, 0xc3, 0xa9]).toString() // cafe with a ` const cafe2 = Buffer.from([ 0x63, 0x61, 0x66, 0x65, 0xcc, 0x81, ]).toString() // CAFÉ const cafe1u = Buffer.from([0x63, 0x61, 0x66, 0xc3, 0xa9]) .toString() .toUpperCase() // CAFE with a ` const cafe2u = Buffer.from([0x63, 0x61, 0x66, 0x65, 0xcc, 0x81]) .toString() .toUpperCase() t.test('nocase: true', t => { const nc = new PathScurry('', { nocase: true }) const cafe1c = nc.cwd.child(cafe1) const cafe2c = nc.cwd.child(cafe2) const cafe1uc = nc.cwd.child(cafe1u) const cafe2uc = nc.cwd.child(cafe2u) t.equal(cafe1c, cafe2c) t.equal(cafe1c, cafe1uc) t.equal(cafe1c, cafe2uc) t.equal(cafe1c.isNamed(cafe1), true) t.equal(cafe1c.isNamed(cafe2), true) t.equal(cafe1c.isNamed(cafe1u), true) t.equal(cafe1c.isNamed(cafe2u), true) t.equal(cafe2c.isNamed(cafe1), true) t.equal(cafe2c.isNamed(cafe2), true) t.equal(cafe2c.isNamed(cafe1u), true) t.equal(cafe2c.isNamed(cafe2u), true) t.equal(cafe1uc.isNamed(cafe1), true) t.equal(cafe1uc.isNamed(cafe2), true) t.equal(cafe1uc.isNamed(cafe1u), true) t.equal(cafe1uc.isNamed(cafe2u), true) t.equal(cafe2uc.isNamed(cafe1), true) t.equal(cafe2uc.isNamed(cafe2), true) t.equal(cafe2uc.isNamed(cafe1u), true) t.equal(cafe2uc.isNamed(cafe2u), true) t.equal(nc.cwd.children().length, 1) t.end() }) t.test('nocase: false', t => { const nc = new PathScurry('', { nocase: false }) const cafe1c = nc.cwd.child(cafe1) const cafe2c = nc.cwd.child(cafe2) const cafe1uc = nc.cwd.child(cafe1u) const cafe2uc = nc.cwd.child(cafe2u) t.equal(cafe1c, cafe2c) t.equal(cafe1uc, cafe2uc) t.not(cafe1c, cafe1uc) t.not(cafe2c, cafe2uc) t.equal(cafe1c.isNamed(cafe1), true) t.equal(cafe1c.isNamed(cafe2), true) t.equal(cafe1c.isNamed(cafe1u), false) t.equal(cafe1c.isNamed(cafe2u), false) t.equal(cafe2c.isNamed(cafe1), true) t.equal(cafe2c.isNamed(cafe2), true) t.equal(cafe2c.isNamed(cafe1u), false) t.equal(cafe2c.isNamed(cafe2u), false) t.equal(cafe1uc.isNamed(cafe1), false) t.equal(cafe1uc.isNamed(cafe2), false) t.equal(cafe1uc.isNamed(cafe1u), true) t.equal(cafe1uc.isNamed(cafe2u), true) t.equal(cafe2uc.isNamed(cafe1), false) t.equal(cafe2uc.isNamed(cafe2), false) t.equal(cafe2uc.isNamed(cafe1u), true) t.equal(cafe2uc.isNamed(cafe2u), true) t.equal(nc.cwd.children().length, 2) t.end() }) t.end() }) t.test('inflight readdirCB calls', t => { const td: { [k: string]: {} } = {} for (let i = 0; i < 100; i++) { td[String(i)] = {} } const results: Set[] = [] const ps = new PathScurry(t.testdir(td)) for (let i = 0; i < 100; i++) { ps.cwd.readdirCB((er, res) => { if (er) throw er results.push(new Set(res.map(r => r.name))) if (results.length === 100) next() }) } const next = () => { t.equal(results[0].size, 100) for (let i = 1; i < 100; i++) { t.same(results[i], results[0]) } t.end() } }) t.test('inflight async readdir calls', t => { const td: { [k: string]: {} } = {} for (let i = 0; i < 100; i++) { td[String(i)] = {} } const results: Set[] = [] const ps = new PathScurry(t.testdir(td)) for (let i = 0; i < 100; i++) { ps.cwd.readdir().then(res => { results.push(new Set(res.map(r => r.name))) if (results.length === 100) next() }) } const next = () => { t.equal(results[0].size, 100) for (let i = 1; i < 100; i++) { t.same(results[i], results[0]) } t.end() } }) t.test('can use file url as cwd option', t => { const fileURL = pathToFileURL(process.cwd()) const fileURLString = String(fileURL) const ps = new PathScurry(process.cwd()) const pu = new PathScurry(fileURL) const pus = new PathScurry(fileURLString) t.equal(ps.cwd.fullpath(), process.cwd()) t.equal(pu.cwd.fullpath(), process.cwd()) t.equal(pus.cwd.fullpath(), process.cwd()) t.end() }) t.test('depth', t => { const ps = new PathScurry('/a/b/c/d') t.equal(ps.depth(), 4) t.equal(ps.depth('e/../g'), 5) t.equal(ps.root.depth(), 0) t.equal(ps.cwd.depth(), 4) t.equal(ps.cwd.parent?.depth(), 3) t.end() }) t.test('lstat() fills out stat fields', async t => { const cwd = t.testdir({ sync: '', async: '', }) const ps = new PathScurry(cwd) const a = await ps.lstat('async') if (!a) throw new Error('failed async lstat') const ast = lstatSync(cwd + '/async') for (const [field, value] of Object.entries(ast)) { const found = a[field as keyof Path] if (value instanceof Date) { t.equal((found as Date).toISOString(), value.toISOString(), field) } else { t.equal(found, value, field) } } const s = ps.lstatSync('sync') if (!s) throw new Error('failed sync lstat') const sst = lstatSync(cwd + '/sync') for (const [field, value] of Object.entries(sst)) { const found = s[field as keyof Path] if (value instanceof Date) { t.equal((found as Date).toISOString(), value.toISOString(), field) } else { t.equal(found, value, field) } } }) t.test('custom FS override option', async t => { let calledLstatSync = 0 let calledLstat = 0 const myfs: FSOption = { lstatSync: (path: string) => { calledLstatSync++ return lstatSync(path) }, promises: { lstat: async (path: string) => { calledLstat++ return lstat(path) }, }, } const cwd = t.testdir({}) const psNoOption = new PathScurry(cwd) psNoOption.lstatSync() await psNoOption.lstat() t.equal(calledLstat, 0) t.equal(calledLstatSync, 0) const psDefaultOption = new PathScurry(cwd, { fs }) psDefaultOption.lstatSync() await psDefaultOption.lstat() t.equal(calledLstat, 0) t.equal(calledLstatSync, 0) const psCustomFS = new PathScurry(cwd, { fs: myfs }) psCustomFS.lstatSync() await psCustomFS.lstat() t.equal(calledLstat, 1) t.equal(calledLstatSync, 1) const psCustomSync = new PathScurry(cwd, { fs: { ...myfs, promises: undefined, }, }) psCustomSync.lstatSync() await psCustomSync.lstat() t.equal(calledLstat, 1) t.equal(calledLstatSync, 2) }) t.test('chdir', async t => { const ps = new PathScurry() const oldCwd = ps.cwd const a = ps.cwd.resolve('a') const oldRoot = ps.root const rfp = oldRoot.fullpath() const rfpp = oldRoot.fullpathPosix() t.equal(oldRoot.relative(), rfp) t.equal(oldRoot.relativePosix(), rfpp) t.equal(a.relative(), 'a') t.equal(a.relativePosix(), 'a') const bc = a.resolve('b/c') t.equal(bc.relativePosix(), 'a/b/c') const p = ps.cwd.resolve('..') t.equal(p.relative(), '..') ps.chdir('x') t.equal(a.relativePosix(), '../a') t.equal(a.relative(), `..${ps.sep}a`) t.equal(bc.relativePosix(), '../a/b/c') t.equal(p.relative(), `..${ps.sep}..`) t.equal(p.relativePosix(), `../..`) t.equal(ps.cwd.resolve('..'), oldCwd) t.equal(oldCwd.relative(), '..') t.equal(oldCwd.relativePosix(), '..') t.equal(ps.root, oldRoot, 'root unchanged') t.equal(ps.root.fullpath(), rfp, 'root fullpath unchanged') t.equal(ps.root.fullpathPosix(), rfpp, 'root fullpathPosix unchanged') t.equal(ps.root.relative(), rfp, 'root relative unchanged') t.equal(ps.root.relativePosix(), rfpp, 'root relativePosix unchanged') // now change to somewhere a bit more different ps.chdir(ps.cwd.resolve('../../i/j/k/l')) t.equal(oldCwd.relative(), relative(ps.cwd.fullpath(), oldCwd.fullpath())) t.equal(a.relative(), relative(ps.cwd.fullpath(), a.fullpath())) t.equal(bc.relative(), relative(ps.cwd.fullpath(), bc.fullpath())) // verify no-op changes nothing const expect = { newCwd: ps.cwd.fullpath(), oldcwdf: oldCwd.fullpath(), oldcwdr: oldCwd.relative(), oldcwdrp: oldCwd.relativePosix(), ar: a.relative(), arp: a.relativePosix(), rr: oldRoot.relative(), rrp: oldRoot.relativePosix(), } ps.chdir(ps.cwd.fullpath()) t.strictSame({ newCwd: ps.cwd.fullpath(), oldcwdf: oldCwd.fullpath(), oldcwdr: oldCwd.relative(), oldcwdrp: oldCwd.relativePosix(), ar: a.relative(), arp: a.relativePosix(), rr: oldRoot.relative(), rrp: oldRoot.relativePosix(), }, expect) }) isaacs-path-scurry-06957ec/tsconfig-base.json000066400000000000000000000007141443124316700212260ustar00rootroot00000000000000{ "exclude": ["./test", "./tap-snapshots"], "include": ["src/**/*.ts"], "compilerOptions": { "allowSyntheticDefaultImports": true, "declaration": true, "inlineSources": true, "declarationMap": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "moduleResolution": "node", "resolveJsonModule": true, "sourceMap": true, "strict": true, "target": "es2022" } } isaacs-path-scurry-06957ec/tsconfig-esm.json000066400000000000000000000002651443124316700211010ustar00rootroot00000000000000{ "extends": "./tsconfig-base.json", "exclude": ["./test", "./tap-snapshots", "src/index-cjs.ts"], "compilerOptions": { "module": "esnext", "outDir": "dist/mjs" } } isaacs-path-scurry-06957ec/tsconfig.json000066400000000000000000000002271443124316700203150ustar00rootroot00000000000000{ "extends": "./tsconfig-base.json", "compilerOptions": { "module": "commonjs", "outDir": "dist/cjs", "moduleResolution": "Node" } } isaacs-path-scurry-06957ec/typedoc.json000066400000000000000000000001221443124316700201420ustar00rootroot00000000000000{ "navigationLinks": { "isaacs projects": "https://isaacs.github.io/" } }