diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b30cb73 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,44 @@ +# .gitattributes snippet to force users to use same line endings for project. +# +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + + +# These files are text and should be normalized (Convert crlf => lf) +*.php text +*.css text +*.js text eol=lf +*.json text +*.htm text +*.html text +*.xml text +*.txt text +*.ini text +*.inc text +*.pl text +*.rb text +*.py text +*.scm text +*.sql text +.htaccess text +*.sh text + +# These files are binary and should be left untouched +# (binary is a macro for -text -diff) +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.pyc binary diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 48d8b27..1839d98 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,7 +15,7 @@ jobs: - name: Setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 registry-url: 'https://registry.npmjs.org/' - name: Install pnpm @@ -26,10 +26,10 @@ jobs: - name: Install dependencies run: pnpm install + - name: Lint + run: pnpm check + - name: Publish to npm env: - GH_TOKEN: ${{ github.token }} - GITHUB_TOKEN: ${{ github.token }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish --tag ${{ github.event.release.prerelease && 'next' || 'latest' }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..a7359e8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,42 @@ +name: Tests + +on: [push, pull_request] + +concurrency: + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + group: ${{ github.workflow }}-${{ github.ref }} + +jobs: + test: + name: Test on node ${{ matrix.node }} + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + node: [18, 20, 22] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: Install dependencies + run: pnpm install + + - name: Lint + run: pnpm check + + - name: Build + run: pnpm build + + - name: Run tests + run: pnpm coverage diff --git a/.gitignore b/.gitignore index 78b3278..1ae4598 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,14 @@ .DS_Store* .nyc_output .vscode +coverage +dist /build /prebuilds junit.xml node_modules npm-debug.log -yarn-error.log +.pnpm-debug.log +tmp +*.tsbuildinfo +*.tgz diff --git a/CHANGELOG.md b/CHANGELOG.md index d5810d1..8831c0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# v3.0.0 + + * BREAKING CHANGE: Require Node.js 18.17 or newer. + * fix: Fixed order of child key events when parent key is deleted. + * fix: Fixed seg fault during cleanup that occurs when using winreglib in a + worker. + * fix: Fixed bug where the Windows Registry worker thread was being spawned + when adding the first listener. The idea was don't spawn the thread until + there was a listener, however thread shutdown is async and not worth the + hassle in a destructor, so now the background thread is always running. + # v2.0.4 (July 2, 2024) * fix: Fixed crash when app exits (thanks TitusQian) diff --git a/README.md b/README.md index c03a40a..b2bf989 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,37 @@ -# Windows Registry Utility Library +
+
+ winreglib +
+
-A library for querying and watching the Windows Registry. +`winreglib` is a native C++ addon for Node.js for querying and watching Windows +Registry keys. It provides a read-only, synchronous API for accessing the +Windows Registry. -## Prerequisites +## Features -`winreglib` requires N-API version 3 and the following Node.js versions: + - Get, list, and watch registry keys _without_ spawning `reg.exe` + - Written in TypeScript + - Packaged as an ESM module + - Supports x64 (64-bit) and ia32 (32-bit) CPU architectures -* v10.2.0 or newer +## Requirements -## Installation - - npm install winreglib - -## Introduction - -`winreglib` is a native Node.js addon for querying the Windows Registry. The API is synchronous. - -Currently `winreglib` only supports read operations. It can support write operations someday if -need and time exists. +`winreglib` requires Node.js >=18.17.0 (Node-API 8) and ships with pre-built +binaries for x64 and ia32 architectures. ARM-based architectures are not +officially supported, but should technically work as long as you have the +build tools installed. ## Example -```js +```javascript import winreglib from 'winreglib'; const key = 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion'; const results = winreglib.list(key); -console.log(`${results.root}\\${results.path}`); +console.log(`Resolved ${results.resolvedRoot}`); +console.log(`${results.key} has ${results.subkeys.length} subkeys`); console.log(' Subkeys:'); for (const subkey of results.subkeys) { @@ -40,6 +44,20 @@ for (const valueName of results.values) { } ``` +## Supported Root Keys + +| Name | Abbreviation | +| ---------------------------------- | ------------ | +| `HKEY_CLASSES_ROOT` | `HKCR` | +| `HKEY_CURRENT_CONFIG` | `HKCC` | +| `HKEY_CURRENT_USER` | `HKCU` | +| `HKEY_CURRENT_USER_LOCAL_SETTINGS` | | +| `HKEY_LOCAL_MACHINE` | `HKLM` | +| `HKEY_PERFORMANCE_DATA` | | +| `HKEY_PERFORMANCE_NLSTEXT` | | +| `HKEY_PERFORMANCE_TEXT` | | +| `HKEY_USERS` | `HKU` | + ## API ### `get(key, valueName)` @@ -51,12 +69,16 @@ Get a value for the given key and value name. | `key` | String | The key beginning with the root. | | `valueName` | String | The name of the value to get. | -Returns a `String`, `Number`, `Buffer`, `Array.`, or `null` depending on the value. +Returns a `String`, `Number`, `Buffer`, `Array.`, or `null` +depending on the value. If `key` or `valueName` is not found, an `Error` is thrown. ```js -const value = winreglib.get('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', 'ProgramFilesDir'); +const value = winreglib.get( + 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', + 'ProgramFilesDir' +); console.log(value); ``` @@ -73,20 +95,31 @@ Retreives all subkeys and value names for a give key. | -------- | ------ | -------------------------------- | | `key` | String | The key beginning with the root. | -Returns an `Object` with the resolved `resolvedRoot` (String), `key` (String), `subkeys` -(Array[String]), and `values` (Array[String]). +Returns an `RegistryKey` object: + +``` +type RegistryKey = { + resolvedRoot: string; + key: string; + subkeys: string[]; + values: unknown[]; +}; +``` If `key` is not found, an `Error` is thrown. ```js -const result = winreglib.list('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup'); +const result = winreglib.list( + 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup +); console.log(result); ``` ```js { resolvedRoot: 'HKEY_LOCAL_MACHINE', - key: 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup', + key: + 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup', subkeys: [ 'DPI', 'ImageServicingData', @@ -109,8 +142,8 @@ Watches a key for changes in subkeys or values. | -------- | ------ | -------------------------------- | | `key` | String | The key beginning with the root. | -Returns a handle (`EventEmitter`) that emits `"change"` events. Call `handle.stop()` to stop watching -the key. +Returns a handle (`WinRegLibWatchHandle` which extends `EventEmitter`) that +emits `"change"` events. Call `handle.stop()` to stop watching the key. ```js const handle = winreglib.watch('HKLM\\SOFTWARE'); @@ -120,7 +153,8 @@ handle.on('change', evt => { }); ``` -The `"change"` event object contains a change `"type"` and the affected `"key"`. +The `"change"` event object contains a change `"type"` and the affected +`"key"`. | Event Type | Description | | ---------- | ---------------------------------- | @@ -128,36 +162,83 @@ The `"change"` event object contains a change `"type"` and the affected `"key"`. | `change` | A subkey or value was added, changed, deleted, or permissions modified, but we don't know exactly what. | | `delete` | The `key` was deleted. | -`watch()` can track keys that do not exist and when they are created, a change event will be -emitted. You can watch the same key multiple times, however each returned handle is unique and you -must call `handle.stop()` for each. +`watch()` can track keys that do not exist and when they are created, a +change event will be emitted. You can watch the same key multiple times, +however each returned handle is unique and you must call `handle.stop()` for +each. -Due to limitations of the Win32 API, `watch()` is unable to determine what actually changed during -a `change` event type. You will need to call `list()` and cache the subkeys and values, then call -`list()` again when a change is emitted and compare the before and after. +Due to limitations of the Win32 API, `watch()` is unable to determine what +actually changed during a `change` event type. You will need to call `list()` +and cache the subkeys and values, then call `list()` again when a change is +emitted and compare the before and after. -Note that `watch()` does not support recursively watching for changes. +Note that `watch()` does not support recursively watching for changes. The +Win32 API does support recursive watching, so this could be added in the +future. ## Advanced ### Debug Logging -`winreglib` exposes an event emitter that emits debug log messages. This is intended to help debug -issues under the hood. The average user will never need to use this, however it would be handy when -filing a bug. +`winreglib` exposes an event emitter that emits debug log messages. This is +intended to help debug issues under the hood. The average user will never +need to use this, however it would be handy when filing a bug. ```js winreglib.on('log', msg => console.log(msg)); ``` -Alternatively, `winreglib` uses the amazing [`snooplogg`][2] debug logger where you simply set the -`SNOOPLOGG` environment variable to `winreglib` (or `*`) and it will print the debug log to stdout. +Alternatively, `winreglib` uses the amazing [`snooplogg`][2] debug logger +where you simply set the `SNOOPLOGG` environment variable to `winreglib` (or +`*`) and it will print the debug log to `stderr`. + +```bash +$ SNOOPLOGG=winreglib node myapp.js + 6.150s winreglib:Watchman Initializing async work (thread 16764576586047274673) + 6.150s winreglib:Watchman::run Initializing run loop (thread 12502165600786624632) + 6.151s winreglib:Watchman::run Populating active copy (count=0) + 6.151s winreglib:Watchman::run Waiting on 2 objects... + 6.152s winreglib:list key="HKLM" subkey="SOFTWARE\Microsoft\Windows\CurrentVersion" + 6.152s winreglib:list 170 keys (max 30), 11 values (max 24) +``` + +### Building `winreglib` + +`winreglib` has two components: the public interface written in TypeScript and +the native addon written in C++. + +To compile the C++ code, you will need the Microsoft Visual Studio (not VSCode) +or the Microsoft Build Tools. You may also need Python 3 installed. + +| Command | Description | +| -------------------- | ----------- | +| `pnpm build` | Compiles the TypeScript and the Node.js native C++ addon for the current architecture | +| `pnpm build:bundle` | Compiles only the TypeScript code | +| `pnpm build:local` | Compiles only the Node.js native C++ addon | +| `pnpm rebuild:local` | Cleans and re-compiles only the Node.js native C++ addon | + +When publishing, the native C++ addon is prebuilt for x64 and ia32 +architectures. Generally you shouldn't need be concerned with the prebuilt +binaries, however the following commands will compile the prebuilds: + +| Command | Description | +| --------------------- | ------------------------------ | +| `pnpm build:prebuild` | Prebuild for x64 and ia32 | +| `pnpm prebuild-arm` | Prebuild for arm (32-bit) | +| `pnpm prebuild-arm64` | Prebuild for arm64 | +| `pnpm prebuild-ia32` | Prebuild for ia32 (x86 32-bit) | +| `pnpm prebuild-x64` | Prebuild for x64 | + +### Architecture + +When `winreglib` is imported, it immediately spawns a background thread in the +event the app is going to watch a key. If a key is added/changed/deleted, the +background thread sends a message to the main thread which emits the change +event. -## License +## Legal -This project is open source under the [Apache Public License v2][1] and is developed by -[Axway, Inc](http://www.axway.com/) and the community. Please read the [`LICENSE`][1] file included -in this distribution for more information. +Titanium is a registered trademark of TiDev Inc. All Titanium trademark and patent rights were transferred and assigned to TiDev Inc. on 4/7/2022. Please see the LEGAL information about using our trademarks, privacy policy, terms of usage and other legal information at https://tidev.io/legal. -[1]: https://github.com/appcelerator/winreglib/blob/master/LICENSE +[1]: https://github.com/tidev/winreglib/blob/master/LICENSE [2]: https://www.npmjs.com/package/snooplogg diff --git a/binding.gyp b/binding.gyp index b32db48..c9e1bf5 100644 --- a/binding.gyp +++ b/binding.gyp @@ -1,9 +1,4 @@ { - 'variables': { - 'v8_enable_pointer_compression': 0, - 'v8_enable_31bit_smis_on_64bit_arch': 0, - 'openssl_fips': '' - }, 'conditions': [ ['OS=="win"', { 'targets': [ @@ -30,13 +25,6 @@ } } ] - }, { - 'targets': [ - { - 'target_name': 'node_winreglib', - 'type': 'none' - } - ] }] ] } diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..fce092e --- /dev/null +++ b/biome.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json", + "organizeImports": { + "enabled": true + }, + "files": { + "ignore": ["coverage/**", "dist/**"] + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "correctness": { + "noConstantCondition": "off", + "noConstructorReturn": "off" + }, + "performance": { + "noDelete": "off" + } + } + }, + "formatter": { + "enabled": true, + "indentStyle": "tab" + }, + "javascript": { + "formatter": { + "arrowParentheses": "asNeeded", + "quoteStyle": "single", + "semicolons": "always", + "trailingCommas": "none" + } + }, + "json": { + "formatter": { + "indentStyle": "space", + "indentWidth": 2 + } + } +} diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..25796b0 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,6 @@ +pre-commit: + parallel: true + commands: + check: + glob: "*.{js,ts,jsx,tsx}" + run: pnpm check && git update-index --again diff --git a/media/winreglib.webp b/media/winreglib.webp new file mode 100644 index 0000000..d12a26d Binary files /dev/null and b/media/winreglib.webp differ diff --git a/package.json b/package.json index 2237b66..f0d16ea 100644 --- a/package.json +++ b/package.json @@ -1,57 +1,82 @@ { - "name": "winreglib", - "version": "2.0.4", - "description": "Windows Registry Utility Library", - "main": "./src/index", - "gypfile": true, - "author": "Axway, Inc. ", - "maintainers": [ - "Chris Barber " - ], - "license": "Apache-2.0", - "keywords": [ - "appcelerator", - "windows", - "windows registry", - "winreg", - "microsoft" - ], - "scripts": { - "install": "node -e \"process.platform === 'win32' && require('node-gyp-build/bin.js')\"", - "prepublishOnly": "npm run prebuild && npm run prebuild-ia32", - "prebuild": "prebuildify --napi=true --strip", - "prebuild-ia32": "prebuildify --napi=true --strip --arch=ia32", - "build": "node-gyp -j 16 build", - "build-debug": "node-gyp -j 16 build --debug", - "clean": "node-gyp clean", - "rebuild": "node-gyp -j 16 rebuild", - "rebuild-debug": "node-gyp -j 16 rebuild --debug", - "test": "set JUNIT_REPORT_PATH=junit.xml&& mocha -r chai --reporter mocha-jenkins-reporter test/**/test-*.js" - }, - "dependencies": { - "napi-macros": "^2.0.0", - "node-gyp": "^10.1.0", - "node-gyp-build": "4.8.1", - "snooplogg": "^3.0.1" - }, - "devDependencies": { - "chai": "^4.2.0", - "mocha": "^8.2.1", - "mocha-jenkins-reporter": "^0.4.5", - "prebuildify": "^6.0.1" - }, - "homepage": "https://github.com/appcelerator/winreglib", - "bugs": "https://github.com/appcelerator/winreglib/issues", - "repository": { - "type": "git", - "url": "git://github.com/appcelerator/winreglib.git" - }, - "engines": { - "node": ">=10.2.0" - }, - "pnpm": { - "patchedDependencies": { - "node-gyp-build@4.8.1": "patches/node-gyp-build@4.8.1.patch" - } - } + "name": "winreglib", + "version": "3.0.0-rc.0", + "description": "Windows Registry utility library", + "type": "module", + "exports": "./dist/index.js", + "types": "./dist/index.d.js", + "gypfile": true, + "author": "TiDev, Inc. ", + "license": "Apache-2.0", + "keywords": [ + "windows", + "windows registry", + "registry", + "winreg", + "microsoft" + ], + "scripts": { + "build": "pnpm build:bundle && pnpm build:local", + "build:bundle": "rimraf dist && rollup -c rollup.config.ts --configPlugin typescript && pnpm build:types", + "build:local": "node-gyp -j 20 build", + "build:local-debug": "node-gyp -j 20 build --debug", + "build:types": "pnpm build:types:temp && pnpm build:types:roll && pnpm build:types:check", + "build:types:temp": "tsc --declaration --emitDeclarationOnly --outDir temp --project tsconfig.build.json", + "build:types:roll": "rollup --config rollup.dts.config.ts --configPlugin typescript && rimraf temp", + "build:types:check": "tsc --project tsconfig.check.json", + "check": "biome check --write .", + "clean": "node-gyp clean", + "coverage": "vitest --pool=forks --coverage", + "install": "node -e \"process.exit(process.platform === 'win32' ? 0 : 1)\" && node-gyp-build", + "prepublishOnly": "pnpm build:bundle && pnpm prebuild", + "prebuild": "pnpm pnpm prebuild-ia32 && pnpm prebuild-x64", + "prebuild-arm": "prebuildify --napi --strip --platform=win32 --arch arm", + "prebuild-arm64": "prebuildify --napi --strip --platform=win32 --arch arm64", + "prebuild-ia32": "prebuildify --napi --strip --platform=win32 --arch ia32", + "prebuild-x64": "prebuildify --napi --strip --platform=win32 --arch x64", + "rebuild:local": "node-gyp rebuild", + "rebuild:local-debug": "node-gyp rebuild --debug", + "test": "vitest --allowOnly --pool=forks", + "type-check": "tsc --noEmit" + }, + "dependencies": { + "napi-macros": "2.2.2", + "node-gyp": "10.2.0", + "node-gyp-build": "4.8.1", + "snooplogg": "6.0.0" + }, + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@rollup/plugin-typescript": "11.1.6", + "@types/node": "20.14.11", + "@vitest/coverage-v8": "2.0.3", + "esbuild": "0.23.0", + "lefthook": "1.7.3", + "prebuildify": "6.0.1", + "rimraf": "6.0.1", + "rollup": "4.18.1", + "rollup-plugin-dts": "6.1.1", + "rollup-plugin-esbuild": "6.1.1", + "tslib": "2.6.3", + "typescript": "5.5.3", + "vitest": "2.0.3" + }, + "files": [ + "dist", + "patches", + "prebuilds", + "src/*.{cpp,h}", + "binding.gyp" + ], + "homepage": "https://github.com/tidev/winreglib", + "bugs": "https://github.com/tidev/winreglib/issues", + "repository": "https://github.com/tidev/winreglib", + "engines": { + "node": ">=18.17" + }, + "pnpm": { + "patchedDependencies": { + "node-gyp-build@4.8.1": "patches/node-gyp-build@4.8.1.patch" + } + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 426c7a7..938e087 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,37 +14,456 @@ importers: .: dependencies: napi-macros: - specifier: ^2.0.0 + specifier: 2.2.2 version: 2.2.2 node-gyp: - specifier: ^10.1.0 - version: 10.1.0 + specifier: 10.2.0 + version: 10.2.0 node-gyp-build: specifier: 4.8.1 version: 4.8.1(patch_hash=4v3havyznpg2abqwiszfjnuita) snooplogg: - specifier: ^3.0.1 - version: 3.0.2 + specifier: 6.0.0 + version: 6.0.0 devDependencies: - chai: - specifier: ^4.2.0 - version: 4.4.1 - mocha: - specifier: ^8.2.1 - version: 8.4.0 - mocha-jenkins-reporter: - specifier: ^0.4.5 - version: 0.4.8(mocha@8.4.0) + '@biomejs/biome': + specifier: 1.8.3 + version: 1.8.3 + '@rollup/plugin-typescript': + specifier: 11.1.6 + version: 11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.5.3) + '@types/node': + specifier: 20.14.11 + version: 20.14.11 + '@vitest/coverage-v8': + specifier: 2.0.3 + version: 2.0.3(vitest@2.0.3(@types/node@20.14.11)) + esbuild: + specifier: 0.23.0 + version: 0.23.0 + lefthook: + specifier: 1.7.2 + version: 1.7.2 prebuildify: - specifier: ^6.0.1 + specifier: 6.0.1 version: 6.0.1 + rimraf: + specifier: 6.0.1 + version: 6.0.1 + rollup: + specifier: 4.18.1 + version: 4.18.1 + rollup-plugin-dts: + specifier: 6.1.1 + version: 6.1.1(rollup@4.18.1)(typescript@5.5.3) + rollup-plugin-esbuild: + specifier: 6.1.1 + version: 6.1.1(esbuild@0.23.0)(rollup@4.18.1) + tslib: + specifier: 2.6.3 + version: 2.6.3 + typescript: + specifier: 5.5.3 + version: 5.5.3 + vitest: + specifier: 2.0.3 + version: 2.0.3(@types/node@20.14.11) packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.7': + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.24.7': + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.24.7': + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@biomejs/biome@1.8.3': + resolution: {integrity: sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@1.8.3': + resolution: {integrity: sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@1.8.3': + resolution: {integrity: sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@1.8.3': + resolution: {integrity: sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@1.8.3': + resolution: {integrity: sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@1.8.3': + resolution: {integrity: sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@1.8.3': + resolution: {integrity: sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@1.8.3': + resolution: {integrity: sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@1.8.3': + resolution: {integrity: sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.23.0': + resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.23.0': + resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.23.0': + resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.23.0': + resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.23.0': + resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.0': + resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.23.0': + resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.0': + resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.23.0': + resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.23.0': + resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.23.0': + resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.23.0': + resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.23.0': + resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.23.0': + resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.0': + resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.23.0': + resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.23.0': + resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.23.0': + resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.0': + resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.0': + resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.23.0': + resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.23.0': + resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.23.0': + resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.23.0': + resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@npmcli/agent@2.2.2': resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} engines: {node: ^16.14.0 || >=18.0.0} @@ -57,8 +476,136 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@ungap/promise-all-settled@1.1.2': - resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} + '@rollup/plugin-typescript@11.1.6': + resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + + '@rollup/pluginutils@5.1.0': + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.18.1': + resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.18.1': + resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.18.1': + resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.18.1': + resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.18.1': + resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.18.1': + resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.18.1': + resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.18.1': + resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': + resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.18.1': + resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.18.1': + resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.18.1': + resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.18.1': + resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.18.1': + resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.18.1': + resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.18.1': + resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/node@20.14.11': + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} + + '@vitest/coverage-v8@2.0.3': + resolution: {integrity: sha512-53d+6jXFdYbasXBmsL6qaGIfcY5eBQq0sP57AjdasOcSiGNj4qxkkpDKIitUNfjxcfAfUfQ8BD0OR2fSey64+g==} + peerDependencies: + vitest: 2.0.3 + + '@vitest/expect@2.0.3': + resolution: {integrity: sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==} + + '@vitest/pretty-format@2.0.3': + resolution: {integrity: sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==} + + '@vitest/runner@2.0.3': + resolution: {integrity: sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==} + + '@vitest/snapshot@2.0.3': + resolution: {integrity: sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==} + + '@vitest/spy@2.0.3': + resolution: {integrity: sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==} + + '@vitest/utils@2.0.3': + resolution: {integrity: sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==} abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} @@ -72,14 +619,6 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - - ansi-regex@3.0.1: - resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} - engines: {node: '>=4'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -88,6 +627,10 @@ packages: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -96,15 +639,9 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -112,61 +649,34 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - brotli@1.3.3: - resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} - - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - bryt@1.0.2: - resolution: {integrity: sha512-K/qt3xOAOU71q5Y2yJKOqleBwfeJ3J5tOn1pds9b/iQvQ/cq984oSzuv6iOXRxoTdZH3WGOazX1HXu0+sLU7VA==} - engines: {node: '>=8.0.0'} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + cacache@18.0.3: resolution: {integrity: sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==} engines: {node: ^16.14.0 || >=18.0.0} - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} + chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - - chokidar@3.5.1: - resolution: {integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==} - engines: {node: '>= 8.10.0'} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -179,32 +689,23 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - debug@4.3.1: - resolution: {integrity: sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.3.5: resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} @@ -214,22 +715,10 @@ packages: supports-color: optional: true - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} - diff@4.0.1: - resolution: {integrity: sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==} - engines: {node: '>=0.3.1'} - - diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -252,28 +741,35 @@ packages: err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true - exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + esbuild@0.23.0: + resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==} + engines: {node: '>=18'} + hasBin: true - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} foreground-child@3.2.1: resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} @@ -290,48 +786,51 @@ packages: resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-tsconfig@4.7.5: + resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} glob@10.4.2: resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==} engines: {node: '>=16 || 14 >=14.18'} hasBin: true - glob@7.1.6: - resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} - deprecated: Glob versions prior to v9 are no longer supported + glob@11.0.0: + resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + engines: {node: 20 || >=22} + hasBin: true graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - growl@1.10.5: - resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} - engines: {node: '>=4.x'} + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -344,6 +843,10 @@ packages: resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} engines: {node: '>= 14'} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -359,10 +862,6 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -370,36 +869,20 @@ packages: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} + is-core-module@2.14.0: + resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} + engines: {node: '>= 0.4'} is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - is-lambda@1.0.1: resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -408,38 +891,126 @@ packages: resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} engines: {node: '>=16'} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + jackspeak@3.4.0: resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} engines: {node: '>=14'} - js-yaml@4.0.0: - resolution: {integrity: sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==} - hasBin: true + jackspeak@4.0.1: + resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==} + engines: {node: 20 || >=22} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.0: + resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + lefthook-darwin-arm64@1.7.2: + resolution: {integrity: sha512-E3Ouk04/yeD8IBLGJkyzL0NMYIrjADQvaDbf4yNSq6HWGnUC0R2KpYxrZno2yahZnvQ0vYTDta7Egw6cqcYGlQ==} + cpu: [arm64] + os: [darwin] + hasBin: true - log-symbols@4.0.0: - resolution: {integrity: sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==} - engines: {node: '>=10'} + lefthook-darwin-x64@1.7.2: + resolution: {integrity: sha512-Am6ZNmjItQSqKbK8/spFIj5GDWNHJ47PM0vpT1PnBHrgWanjz0iLw6adwpMu8u7+CkZlHjp08lbvjBPGHIu3dg==} + cpu: [x64] + os: [darwin] + hasBin: true + + lefthook-freebsd-arm64@1.7.2: + resolution: {integrity: sha512-o1LBgHhwnUOLs9iVbi1GhvXMQlzYSKnyFcc061iADxHMJk1xWMD6RUyyohmLbfEU0gTWxkRfkdAFvbvwNqQiww==} + cpu: [arm64] + os: [freebsd] + hasBin: true + + lefthook-freebsd-x64@1.7.2: + resolution: {integrity: sha512-vxB3FeeFYDfk4vAahaZdGJ7gbViGOkOyL5JRBDWlFjUfZJLGwVauf6GhtysdO1dgxs9K3ECdEtXgW+uOB872rQ==} + cpu: [x64] + os: [freebsd] + hasBin: true + + lefthook-linux-arm64@1.7.2: + resolution: {integrity: sha512-4dbVj5Jjy12flAyOcVWvWQ6gJoQ6X7HJ3qfsrM8/GIfLQBlkw+YRcLuWHUI3H9qsQFpkpYZsLcmUXoVM77z5mw==} + cpu: [arm64] + os: [linux] + hasBin: true + + lefthook-linux-x64@1.7.2: + resolution: {integrity: sha512-lT0IRp1pGtbua8IWVeIVCSAxKex9fOyAexHaEmBZytfqr/94lpjzWWEQdLFQAlpZthuyCkuaJp5kLgMj6/IySQ==} + cpu: [x64] + os: [linux] + hasBin: true + + lefthook-windows-arm64@1.7.2: + resolution: {integrity: sha512-DxWLmcNI3NICd4rFqTPgXf+G/97ztl+ONvYuNE/ELAxVp338xAUFvzZCQvDZDzeTLrT1C4hZZ4zDvEhnOOECXg==} + cpu: [arm64] + os: [win32] + hasBin: true + + lefthook-windows-x64@1.7.2: + resolution: {integrity: sha512-fL4F8/XXoYUJJ6GSYCwFL+bRufzbkeMSGYZKUDr6ZKOI4KafIEcgFNwlnQF03gY6vkUrYKksXQofOVlOfv3vPA==} + cpu: [x64] + os: [win32] + hasBin: true + + lefthook@1.7.2: + resolution: {integrity: sha512-QCCq6KyVAVYBuxWf338TjMAjjGesyNRtfxJhjYV+kpUkd5ST2yr8ZUJrcEKe+0cUfziPOQ9Hz+1JZniXJx+JqA==} + hasBin: true - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + loupe@3.1.1: + resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} lru-cache@10.3.0: resolution: {integrity: sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==} engines: {node: 14 || >=16.14} + lru-cache@11.0.0: + resolution: {integrity: sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==} + engines: {node: 20 || >=22} + + magic-string@0.30.10: + resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + + magicast@0.3.4: + resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + make-fetch-happen@13.0.1: resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} engines: {node: ^16.14.0 || >=18.0.0} - minimatch@3.0.4: - resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} @@ -492,28 +1063,11 @@ packages: engines: {node: '>=10'} hasBin: true - mocha-jenkins-reporter@0.4.8: - resolution: {integrity: sha512-1nz1Q+YgREUlh2kgFR+lrp+ufEFbdhCdtlEVEJR/5LhgqNLIg52+KG3X94hHpwWnf5SwYLS7udxgBbkWOUbyeQ==} - peerDependencies: - mocha: ^5.2.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 - - mocha@8.4.0: - resolution: {integrity: sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==} - engines: {node: '>= 10.12.0'} - hasBin: true - ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanobuffer@1.1.7: - resolution: {integrity: sha512-LP1JYWQh4qFmpLaauE3mWuOjGJSxts+wnYeTlSb4zurdn8xIhJ906oyb7M7Ih6EiImaUskFdHfYx9gyijf1FLA==} - engines: {node: '>=6.0.0'} - - nanoid@3.1.20: - resolution: {integrity: sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==} + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -532,8 +1086,8 @@ packages: resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true - node-gyp@10.1.0: - resolution: {integrity: sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==} + node-gyp@10.2.0: + resolution: {integrity: sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==} engines: {node: ^16.14.0 || >=18.0.0} hasBin: true @@ -542,24 +1096,20 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - npm-run-path@3.1.0: resolution: {integrity: sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==} engines: {node: '>=8'} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} @@ -568,37 +1118,47 @@ packages: package-json-from-dist@1.0.0: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + prebuildify@6.0.1: resolution: {integrity: sha512-8Y2oOOateom/s8dNBsGIcnm6AxPmLH4/nanQzL5lQMU+sC0CMhzARZHizwr36pUPLdvBnOkCNQzxg4djuFSgIw==} hasBin: true - proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - proc-log@4.2.0: resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -610,25 +1170,45 @@ packages: pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - readdirp@3.5.0: - resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==} - engines: {node: '>=8.10.0'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + + rollup-plugin-dts@6.1.1: + resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} + engines: {node: '>=16'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 + + rollup-plugin-esbuild@6.1.1: + resolution: {integrity: sha512-CehMY9FAqJD5OUaE/Mi1r5z0kNeYxItmRO2zG4Qnv2qWKF09J2lTy5GUzjJR354ZPrLkCj4fiBN41lo8PzBUhw==} + engines: {node: '>=14.18.0'} + peerDependencies: + esbuild: '>=0.18.0' + rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + + rollup@4.18.1: + resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -640,9 +1220,6 @@ packages: engines: {node: '>=10'} hasBin: true - serialize-javascript@5.0.1: - resolution: {integrity: sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -651,6 +1228,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -659,9 +1239,9 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - snooplogg@3.0.2: - resolution: {integrity: sha512-WIeAbTRd64HEtkdoqwK8i9A+anSp1FZXai31fxBzcW8ESvg9wsBuD8+XPVNpX4i6ASUqH73NvXOUVeXzEb0Bcg==} - engines: {node: '>=10'} + snooplogg@6.0.0: + resolution: {integrity: sha512-lzRh5OBbg6mRs94QhCY6UbUVX84rlupvXTfGEeRCEkZmDp3jMf6vGPSVoZ93n3YeUloWSKlWZA81IULVP22GnQ==} + engines: {node: '>=18.17'} socks-proxy-agent@8.0.4: resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==} @@ -671,11 +1251,8 @@ packages: resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} sprintf-js@1.1.3: @@ -685,9 +1262,11 @@ packages: resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - string-width@2.1.1: - resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} - engines: {node: '>=4'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -700,10 +1279,6 @@ packages: string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-ansi@4.0.0: - resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} - engines: {node: '>=4'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -712,17 +1287,24 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-literal@2.1.0: + resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} @@ -735,14 +1317,40 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + + tinybench@2.8.0: + resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} + + tinypool@1.0.0: + resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} + engines: {node: ^18.0.0 || >=20.0.0} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.0: + resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} + engines: {node: '>=14.0.0'} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + unique-filename@3.0.0: resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -754,6 +1362,64 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + vite-node@2.0.3: + resolution: {integrity: sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.3.1: + resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@2.0.3: + resolution: {integrity: sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.0.3 + '@vitest/ui': 2.0.3 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -764,11 +1430,10 @@ packages: engines: {node: ^16.13.0 || >=18.0.0} hasBin: true - wide-align@1.1.3: - resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==} - - workerpool@6.1.0: - resolution: {integrity: sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==} + why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -781,61 +1446,389 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - xml@1.0.1: - resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + optional: true + + '@babel/helper-string-parser@7.24.7': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + optional: true + + '@babel/parser@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/types@7.24.7': + dependencies: + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@bcoe/v8-coverage@0.2.3': {} + + '@biomejs/biome@1.8.3': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 1.8.3 + '@biomejs/cli-darwin-x64': 1.8.3 + '@biomejs/cli-linux-arm64': 1.8.3 + '@biomejs/cli-linux-arm64-musl': 1.8.3 + '@biomejs/cli-linux-x64': 1.8.3 + '@biomejs/cli-linux-x64-musl': 1.8.3 + '@biomejs/cli-win32-arm64': 1.8.3 + '@biomejs/cli-win32-x64': 1.8.3 + + '@biomejs/cli-darwin-arm64@1.8.3': + optional: true + + '@biomejs/cli-darwin-x64@1.8.3': + optional: true + + '@biomejs/cli-linux-arm64-musl@1.8.3': + optional: true + + '@biomejs/cli-linux-arm64@1.8.3': + optional: true + + '@biomejs/cli-linux-x64-musl@1.8.3': + optional: true + + '@biomejs/cli-linux-x64@1.8.3': + optional: true + + '@biomejs/cli-win32-arm64@1.8.3': + optional: true + + '@biomejs/cli-win32-x64@1.8.3': + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.23.0': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.23.0': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.23.0': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.23.0': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.23.0': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.23.0': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.23.0': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.23.0': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.23.0': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.23.0': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.23.0': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.23.0': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.23.0': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.23.0': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.23.0': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.23.0': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.23.0': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.23.0': + optional: true + + '@esbuild/openbsd-arm64@0.23.0': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.23.0': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.23.0': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.23.0': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.23.0': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.23.0': + optional: true + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@npmcli/agent@2.2.2': + dependencies: + agent-base: 7.1.1 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.5 + lru-cache: 10.3.0 + socks-proxy-agent: 8.0.4 + transitivePeerDependencies: + - supports-color + + '@npmcli/fs@3.1.1': + dependencies: + semver: 7.6.2 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/plugin-typescript@11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.5.3)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) + resolve: 1.22.8 + typescript: 5.5.3 + optionalDependencies: + rollup: 4.18.1 + tslib: 2.6.3 + + '@rollup/pluginutils@5.1.0(rollup@4.18.1)': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.18.1 + + '@rollup/rollup-android-arm-eabi@4.18.1': + optional: true + + '@rollup/rollup-android-arm64@4.18.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.18.1': + optional: true + + '@rollup/rollup-darwin-x64@4.18.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.18.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.18.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.18.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.18.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.18.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.18.1': + optional: true - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} + '@rollup/rollup-linux-s390x-gnu@4.18.1': + optional: true - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + '@rollup/rollup-linux-x64-gnu@4.18.1': + optional: true - yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} + '@rollup/rollup-linux-x64-musl@4.18.1': + optional: true - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} + '@rollup/rollup-win32-arm64-msvc@4.18.1': + optional: true - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} + '@rollup/rollup-win32-ia32-msvc@4.18.1': + optional: true - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + '@rollup/rollup-win32-x64-msvc@4.18.1': + optional: true -snapshots: + '@types/estree@1.0.5': {} - '@isaacs/cliui@8.0.2': + '@types/node@20.14.11': dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + undici-types: 5.26.5 - '@npmcli/agent@2.2.2': + '@vitest/coverage-v8@2.0.3(vitest@2.0.3(@types/node@20.14.11))': dependencies: - agent-base: 7.1.1 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.5 - lru-cache: 10.3.0 - socks-proxy-agent: 8.0.4 + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.3.5 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.10 + magicast: 0.3.4 + std-env: 3.7.0 + strip-literal: 2.1.0 + test-exclude: 7.0.1 + tinyrainbow: 1.2.0 + vitest: 2.0.3(@types/node@20.14.11) transitivePeerDependencies: - supports-color - '@npmcli/fs@3.1.1': + '@vitest/expect@2.0.3': dependencies: - semver: 7.6.2 + '@vitest/spy': 2.0.3 + '@vitest/utils': 2.0.3 + chai: 5.1.1 + tinyrainbow: 1.2.0 - '@pkgjs/parseargs@0.11.0': - optional: true + '@vitest/pretty-format@2.0.3': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.0.3': + dependencies: + '@vitest/utils': 2.0.3 + pathe: 1.1.2 + + '@vitest/snapshot@2.0.3': + dependencies: + '@vitest/pretty-format': 2.0.3 + magic-string: 0.30.10 + pathe: 1.1.2 + + '@vitest/spy@2.0.3': + dependencies: + tinyspy: 3.0.0 - '@ungap/promise-all-settled@1.1.2': {} + '@vitest/utils@2.0.3': + dependencies: + '@vitest/pretty-format': 2.0.3 + estree-walker: 3.0.3 + loupe: 3.1.1 + tinyrainbow: 1.2.0 abbrev@2.0.0: {} @@ -850,71 +1843,44 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ansi-colors@4.1.1: {} - - ansi-regex@3.0.1: {} - ansi-regex@5.0.1: {} ansi-regex@6.0.1: {} + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + optional: true + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 ansi-styles@6.2.1: {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - argparse@2.0.1: {} - - assertion-error@1.1.0: {} + assertion-error@2.0.1: {} balanced-match@1.0.2: {} base64-js@1.5.1: {} - binary-extensions@2.3.0: {} - bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - brotli@1.3.3: - dependencies: - base64-js: 1.5.1 - - browser-stdout@1.3.1: {} - - bryt@1.0.2: - dependencies: - brotli: 1.3.3 - - buffer-from@1.1.2: {} - buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 + cac@6.7.14: {} + cacache@18.0.3: dependencies: '@npmcli/fs': 3.1.1 @@ -930,38 +1896,22 @@ snapshots: tar: 6.2.1 unique-filename: 3.0.0 - camelcase@6.3.0: {} - - chai@4.4.1: + chai@5.1.1: dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.0.8 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.1 + pathval: 2.0.0 - check-error@1.0.3: + chalk@2.4.2: dependencies: - get-func-name: 2.0.2 + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + optional: true - chokidar@3.5.1: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.5.0 - optionalDependencies: - fsevents: 2.3.3 + check-error@2.1.1: {} chownr@1.1.4: {} @@ -969,19 +1919,19 @@ snapshots: clean-stack@2.2.0: {} - cliui@7.0.4: + color-convert@1.9.3: dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 + color-name: 1.1.3 + optional: true color-convert@2.0.1: dependencies: color-name: 1.1.4 - color-name@1.1.4: {} + color-name@1.1.3: + optional: true - concat-map@0.0.1: {} + color-name@1.1.4: {} cross-spawn@7.0.3: dependencies: @@ -989,25 +1939,11 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - debug@4.3.1(supports-color@8.1.1): - dependencies: - ms: 2.1.2 - optionalDependencies: - supports-color: 8.1.1 - debug@4.3.5: dependencies: ms: 2.1.2 - decamelize@4.0.0: {} - - deep-eql@4.1.4: - dependencies: - type-detect: 4.0.8 - - diff@4.0.1: {} - - diff@5.0.0: {} + deep-eql@5.0.2: {} eastasianwidth@0.2.0: {} @@ -1028,22 +1964,83 @@ snapshots: err-code@2.0.3: {} - escalade@3.1.2: {} + es-module-lexer@1.5.4: {} - escape-string-regexp@4.0.0: {} + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.23.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.0 + '@esbuild/android-arm': 0.23.0 + '@esbuild/android-arm64': 0.23.0 + '@esbuild/android-x64': 0.23.0 + '@esbuild/darwin-arm64': 0.23.0 + '@esbuild/darwin-x64': 0.23.0 + '@esbuild/freebsd-arm64': 0.23.0 + '@esbuild/freebsd-x64': 0.23.0 + '@esbuild/linux-arm': 0.23.0 + '@esbuild/linux-arm64': 0.23.0 + '@esbuild/linux-ia32': 0.23.0 + '@esbuild/linux-loong64': 0.23.0 + '@esbuild/linux-mips64el': 0.23.0 + '@esbuild/linux-ppc64': 0.23.0 + '@esbuild/linux-riscv64': 0.23.0 + '@esbuild/linux-s390x': 0.23.0 + '@esbuild/linux-x64': 0.23.0 + '@esbuild/netbsd-x64': 0.23.0 + '@esbuild/openbsd-arm64': 0.23.0 + '@esbuild/openbsd-x64': 0.23.0 + '@esbuild/sunos-x64': 0.23.0 + '@esbuild/win32-arm64': 0.23.0 + '@esbuild/win32-ia32': 0.23.0 + '@esbuild/win32-x64': 0.23.0 + + escape-string-regexp@1.0.5: + optional: true - exponential-backoff@3.1.1: {} + estree-walker@2.0.2: {} - fill-range@7.1.1: + estree-walker@3.0.3: dependencies: - to-regex-range: 5.0.1 + '@types/estree': 1.0.5 - find-up@5.0.0: + execa@8.0.1: dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 - flat@5.0.2: {} + exponential-backoff@3.1.1: {} foreground-child@3.2.1: dependencies: @@ -1060,18 +2057,18 @@ snapshots: dependencies: minipass: 7.1.2 - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true - get-caller-file@2.0.5: {} + function-bind@1.1.2: {} get-func-name@2.0.2: {} - glob-parent@5.1.2: + get-stream@8.0.1: {} + + get-tsconfig@4.7.5: dependencies: - is-glob: 4.0.3 + resolve-pkg-maps: 1.0.0 glob@10.4.2: dependencies: @@ -1082,22 +2079,27 @@ snapshots: package-json-from-dist: 1.0.0 path-scurry: 1.11.1 - glob@7.1.6: + glob@11.0.0: dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.0.4 - once: 1.4.0 - path-is-absolute: 1.0.1 + foreground-child: 3.2.1 + jackspeak: 4.0.1 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 2.0.0 graceful-fs@4.2.11: {} - growl@1.10.5: {} + has-flag@3.0.0: + optional: true has-flag@4.0.0: {} - he@1.2.0: {} + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + html-escaper@2.0.2: {} http-cache-semantics@4.1.1: {} @@ -1115,6 +2117,8 @@ snapshots: transitivePeerDependencies: - supports-color + human-signals@5.0.0: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -1126,11 +2130,6 @@ snapshots: indent-string@4.0.0: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} ip-address@9.0.5: @@ -1138,56 +2137,117 @@ snapshots: jsbn: 1.1.0 sprintf-js: 1.1.3 - is-binary-path@2.1.0: + is-core-module@2.14.0: dependencies: - binary-extensions: 2.3.0 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@2.0.0: {} + hasown: 2.0.2 is-fullwidth-code-point@3.0.0: {} - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - is-lambda@1.0.1: {} - is-number@7.0.0: {} - - is-plain-obj@2.1.0: {} + is-stream@3.0.0: {} isexe@2.0.0: {} isexe@3.1.1: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.3.5 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jackspeak@3.4.0: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - js-yaml@4.0.0: + jackspeak@4.0.1: dependencies: - argparse: 2.0.1 + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + js-tokens@4.0.0: + optional: true + + js-tokens@9.0.0: {} jsbn@1.1.0: {} - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 + lefthook-darwin-arm64@1.7.2: + optional: true - log-symbols@4.0.0: - dependencies: - chalk: 4.1.2 + lefthook-darwin-x64@1.7.2: + optional: true + + lefthook-freebsd-arm64@1.7.2: + optional: true + + lefthook-freebsd-x64@1.7.2: + optional: true + + lefthook-linux-arm64@1.7.2: + optional: true + + lefthook-linux-x64@1.7.2: + optional: true - loupe@2.3.7: + lefthook-windows-arm64@1.7.2: + optional: true + + lefthook-windows-x64@1.7.2: + optional: true + + lefthook@1.7.2: + optionalDependencies: + lefthook-darwin-arm64: 1.7.2 + lefthook-darwin-x64: 1.7.2 + lefthook-freebsd-arm64: 1.7.2 + lefthook-freebsd-x64: 1.7.2 + lefthook-linux-arm64: 1.7.2 + lefthook-linux-x64: 1.7.2 + lefthook-windows-arm64: 1.7.2 + lefthook-windows-x64: 1.7.2 + + loupe@3.1.1: dependencies: get-func-name: 2.0.2 lru-cache@10.3.0: {} + lru-cache@11.0.0: {} + + magic-string@0.30.10: + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + magicast@0.3.4: + dependencies: + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + source-map-js: 1.2.0 + + make-dir@4.0.0: + dependencies: + semver: 7.6.2 + make-fetch-happen@13.0.1: dependencies: '@npmcli/agent': 2.2.2 @@ -1205,9 +2265,13 @@ snapshots: transitivePeerDependencies: - supports-color - minimatch@3.0.4: + merge-stream@2.0.0: {} + + mimic-fn@4.0.0: {} + + minimatch@10.0.1: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 2.0.1 minimatch@9.0.5: dependencies: @@ -1256,50 +2320,9 @@ snapshots: mkdirp@1.0.4: {} - mocha-jenkins-reporter@0.4.8(mocha@8.4.0): - dependencies: - diff: 4.0.1 - mkdirp: 1.0.4 - mocha: 8.4.0 - xml: 1.0.1 - - mocha@8.4.0: - dependencies: - '@ungap/promise-all-settled': 1.1.2 - ansi-colors: 4.1.1 - browser-stdout: 1.3.1 - chokidar: 3.5.1 - debug: 4.3.1(supports-color@8.1.1) - diff: 5.0.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 7.1.6 - growl: 1.10.5 - he: 1.2.0 - js-yaml: 4.0.0 - log-symbols: 4.0.0 - minimatch: 3.0.4 - ms: 2.1.3 - nanoid: 3.1.20 - serialize-javascript: 5.0.1 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - which: 2.0.2 - wide-align: 1.1.3 - workerpool: 6.1.0 - yargs: 16.2.0 - yargs-parser: 20.2.4 - yargs-unparser: 2.0.0 - ms@2.1.2: {} - ms@2.1.3: {} - - nanobuffer@1.1.7: - dependencies: - source-map-support: 0.5.21 - - nanoid@3.1.20: {} + nanoid@3.3.7: {} napi-macros@2.2.2: {} @@ -1311,7 +2334,7 @@ snapshots: node-gyp-build@4.8.1(patch_hash=4v3havyznpg2abqwiszfjnuita): {} - node-gyp@10.1.0: + node-gyp@10.2.0: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.1 @@ -1319,7 +2342,7 @@ snapshots: graceful-fs: 4.2.11 make-fetch-happen: 13.0.1 nopt: 7.2.1 - proc-log: 3.0.0 + proc-log: 4.2.0 semver: 7.6.2 tar: 6.2.1 which: 4.0.0 @@ -1330,23 +2353,21 @@ snapshots: dependencies: abbrev: 2.0.0 - normalize-path@3.0.0: {} - npm-run-path@3.1.0: dependencies: path-key: 3.1.1 - once@1.4.0: + npm-run-path@5.3.0: dependencies: - wrappy: 1.0.2 + path-key: 4.0.0 - p-limit@3.1.0: + once@1.4.0: dependencies: - yocto-queue: 0.1.0 + wrappy: 1.0.2 - p-locate@5.0.0: + onetime@6.0.0: dependencies: - p-limit: 3.1.0 + mimic-fn: 4.0.0 p-map@4.0.0: dependencies: @@ -1354,21 +2375,36 @@ snapshots: package-json-from-dist@1.0.0: {} - path-exists@4.0.0: {} + path-key@3.1.1: {} - path-is-absolute@1.0.1: {} + path-key@4.0.0: {} - path-key@3.1.1: {} + path-parse@1.0.7: {} path-scurry@1.11.1: dependencies: lru-cache: 10.3.0 minipass: 7.1.2 - pathval@1.1.1: {} + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.0 + minipass: 7.1.2 + + pathe@1.1.2: {} + + pathval@2.0.0: {} + + picocolors@1.0.1: {} picomatch@2.3.1: {} + postcss@8.4.38: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + prebuildify@6.0.1: dependencies: minimist: 1.2.8 @@ -1378,8 +2414,6 @@ snapshots: pump: 3.0.0 tar-fs: 2.1.1 - proc-log@3.0.0: {} - proc-log@4.2.0: {} promise-retry@2.0.1: @@ -1392,24 +2426,68 @@ snapshots: end-of-stream: 1.4.4 once: 1.4.0 - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - readdirp@3.5.0: - dependencies: - picomatch: 2.3.1 + resolve-pkg-maps@1.0.0: {} - require-directory@2.1.1: {} + resolve@1.22.8: + dependencies: + is-core-module: 2.14.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 retry@0.12.0: {} + rimraf@6.0.1: + dependencies: + glob: 11.0.0 + package-json-from-dist: 1.0.0 + + rollup-plugin-dts@6.1.1(rollup@4.18.1)(typescript@5.5.3): + dependencies: + magic-string: 0.30.10 + rollup: 4.18.1 + typescript: 5.5.3 + optionalDependencies: + '@babel/code-frame': 7.24.7 + + rollup-plugin-esbuild@6.1.1(esbuild@0.23.0)(rollup@4.18.1): + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) + debug: 4.3.5 + es-module-lexer: 1.5.4 + esbuild: 0.23.0 + get-tsconfig: 4.7.5 + rollup: 4.18.1 + transitivePeerDependencies: + - supports-color + + rollup@4.18.1: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.18.1 + '@rollup/rollup-android-arm64': 4.18.1 + '@rollup/rollup-darwin-arm64': 4.18.1 + '@rollup/rollup-darwin-x64': 4.18.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.1 + '@rollup/rollup-linux-arm-musleabihf': 4.18.1 + '@rollup/rollup-linux-arm64-gnu': 4.18.1 + '@rollup/rollup-linux-arm64-musl': 4.18.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1 + '@rollup/rollup-linux-riscv64-gnu': 4.18.1 + '@rollup/rollup-linux-s390x-gnu': 4.18.1 + '@rollup/rollup-linux-x64-gnu': 4.18.1 + '@rollup/rollup-linux-x64-musl': 4.18.1 + '@rollup/rollup-win32-arm64-msvc': 4.18.1 + '@rollup/rollup-win32-ia32-msvc': 4.18.1 + '@rollup/rollup-win32-x64-msvc': 4.18.1 + fsevents: 2.3.3 + safe-buffer@5.2.1: {} safer-buffer@2.1.2: @@ -1417,27 +2495,19 @@ snapshots: semver@7.6.2: {} - serialize-javascript@5.0.1: - dependencies: - randombytes: 2.1.0 - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} + siginfo@2.0.0: {} + signal-exit@4.1.0: {} smart-buffer@4.2.0: {} - snooplogg@3.0.2: - dependencies: - bryt: 1.0.2 - chalk: 4.1.2 - nanobuffer: 1.1.7 - source-map-support: 0.5.21 - supports-color: 8.1.1 + snooplogg@6.0.0: {} socks-proxy-agent@8.0.4: dependencies: @@ -1452,12 +2522,7 @@ snapshots: ip-address: 9.0.5 smart-buffer: 4.2.0 - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} + source-map-js@1.2.0: {} sprintf-js@1.1.3: {} @@ -1465,10 +2530,9 @@ snapshots: dependencies: minipass: 7.1.2 - string-width@2.1.1: - dependencies: - is-fullwidth-code-point: 2.0.0 - strip-ansi: 4.0.0 + stackback@0.0.2: {} + + std-env@3.7.0: {} string-width@4.2.3: dependencies: @@ -1486,10 +2550,6 @@ snapshots: dependencies: safe-buffer: 5.2.1 - strip-ansi@4.0.0: - dependencies: - ansi-regex: 3.0.1 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -1498,16 +2558,23 @@ snapshots: dependencies: ansi-regex: 6.0.1 - strip-json-comments@3.1.1: {} + strip-final-newline@3.0.0: {} - supports-color@7.2.0: + strip-literal@2.1.0: dependencies: - has-flag: 4.0.0 + js-tokens: 9.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + optional: true - supports-color@8.1.1: + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + tar-fs@2.1.1: dependencies: chownr: 1.1.4 @@ -1532,11 +2599,27 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - to-regex-range@5.0.1: + test-exclude@7.0.1: dependencies: - is-number: 7.0.0 + '@istanbuljs/schema': 0.1.3 + glob: 10.4.2 + minimatch: 9.0.5 - type-detect@4.0.8: {} + tinybench@2.8.0: {} + + tinypool@1.0.0: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.0: {} + + to-fast-properties@2.0.0: {} + + tslib@2.6.3: {} + + typescript@5.5.3: {} + + undici-types@5.26.5: {} unique-filename@3.0.0: dependencies: @@ -1548,6 +2631,64 @@ snapshots: util-deprecate@1.0.2: {} + vite-node@2.0.3(@types/node@20.14.11): + dependencies: + cac: 6.7.14 + debug: 4.3.5 + pathe: 1.1.2 + tinyrainbow: 1.2.0 + vite: 5.3.1(@types/node@20.14.11) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + vite@5.3.1(@types/node@20.14.11): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.38 + rollup: 4.18.1 + optionalDependencies: + '@types/node': 20.14.11 + fsevents: 2.3.3 + + vitest@2.0.3(@types/node@20.14.11): + dependencies: + '@ampproject/remapping': 2.3.0 + '@vitest/expect': 2.0.3 + '@vitest/pretty-format': 2.0.3 + '@vitest/runner': 2.0.3 + '@vitest/snapshot': 2.0.3 + '@vitest/spy': 2.0.3 + '@vitest/utils': 2.0.3 + chai: 5.1.1 + debug: 4.3.5 + execa: 8.0.1 + magic-string: 0.30.10 + pathe: 1.1.2 + std-env: 3.7.0 + tinybench: 2.8.0 + tinypool: 1.0.0 + tinyrainbow: 1.2.0 + vite: 5.3.1(@types/node@20.14.11) + vite-node: 2.0.3(@types/node@20.14.11) + why-is-node-running: 2.2.2 + optionalDependencies: + '@types/node': 20.14.11 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + which@2.0.2: dependencies: isexe: 2.0.0 @@ -1556,11 +2697,10 @@ snapshots: dependencies: isexe: 3.1.1 - wide-align@1.1.3: + why-is-node-running@2.2.2: dependencies: - string-width: 2.1.1 - - workerpool@6.1.0: {} + siginfo: 2.0.0 + stackback: 0.0.2 wrap-ansi@7.0.0: dependencies: @@ -1576,29 +2716,4 @@ snapshots: wrappy@1.0.2: {} - xml@1.0.1: {} - - y18n@5.0.8: {} - yallist@4.0.0: {} - - yargs-parser@20.2.4: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.4 - - yocto-queue@0.1.0: {} diff --git a/rollup.config.ts b/rollup.config.ts new file mode 100644 index 0000000..6e1f035 --- /dev/null +++ b/rollup.config.ts @@ -0,0 +1,26 @@ +import typescript from '@rollup/plugin-typescript'; +import { defineConfig } from 'rollup'; +import { minify as esbuildMinifyPlugin } from 'rollup-plugin-esbuild'; + +export default defineConfig([ + { + input: './src/index.ts', + output: { + dir: './dist', + externalLiveBindings: false, + format: 'es', + freeze: false, + preserveModules: false, + sourcemap: true + }, + plugins: [ + esbuildMinifyPlugin({ + minify: true, + minifySyntax: true + }), + typescript({ + tsconfig: './tsconfig.build.json' + }) + ] + } +]); diff --git a/rollup.dts.config.ts b/rollup.dts.config.ts new file mode 100644 index 0000000..cb43fa9 --- /dev/null +++ b/rollup.dts.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'rollup'; +import { dts } from 'rollup-plugin-dts'; + +export default defineConfig([ + { + input: './temp/index.d.ts', + output: { + file: './dist/index.d.ts', + format: 'es' + }, + plugins: [ + dts({ + respectExternal: true + }) + ] + } +]); diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 073d190..0000000 --- a/src/index.js +++ /dev/null @@ -1,77 +0,0 @@ -const binding = require('node-gyp-build')(`${__dirname}/..`); -const { EventEmitter } = require('events'); -const logger = require('snooplogg').default('winreglib'); -const nss = {}; - -/** - * The `winreglib` API and debug log emitter. - * - * @type {EventEmitter} - * @emits {log} Emits a debug log message. - */ -const api = module.exports = new EventEmitter(); - -binding.init((ns, msg) => { - api.emit('log', msg); - if (ns) { - (nss[ns] || (nss[ns] = logger(ns))).log(msg); - } else { - logger.log(msg); - } -}); - -/** - * Gets the value for a specific key value. - * - * @param {String} key - The key. - * @param {String} value - The name of the value to get. - * @returns {*} The value reflects the data type from the registry. - */ -api.get = function get(key, value) { - if (!key || typeof key !== 'string') { - throw new TypeError('Expected key to be a non-empty string'); - } - - if (!value || typeof value !== 'string') { - throw new TypeError('Expected value name to be a non-empty string'); - } - - return binding.get(key, value); -}; - -/** - * Lists all subkeys and values for a specific key. - * - * @param {String} key - The key to list. - * @returns {Object} Contains the resolved `root`, `path`, `subkeys`, and `values`. - */ -api.list = function list(key) { - if (!key || typeof key !== 'string') { - throw new TypeError('Expected key to be a non-empty string'); - } - - return binding.list(key); -}; - -/** - * Watches a key for changes to subkeys and values. - * - * @param {String} key - The key to watch. - * @returns {EventEmitter} The handle to wire up listeners and stop watching. - * @emits {change} Emits an event object containing the `key` that changed. - */ -api.watch = function watch(key) { - if (!key || typeof key !== 'string') { - throw new TypeError('Expected key to be a non-empty string'); - } - - const handle = new EventEmitter(); - const emit = handle.emit.bind(handle); - - binding.watch(key, emit); - handle.stop = function stop() { - binding.unwatch(key, emit); - }; - - return handle; -}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..528b9e2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,111 @@ +import { EventEmitter } from 'node:events'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import nodeGypBuild from 'node-gyp-build/node-gyp-build.js'; +import snooplogg, { type Logger } from 'snooplogg'; + +const cwd = dirname(dirname(fileURLToPath(import.meta.url))); +const binding = nodeGypBuild(cwd); + +const logger = snooplogg('winreglib'); + +/** + * A handle for watching a registry key for changes. + */ +export class WinRegLibWatchHandle extends EventEmitter { + key: string; + stop: () => void; + + constructor(key: string) { + super(); + this.key = key; + + const emitter = this.emit.bind(this); + binding.watch(key, emitter); + + this.stop = () => binding.unwatch(this.key, emitter); + } +} + +export type RegistryKey = { + resolvedRoot: string; + key: string; + subkeys: string[]; + values: unknown[]; +}; + +/** + * The `winreglib` API and debug log emitter. + * + * @type {EventEmitter} + * @emits {log} Emits a debug log message. + */ +class WinRegLib extends EventEmitter { + nss: Record = {}; + + constructor() { + super(); + + binding.init((ns: string, msg: string) => { + this.emit('log', msg); + if (ns) { + if (!this.nss[ns]) { + this.nss[ns] = logger(ns); + } + this.nss[ns].log(msg); + } else { + logger.log(msg); + } + }); + } + + /** + * Gets the value for a specific key value. + * + * @param {String} key - The key. + * @param {String} valueName - The name of the value to get. + * @returns {*} The value reflects the data type from the registry. + */ + get(key: string, valueName: string): unknown { + if (!key || typeof key !== 'string') { + throw new TypeError('Expected key to be a non-empty string'); + } + + if (!valueName || typeof valueName !== 'string') { + throw new TypeError('Expected value name to be a non-empty string'); + } + + return binding.get(key, valueName); + } + + /** + * Lists all subkeys and values for a specific key. + * + * @param {String} key - The key to list. + * @returns {RegistryKey} Contains the resolved `resolvedRoot`, `key`, `subkeys`, and `values`. + */ + list(key: string): RegistryKey | undefined { + if (!key || typeof key !== 'string') { + throw new TypeError('Expected key to be a non-empty string'); + } + + return binding.list(key); + } + + /** + * Watches a key for changes to subkeys and values. + * + * @param {String} key - The key to watch. + * @returns {EventEmitter} The handle to wire up listeners and stop watching. + * @emits {change} Emits an event object containing the `key` that changed. + */ + watch(key: string): WinRegLibWatchHandle { + if (!key || typeof key !== 'string') { + throw new TypeError('Expected key to be a non-empty string'); + } + + return new WinRegLibWatchHandle(key); + } +} + +export default new WinRegLib(); diff --git a/src/watchman.cpp b/src/watchman.cpp index 681b6bb..04fd4aa 100644 --- a/src/watchman.cpp +++ b/src/watchman.cpp @@ -10,7 +10,13 @@ static void execute(napi_env env, void* data) { } static void complete(napi_env env, napi_status status, void* data) { - LOG_DEBUG("Watchman::complete", L"Worker thread exited") + if (status != napi_ok) { + const napi_extended_error_info* error; + ::napi_get_last_error_info(env, &error); + LOG_DEBUG_2("Watchman::complete", L"Watchman::complete: Worker thread failed (status=%d) %hs", status, error->error_message) + } else { + LOG_DEBUG_1("Watchman::complete", L"Worker thread exited (status=%d)", status) + } } /** @@ -31,16 +37,36 @@ Watchman::Watchman(napi_env env) : env(env) { // initialize the background thread that waits for win32 events LOG_DEBUG_THREAD_ID("Watchman", L"Initializing async work") napi_value name; - NAPI_THROW("Watchman", "ERR_NAPI_CREATE_STRING", ::napi_create_string_utf8(env, "winreglib.runloop", NAPI_AUTO_LENGTH, &name)); - NAPI_THROW("Watchman", "ERR_NAPI_CREATE_ASYNC_WORK", ::napi_create_async_work(env, NULL, name, execute, complete, this, &asyncWork)); + NAPI_THROW("Watchman", "ERR_NAPI_CREATE_STRING", ::napi_create_string_utf8( + env, + "winreglib.runloop", + NAPI_AUTO_LENGTH, + &name + )) + NAPI_THROW("Watchman", "ERR_NAPI_CREATE_ASYNC_WORK", ::napi_create_async_work( + env, + NULL, + name, + execute, + complete, + this, + &asyncWork + )) + NAPI_THROW("Watchman", "ERR_NAPI_QUEUE_ASYNC_WORK", ::napi_queue_async_work(env, asyncWork)) // wire up our dispatch change handler into Node's event loop, then unref it so that we don't // block Node from exiting uv_loop_t* loop; ::napi_get_uv_event_loop(env, &loop); + notifyChange = new uv_async_t; - notifyChange->data = this; - ::uv_async_init(loop, notifyChange, [](uv_async_t* handle) { if (handle && handle->data) ((Watchman*)handle->data)->dispatch(); }); + notifyChange->data = (void*)this; + ::uv_async_init(loop, notifyChange, [](uv_async_t* handle) { + // the background thread has signaled that a registry event has occurred + if (handle && handle->data) { + ((Watchman*)handle->data)->dispatch(); + } + }); ::uv_unref((uv_handle_t*)notifyChange); } @@ -52,7 +78,11 @@ Watchman::~Watchman() { ::napi_delete_async_work(env, asyncWork); ::CloseHandle(term); ::CloseHandle(refresh); - ::uv_close((uv_handle_t*)notifyChange, [](uv_handle_t* handle) { if (handle) delete (uv_async_t*)handle; }); + + ::uv_close(reinterpret_cast(notifyChange), [](uv_handle_t* handle) { + uv_async_t* async = reinterpret_cast(handle); + delete async; + }); } /** @@ -129,14 +159,10 @@ void Watchman::config(const std::wstring& key, napi_value listener, WatchAction } } - if (beforeCount == 0 && afterCount > 0) { - LOG_DEBUG_THREAD_ID("Watchman::config", L"Starting background thread") - NAPI_THROW("Watchman::config", "ERR_NAPI_QUEUE_ASYNC_WORK", ::napi_queue_async_work(env, asyncWork)) - } else if (beforeCount > 0 && afterCount == 0) { - LOG_DEBUG_THREAD_ID("Watchman::config", L"Signalling term event") - ::SetEvent(term); - } else if (beforeCount != afterCount) { - LOG_DEBUG_THREAD_ID("Watchman::config", L"Signalling refresh event") + // if we have any active listeners and the number of listeners changed, + // then signal the refresh + if (afterCount > 0 && beforeCount != afterCount) { + LOG_DEBUG_THREAD_ID("Watchman::config", L"Signaling refresh event") ::SetEvent(refresh); } @@ -152,7 +178,7 @@ void Watchman::dispatch() { while (1) { std::shared_ptr node; - DWORD count = 0; + DWORD remaining = 0; // check if there are any changed nodes left... // the first time we loop, we know there's at least one @@ -160,15 +186,15 @@ void Watchman::dispatch() { std::lock_guard lock(changedNodesLock); if (changedNodes.empty()) { - break; + return; } - count = changedNodes.size(); + remaining = changedNodes.size(); node = changedNodes.front(); changedNodes.pop_front(); } - LOG_DEBUG_2("Watchman::dispatch", L"Dispatching change event for \"%ls\" (%d pending)", node->name.c_str(), --count) + LOG_DEBUG_2("Watchman::dispatch", L"Dispatching change event for \"%ls\" (%d remaining)", node->name.c_str(), --remaining) if (node->onChange()) { printTree(); } diff --git a/src/watchnode.cpp b/src/watchnode.cpp index 5266929..9ed7409 100644 --- a/src/watchnode.cpp +++ b/src/watchnode.cpp @@ -81,6 +81,8 @@ std::u16string WatchNode::getKey() { /** * Attempts to open this node's registry key and watch it. + * + * Returns true if something changed. */ bool WatchNode::load(CallbackQueue* pending) { bool result = false; @@ -99,8 +101,6 @@ bool WatchNode::load(CallbackQueue* pending) { LOG_DEBUG_1("WatchNode::load", L"\"%ls\" hkey is still valid", name.c_str()) } else { // no longer valid! - LOG_DEBUG_1("WatchNode::load", L"\"%ls\" hkey is no longer valid", name.c_str()) - unload(pending); result = true; } } else { @@ -112,13 +112,11 @@ bool WatchNode::load(CallbackQueue* pending) { watch(pending); if (pending) { - PUSH_CALLBACK(*pending, "add", getKey(), listeners); + PUSH_CALLBACK(*pending, "add", getKey(), listeners) } for (auto const& it : subkeys) { - if (it.second->load(pending)) { - result = true; - } + it.second->load(pending); } result = true; @@ -146,7 +144,18 @@ bool WatchNode::onChange() { if (hkey) { if (watch(&pending)) { - PUSH_CALLBACK(pending, "change", getKey(), listeners); + // hkey should be valid, check if subkeys are ok + LOG_DEBUG_1("WatchNode::onChange", L"Checking if subkeys under \"%ls\" are still valid", name.c_str()) + for (auto const& it : subkeys) { + HKEY tmp; + LSTATUS status = ::RegOpenKeyW(hkey, it.second->name.c_str(), &tmp); + if (status != ERROR_SUCCESS) { + LOG_DEBUG_1("WatchNode::onChange", L"\"%ls\" hkey is no longer valid", it.second->name.c_str()) + it.second->unload(&pending); + } + } + + PUSH_CALLBACK(pending, "change", getKey(), listeners) } for (auto const& it : subkeys) { @@ -251,13 +260,15 @@ void WatchNode::unload(CallbackQueue* pending) { hkey = NULL; if (pending) { - PUSH_CALLBACK(*pending, "delete", getKey(), listeners); + PUSH_CALLBACK(*pending, "delete", getKey(), listeners) } } } /** - * Wires up the change notification event. + * Wires up the Windows Registry change notification event asynchronously. + * + * Returns true if the key is valid and the watcher was successfully registered. */ bool WatchNode::watch(CallbackQueue* pending) { if (hkey) { diff --git a/src/watchnode.h b/src/watchnode.h index 0e63619..36bb412 100644 --- a/src/watchnode.h +++ b/src/watchnode.h @@ -20,7 +20,7 @@ const DWORD filter = REG_NOTIFY_CHANGE_NAME | #define PUSH_CALLBACK(list, evtType, key, listeners) \ if (listeners.size() > 0) { \ - char type[] = evtType; \ + const char* type = evtType; \ (list).push(std::make_shared(type, key, listeners)); \ } @@ -28,10 +28,13 @@ const DWORD filter = REG_NOTIFY_CHANGE_NAME | * Holds everything needed to emit a change event for a given node. */ struct Callback { - Callback(char* type, std::u16string key, std::list listeners) : - type(type), key(key), listeners(listeners) {} + Callback(const char* type, std::u16string key, std::list listeners) : + key(key), listeners(listeners) + { + strncpy(this->type, type, 10); + } - char* type; + char type[10]; std::u16string key; std::list listeners; }; diff --git a/src/winreglib.cpp b/src/winreglib.cpp index 41704b1..797d679 100644 --- a/src/winreglib.cpp +++ b/src/winreglib.cpp @@ -222,9 +222,12 @@ NAPI_METHOD(init) { // wire up the log notification handler uv_loop_t* loop; napi_get_uv_event_loop(env, &loop); - winreglib::logNotify.data = env; - uv_async_init(loop, &winreglib::logNotify, &dispatchLog); - uv_unref((uv_handle_t*)&winreglib::logNotify); + if (!winreglib::logNotify) { + winreglib::logNotify = new uv_async_t; + } + winreglib::logNotify->data = env; + uv_async_init(loop, (uv_async_t*)winreglib::logNotify, &dispatchLog); + uv_unref((uv_handle_t*)winreglib::logNotify); // create the reference for the emit log callback so it doesn't get GC'd NAPI_THROW_RETURN("init", "ERR_NAPI_CREATE_REFERENCE", napi_create_reference(env, logFn, 1, &winreglib::logRef), NULL) @@ -376,27 +379,31 @@ NAPI_METHOD(unwatch) { } /** - * Destroys the Watchman instance and closes open handles. + * Destroys the Watchman instance, log ref handle, and notify handle. */ -static void cleanup(void* arg) { - napi_env env = (napi_env)arg; - +static void cleanup(napi_async_cleanup_hook_handle handle, void* arg) { if (winreglib::watchman) { - LOG_DEBUG("cleanup", L"Deleting watchman") delete winreglib::watchman; - winreglib::watchman = NULL; } - uv_close((uv_handle_t*)&winreglib::logNotify, NULL); - if (winreglib::logRef) { - napi_delete_reference(env, winreglib::logRef); + napi_delete_reference((napi_env)arg, winreglib::logRef); winreglib::logRef = NULL; } + + if (winreglib::logNotify) { + uv_close((uv_handle_t*)winreglib::logNotify, [](uv_handle_t* handle) { + if (handle) { + delete handle; + } + }); + } + + napi_remove_async_cleanup_hook(handle); } /** - * Wire up the public API and cleanup handler and creates the Watchman instance. + * Wire up the public API, cleanup handler, and creates the Watchman instance. */ NAPI_INIT() { NAPI_EXPORT_FUNCTION(get); @@ -405,7 +412,11 @@ NAPI_INIT() { NAPI_EXPORT_FUNCTION(watch); NAPI_EXPORT_FUNCTION(unwatch); - NAPI_THROW("init", "ERR_NAPI_ADD_ENV_CLEANUP_HOOK", napi_add_env_cleanup_hook(env, cleanup, env)) + NAPI_THROW( + "init", + "ERR_NAPI_ADD_ASYNC_CLEANUP_HOOK", + napi_add_async_cleanup_hook(env, cleanup, NULL, NULL) + ) winreglib::watchman = new winreglib::Watchman(env); } diff --git a/src/winreglib.h b/src/winreglib.h index 1303756..02ce385 100644 --- a/src/winreglib.h +++ b/src/winreglib.h @@ -4,7 +4,8 @@ // enable the following line to bypass the message queue and print the raw debug log messages to stdout // #define ENABLE_RAW_DEBUGGING -#define NAPI_VERSION 3 +// v12.22.0+, v14.17.0+, v15.12.0+, 16.0.0 and all later versions +#define NAPI_VERSION 8 #include #include @@ -193,12 +194,12 @@ namespace winreglib { #define LOG_DEBUG_VARS \ std::mutex logLock; \ - uv_async_t logNotify; \ + uv_async_t* logNotify; \ std::queue> logQueue; #define LOG_DEBUG_EXTERN_VARS \ extern std::mutex logLock; \ - extern uv_async_t logNotify; \ + extern uv_async_t* logNotify; \ extern std::queue> logQueue; #ifdef ENABLE_RAW_DEBUGGING @@ -218,7 +219,9 @@ namespace winreglib { std::shared_ptr obj = std::make_shared(ns, u16buffer); \ std::lock_guard lock(winreglib::logLock); \ winreglib::logQueue.push(obj); \ - ::uv_async_send(&winreglib::logNotify); \ + if (winreglib::logNotify) { \ + ::uv_async_send(winreglib::logNotify); \ + } \ } #define WLOG_DEBUG(ns, wmsg) \ @@ -227,7 +230,9 @@ namespace winreglib { std::shared_ptr obj = std::make_shared(ns, u16buffer); \ std::lock_guard lock(winreglib::logLock); \ winreglib::logQueue.push(obj); \ - ::uv_async_send(&winreglib::logNotify); \ + if (winreglib::logNotify) { \ + ::uv_async_send(winreglib::logNotify); \ + } \ } #endif diff --git a/test/get.test.ts b/test/get.test.ts new file mode 100644 index 0000000..70f0164 --- /dev/null +++ b/test/get.test.ts @@ -0,0 +1,147 @@ +import fs from 'node:fs'; +import { describe, expect, it } from 'vitest'; +import winreglib from '../src/index.js'; +const { spawnSync } = require('node:child_process'); +import snooplogg from 'snooplogg'; + +const { log } = snooplogg('test:winreglib'); + +const reg = (...args) => { + log(`Executing: reg ${args.join(' ')}`); + spawnSync('reg', args, { stdio: 'ignore' }); +}; + +describe('get()', () => { + it('should error if key is not specified', () => { + expect(() => { + // biome-ignore lint/suspicious/noExplicitAny: need to test invalid input + winreglib.get(undefined as any, undefined as any); + }).toThrowError(new TypeError('Expected key to be a non-empty string')); + }); + + it('should error if value name is not specified', () => { + expect(() => { + // biome-ignore lint/suspicious/noExplicitAny: need to test invalid input + winreglib.get('HKLM\\software', undefined as any); + }).toThrowError( + new TypeError('Expected value name to be a non-empty string') + ); + }); + + it('should error if key does not contain a subkey', () => { + expect(() => { + winreglib.get('foo', 'bar'); + }).toThrowError( + new Error('Expected key to contain both a root and subkey') + ); + }); + + it('should error if key is not valid', () => { + expect(() => { + winreglib.get('foo\\bar', 'baz'); + }).toThrowError(new Error('Invalid registry root key "foo"')); + }); + + it('should error if key is not found', () => { + expect(() => { + winreglib.get('HKLM\\foo', 'bar'); + }).toThrowError(new Error('Registry key or value not found')); + }); + + it('should error if value is not found', () => { + expect(() => { + winreglib.get('HKLM\\SOFTWARE', 'bar'); + }).toThrowError(new Error('Registry key or value not found')); + }); + + it('should get a string value', () => { + const value = winreglib.get( + 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', + 'ProgramFilesDir' + ) as string; + expect(value).toBeTypeOf('string'); + expect(value).not.toBe(''); + expect(fs.existsSync(value)).toBe(true); + }); + + it('should get an expanded string value', () => { + const value = winreglib.get( + 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', + 'ProgramFilesPath' + ) as string; + expect(value).toBeTypeOf('string'); + expect(value).not.toBe(''); + expect(fs.existsSync(value)).toBe(true); + }); + + it('should get multi-string value', () => { + const value = winreglib.get( + 'HKLM\\HARDWARE\\DESCRIPTION\\System', + 'SystemBiosVersion' + ) as string[]; + expect(value).toBeInstanceOf(Array); + expect(value.length).toBeGreaterThan(0); + for (const v of value) { + expect(v).toBeTypeOf('string'); + expect(v).not.toBe(''); + } + }); + + it('should get an 32-bit integer value', () => { + const value = winreglib.get( + 'HKLM\\HARDWARE\\DESCRIPTION\\System', + 'Capabilities' + ) as number; + expect(value).toBeTypeOf('number'); + expect(value).toBeGreaterThanOrEqual(0); + }); + + it('should get an 64-bit integer value', async () => { + const value = winreglib.get( + 'HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\StateRepositoryStatus', + 'MaintenanceLastPerformed' + ) as number; + expect(value).toBeTypeOf('number'); + expect(value).toBeGreaterThan(0); + }); + + it('should get a binary value', () => { + const value = winreglib.get( + 'HKLM\\HARDWARE\\DESCRIPTION\\System', + 'Component Information' + ) as Buffer; + expect(value).toBeInstanceOf(Buffer); + expect(value.length).toBeGreaterThan(0); + }); + + it('should get a full resource descriptor value', () => { + const value = winreglib.get( + 'HKLM\\HARDWARE\\DESCRIPTION\\System', + 'Configuration Data' + ) as Buffer; + expect(value).toBeInstanceOf(Buffer); + expect(value.length).toBeGreaterThan(0); + }); + + it('should get a resource list value', () => { + const value = winreglib.get( + 'HKLM\\HARDWARE\\RESOURCEMAP\\System Resources\\Loader Reserved', + '.Raw' + ) as Buffer; + expect(value).toBeInstanceOf(Buffer); + expect(value.length).toBeGreaterThan(0); + }); + + it('should get none value', { timeout: 15000 }, () => { + try { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib'); + reg('add', 'HKCU\\Software\\winreglib', '/v', 'foo', '/t', 'REG_NONE'); + + const value = winreglib.get('HKCU\\Software\\winreglib', 'foo'); + expect(value).toBeNull(); + } finally { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + }); +}); diff --git a/test/list.test.ts b/test/list.test.ts new file mode 100644 index 0000000..2978f26 --- /dev/null +++ b/test/list.test.ts @@ -0,0 +1,57 @@ +import assert from 'node:assert'; +import { describe, expect, it } from 'vitest'; +import winreglib from '../src/index.js'; + +describe('list()', () => { + it('should error if key is not specified', () => { + expect(() => { + // biome-ignore lint/suspicious/noExplicitAny: need to test invalid input + winreglib.list(undefined as any); + }).toThrowError(new Error('Expected key to be a non-empty string')); + }); + + it('should error if key does not contain a subkey', () => { + expect(() => { + winreglib.list('foo'); + }).toThrowError( + new Error('Expected key to contain both a root and subkey') + ); + }); + + it('should error if key is not valid', () => { + expect(() => { + winreglib.list('foo\\bar'); + }).toThrowError(new Error('Invalid registry root key "foo"')); + }); + + it('should error if key is not found', () => { + expect(() => { + winreglib.list('HKLM\\foo'); + }).toThrowError(new Error('Registry key or value not found')); + }); + + it('should retrieve subkeys and values', () => { + const result = winreglib.list( + 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion' + ); + expect(result).toBeTypeOf('object'); + assert(result); + expect(result).toHaveProperty('resolvedRoot', 'HKEY_LOCAL_MACHINE'); + expect(result).toHaveProperty( + 'key', + 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion' + ); + expect(result).toHaveProperty('subkeys'); + expect(result.subkeys).toBeInstanceOf(Array); + for (const key of result.subkeys) { + expect(key).toBeTypeOf('string'); + expect(key).not.toBe(''); + } + expect(result).toHaveProperty('values'); + expect(result.values).toBeInstanceOf(Array); + for (const value of result.values) { + expect(value).toBeTypeOf('string'); + expect(value).not.toBe(''); + } + }); +}); diff --git a/test/test-winreglib.js b/test/test-winreglib.js deleted file mode 100644 index f6a5518..0000000 --- a/test/test-winreglib.js +++ /dev/null @@ -1,725 +0,0 @@ -const fs = require('fs'); -const winreglib = require('../src/index'); -const { expect } = require('chai'); -const { spawnSync } = require('child_process'); -const snooplogg = require('snooplogg').default; - -const { log } = snooplogg('test:winreglib'); - -const reg = (...args) => { - log('Executing: reg ' + args.join(' ')); - spawnSync('reg', args, { stdio: 'ignore' }); -}; - -describe('get()', () => { - it('should error if key is not specified', () => { - try { - winreglib.get(); - } catch (e) { - expect(e.message).to.equal('Expected key to be a non-empty string'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if value name is not specified', () => { - try { - winreglib.get('HKLM\\software'); - } catch (e) { - expect(e.message).to.equal('Expected value name to be a non-empty string'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key does not contain a subkey', () => { - try { - winreglib.get('foo', 'bar'); - } catch (e) { - expect(e.message).to.equal('Expected key to contain both a root and subkey'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key is not valid', () => { - try { - winreglib.get('foo\\bar', 'baz'); - } catch (e) { - expect(e.message).to.equal('Invalid registry root key "foo"'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key is not found', () => { - try { - winreglib.get('HKLM\\foo', 'bar'); - } catch (e) { - expect(e.message).to.equal('Registry key or value not found'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if value is not found', () => { - try { - winreglib.get('HKLM\\SOFTWARE', 'bar'); - } catch (e) { - expect(e.message).to.equal('Registry key or value not found'); - return; - } - throw new Error('Expected error'); - }); - - it('should get a string value', () => { - const value = winreglib.get('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', 'ProgramFilesDir'); - expect(value).to.be.a('string'); - expect(value).to.not.equal(''); - expect(fs.existsSync(value)).to.be.true; - }); - - it('should get an expanded string value', () => { - const value = winreglib.get('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion', 'ProgramFilesPath'); - expect(value).to.be.a('string'); - expect(value).to.not.equal(''); - expect(fs.existsSync(value)).to.be.true; - }); - - it('should get multi-string value', () => { - const value = winreglib.get('HKLM\\HARDWARE\\DESCRIPTION\\System', 'SystemBiosVersion'); - expect(value).to.be.an('array'); - expect(value).to.have.lengthOf.above(0); - for (const v of value) { - expect(v).to.be.a('string'); - expect(v).to.not.equal(''); - } - }); - - it('should get an 32-bit integer value', () => { - const value = winreglib.get('HKLM\\HARDWARE\\DESCRIPTION\\System', 'Capabilities'); - expect(value).to.be.a('number'); - expect(value).to.be.at.least(0); - }); - - it('should get an 64-bit integer value', () => { - const value = winreglib.get('HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Diagnostics\\DiagTrack', 'TriggerCount'); - expect(value).to.be.a('number'); - expect(value).to.be.at.least(0); - }); - - it('should get a binary value', () => { - const value = winreglib.get('HKLM\\HARDWARE\\DESCRIPTION\\System', 'Component Information'); - expect(value).to.be.an.instanceof(Buffer); - expect(value.length).to.be.above(0); - }); - - it('should get a full resource descriptor value', () => { - const value = winreglib.get('HKLM\\HARDWARE\\DESCRIPTION\\System', 'Configuration Data'); - expect(value).to.be.an.instanceof(Buffer); - expect(value.length).to.be.above(0); - }); - - it('should get a resource list value', () => { - const value = winreglib.get('HKLM\\HARDWARE\\RESOURCEMAP\\System Resources\\Loader Reserved', '.Raw'); - expect(value).to.be.an.instanceof(Buffer); - expect(value.length).to.be.above(0); - }); - - it('should get none value', function () { - this.timeout(15000); - this.slow(14000); - - try { - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib'); - reg('add', 'HKCU\\Software\\winreglib', '/v', 'foo', '/t', 'REG_NONE'); - - const value = winreglib.get('HKCU\\Software\\winreglib', 'foo'); - expect(value).to.be.null; - } finally { - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); -}); - -describe('list()', () => { - it('should error if key is not specified', () => { - try { - winreglib.list(); - } catch (e) { - expect(e.message).to.equal('Expected key to be a non-empty string'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key does not contain a subkey', () => { - try { - winreglib.list('foo'); - } catch (e) { - expect(e.message).to.equal('Expected key to contain both a root and subkey'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key is not valid', () => { - try { - winreglib.list('foo\\bar'); - } catch (e) { - expect(e.message).to.equal('Invalid registry root key "foo"'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key is not found', () => { - try { - winreglib.list('HKLM\\foo'); - } catch (e) { - expect(e.message).to.equal('Registry key or value not found'); - return; - } - throw new Error('Expected error'); - }); - - it('should retrieve subkeys and values', () => { - const result = winreglib.list('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion'); - - expect(result).to.be.an('object'); - expect(result).to.have.keys('resolvedRoot', 'key', 'subkeys', 'values'); - - expect(result.resolvedRoot).to.equal('HKEY_LOCAL_MACHINE'); - expect(result.key).to.equal('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion'); - - expect(result.subkeys).to.be.an('array'); - for (const key of result.subkeys) { - expect(key).to.be.a('string'); - expect(key).to.not.equal(''); - } - - expect(result.values).to.be.an('array'); - for (const value of result.values) { - expect(value).to.be.a('string'); - expect(value).to.not.equal(''); - } - }); -}); - -describe('watch()', () => { - it('should error if key is not specified', () => { - try { - winreglib.watch(); - } catch (e) { - expect(e.message).to.equal('Expected key to be a non-empty string'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if key does not contain a subkey', () => { - try { - winreglib.watch('HKLM'); - } catch (e) { - expect(e.message).to.equal('Expected key to contain both a root and subkey'); - return; - } - throw new Error('Expected error'); - }); - - it('should error if root key is not valid', () => { - try { - winreglib.watch('foo\\bar'); - } catch (e) { - expect(e.message).to.equal('Invalid registry root key "foo"'); - return; - } - throw new Error('Expected error'); - }); - - it('should watch existing key for new subkey', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib'); - - const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - handle.on('change', evt => { - // console.log('CHANGE!', evt); - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'); - break; - - case 1: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }); - - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 500); - }); - handle.stop(); - } finally { - // also test stop() being called twice - handle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); - - it('should watch existing key for value change', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib'); - - const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - handle.on('change', evt => { - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - reg('delete', 'HKCU\\Software\\winreglib', '/f', '/v', 'foo'); - break; - - case 1: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }); - - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib', '/v', 'foo', '/t', 'REG_SZ', '/d', 'bar'), 500); - }); - } finally { - handle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); - - it('should watch a key that does not exist', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib'); - - const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - handle.on('change', evt => { - // console.log('CHANGE!!', counter, evt); - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - reg('add', 'HKCU\\Software\\winreglib\\foo', '/v', 'bar', '/t', 'REG_SZ', '/d', 'baz'); - break; - - case 1: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - - reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f', '/v', 'bar'); - break; - - case 2: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - - setTimeout(() => reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'), 500); - break; - - case 3: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 500); - break; - - case 4: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }); - - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 500); - }); - } finally { - handle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); - - it('should watch a key whose parent does not exist', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib'); - - const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo\\bar\\baz'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - handle.on('change', evt => { - // console.log('CHANGE!!', counter, evt); - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz', '/v', 'val1', '/t', 'REG_SZ', '/d', 'hello1'); - break; - - case 1: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - - // this next line should not trigger anything - reg('add', 'HKCU\\Software\\winreglib\\foo', '/v', 'val2', '/t', 'REG_SZ', '/d', 'hello2'); - - setTimeout(() => { - reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz', '/v', 'val3', '/t', 'REG_SZ', '/d', 'hello3'); - }, 1000); - break; - - case 2: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - - setTimeout(() => { - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - }, 1000); - break; - - case 3: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }); - - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 500); - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz\\wiz'), 2000); - }); - } finally { - handle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); - - it('should watch a key that gets deleted', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib\\foo'); - - const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - handle.on('change', evt => { - // console.log('CHANGE!', evt); - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }); - - setTimeout(() => reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'), 500); - }); - handle.stop(); - } finally { - // also test stop() being called twice - handle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); - - it('should watch a key whose parent gets deleted', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz'); - - const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo\\bar\\baz'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - handle.on('change', evt => { - // console.log('CHANGE!', evt); - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }); - - setTimeout(() => reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'), 500); - }); - handle.stop(); - } finally { - // also test stop() being called twice - handle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); - - it('should survive the gauntlet', async function () { - this.timeout(15000); - this.slow(14000); - - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - reg('add', 'HKCU\\Software\\winreglib'); - - const winreglibHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib'); - const fooHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo'); - const barHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo\\bar'); - const bazHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo\\bar\\baz'); - - try { - let counter = 0; - - await new Promise((resolve, reject) => { - const fn = evt => { - // console.log('CHANGE!', evt); - try { - expect(evt).to.be.an('object'); - switch (counter++) { - case 0: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - break; - - case 1: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - break; - - case 2: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' - }); - reg('delete', 'HKCU\\Software\\winreglib\\foo\\bar', '/f'); - break; - - case 3: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - break; - - case 4: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' - }); - reg('add', 'HKCU\\Software\\winreglib', '/v', 'foo', '/t', 'REG_SZ', '/d', 'bar'); - break; - - case 5: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\wiz'); - break; - - case 6: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - break; - - case 7: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' - }); - reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz'); - break; - - case 8: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' - }); - break; - - case 9: - expect(evt).to.deep.equal({ - type: 'add', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz', '/v', 'foo', '/t', 'REG_SZ', '/d', 'bar'); - break; - - case 10: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - reg('delete', 'HKCU\\Software\\winreglib', '/f', '/v', 'foo'); - break; - - case 11: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'); - break; - - case 12: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' - }); - break; - - case 13: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' - }); - break; - - case 14: - expect(evt).to.deep.equal({ - type: 'delete', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' - }); - break; - - case 15: - expect(evt).to.deep.equal({ - type: 'change', - key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' - }); - resolve(); - break; - } - } catch (e) { - reject(e); - } - }; - - winreglibHandle.on('change', fn); - fooHandle.on('change', fn); - barHandle.on('change', fn); - bazHandle.on('change', fn); - - setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo\\bar'), 500); - }); - } finally { - winreglibHandle.stop(); - fooHandle.stop(); - barHandle.stop(); - bazHandle.stop(); - reg('delete', 'HKCU\\Software\\winreglib', '/f'); - } - }); -}); diff --git a/test/watch.test.ts b/test/watch.test.ts new file mode 100644 index 0000000..956905b --- /dev/null +++ b/test/watch.test.ts @@ -0,0 +1,592 @@ +import { describe, expect, it } from 'vitest'; +import winreglib from '../src/index.js'; +const { spawnSync } = require('node:child_process'); +import snooplogg from 'snooplogg'; + +const { log } = snooplogg('test:winreglib'); + +const reg = (...args) => { + log(`Executing: reg ${args.join(' ')}`); + spawnSync('reg', args, { stdio: 'ignore' }); +}; + +describe('watch()', () => { + it('should error if key is not specified', () => { + expect(() => { + // biome-ignore lint/suspicious/noExplicitAny: need to test invalid input + winreglib.watch(undefined as any); + }).toThrowError(new TypeError('Expected key to be a non-empty string')); + }); + + it('should error if key does not contain a subkey', () => { + expect(() => { + winreglib.watch('HKLM'); + }).toThrowError( + new TypeError('Expected key to contain both a root and subkey') + ); + }); + + it('should error if root key is not valid', () => { + expect(() => { + winreglib.watch('foo\\bar'); + }).toThrowError(new TypeError('Invalid registry root key "foo"')); + }); + + it( + 'should watch existing key for new subkey', + { timeout: 15000 }, + async () => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib'); + + const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib'); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + handle.on('change', evt => { + // log('CHANGE!', evt); + try { + expect(evt).toBeInstanceOf(Object); + switch (counter++) { + case 0: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' + }); + reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'); + break; + case 1: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }); + setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 250); + }); + + handle.stop(); + } finally { + // also test stop() being called twice + handle.stop(); + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + } + ); + + it( + 'should watch existing key for value change', + { timeout: 15000 }, + async () => { + reg('delete', 'HKCU\\Software\\winreglib2', '/f'); + reg('add', 'HKCU\\Software\\winreglib2'); + + const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib2'); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + handle.on('change', evt => { + // log('CHANGE!', evt); + try { + expect(evt).toBeTypeOf('object'); + switch (counter++) { + case 0: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib2' + }); + reg( + 'delete', + 'HKCU\\Software\\winreglib2', + '/f', + '/v', + 'foo' + ); + break; + case 1: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib2' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }); + setTimeout( + () => + reg( + 'add', + 'HKCU\\Software\\winreglib2', + '/v', + 'foo', + '/t', + 'REG_SZ', + '/d', + 'bar' + ), + 250 + ); + }); + } finally { + handle.stop(); + reg('delete', 'HKCU\\Software\\winreglib2', '/f'); + } + } + ); + + it('should watch a key that does not exist', { timeout: 15000 }, async () => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib'); + + const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo'); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + handle.on('change', evt => { + // console.log('CHANGE!!', counter, evt); + try { + expect(evt).toBeTypeOf('object'); + switch (counter++) { + case 0: + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + reg( + 'add', + 'HKCU\\Software\\winreglib\\foo', + '/v', + 'bar', + '/t', + 'REG_SZ', + '/d', + 'baz' + ); + break; + case 1: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + reg( + 'delete', + 'HKCU\\Software\\winreglib\\foo', + '/f', + '/v', + 'bar' + ); + break; + case 2: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + setTimeout( + () => reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'), + 250 + ); + break; + case 3: + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + setTimeout( + () => reg('add', 'HKCU\\Software\\winreglib\\foo'), + 250 + ); + break; + case 4: + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }); + setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 250); + }); + } finally { + handle.stop(); + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + }); + + it( + 'should watch a key whose parent does not exist', + { timeout: 15000 }, + async () => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib'); + + const handle = winreglib.watch( + 'HKCU\\SOFTWARE\\winreglib\\foo\\bar\\baz' + ); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + handle.on('change', evt => { + // console.log('CHANGE!!', counter, evt); + try { + expect(evt).toBeTypeOf('object'); + switch (counter++) { + case 0: + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + reg( + 'add', + 'HKCU\\Software\\winreglib\\foo\\bar\\baz', + '/v', + 'val1', + '/t', + 'REG_SZ', + '/d', + 'hello1' + ); + break; + case 1: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + // this next line should not trigger anything + reg( + 'add', + 'HKCU\\Software\\winreglib\\foo', + '/v', + 'val2', + '/t', + 'REG_SZ', + '/d', + 'hello2' + ); + setTimeout(() => { + reg( + 'add', + 'HKCU\\Software\\winreglib\\foo\\bar\\baz', + '/v', + 'val3', + '/t', + 'REG_SZ', + '/d', + 'hello3' + ); + }, 250); + break; + case 2: + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + setTimeout(() => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + }, 250); + break; + case 3: + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }); + + setTimeout(() => reg('add', 'HKCU\\Software\\winreglib\\foo'), 250); + setTimeout( + () => reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz\\wiz'), + 250 + ); + }); + } finally { + handle.stop(); + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + } + ); + + it('should watch a key that gets deleted', { timeout: 15000 }, async () => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib\\foo'); + + const handle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo'); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + handle.on('change', evt => { + // console.log('CHANGE!', evt); + try { + expect(evt).toBeTypeOf('object'); + switch (counter++) { + case 0: + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }); + setTimeout( + () => reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'), + 250 + ); + }); + handle.stop(); + } finally { + // also test stop() being called twice + handle.stop(); + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + }); + + it( + 'should watch a key whose parent gets deleted', + { timeout: 15000 }, + async () => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz'); + + const handle = winreglib.watch( + 'HKCU\\SOFTWARE\\winreglib\\foo\\bar\\baz' + ); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + handle.on('change', evt => { + // console.log('CHANGE!', evt); + try { + expect(evt).toBeTypeOf('object'); + switch (counter++) { + case 0: + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }); + setTimeout( + () => reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'), + 250 + ); + }); + handle.stop(); + } finally { + // also test stop() being called twice + handle.stop(); + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + } + ); + + it('should survive the gauntlet', { timeout: 15000 }, async () => { + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + reg('add', 'HKCU\\Software\\winreglib'); + + const winreglibHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib'); + const fooHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo'); + const barHandle = winreglib.watch('HKCU\\SOFTWARE\\winreglib\\foo\\bar'); + const bazHandle = winreglib.watch( + 'HKCU\\SOFTWARE\\winreglib\\foo\\bar\\baz' + ); + + try { + let counter = 0; + await new Promise((resolve, reject) => { + const fn = (evt, handleName) => { + log('CHANGE!', counter, handleName, evt); + try { + expect(evt).toBeTypeOf('object'); + switch (counter++) { + case 0: + expect(handleName).toBe('winreglibHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' + }); + break; + case 1: + expect(handleName).toBe('fooHandle'); + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + break; + case 2: + expect(handleName).toBe('barHandle'); + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' + }); + reg('delete', 'HKCU\\Software\\winreglib\\foo\\bar', '/f'); + break; + case 3: + expect(handleName).toBe('barHandle'); + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' + }); + break; + case 4: + expect(handleName).toBe('fooHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + reg( + 'add', + 'HKCU\\Software\\winreglib', + '/v', + 'foo', + '/t', + 'REG_SZ', + '/d', + 'bar' + ); + break; + case 5: + expect(handleName).toBe('winreglibHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' + }); + reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\wiz'); + break; + case 6: + expect(handleName).toBe('fooHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + break; + case 7: + expect(handleName).toBe('barHandle'); + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' + }); + reg('add', 'HKCU\\Software\\winreglib\\foo\\bar\\baz'); + break; + case 8: + expect(handleName).toBe('barHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' + }); + break; + case 9: + expect(handleName).toBe('bazHandle'); + expect(evt).toMatchObject({ + type: 'add', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + reg( + 'add', + 'HKCU\\Software\\winreglib\\foo\\bar\\baz', + '/v', + 'foo', + '/t', + 'REG_SZ', + '/d', + 'bar' + ); + break; + case 10: + expect(handleName).toBe('bazHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + reg('delete', 'HKCU\\Software\\winreglib', '/f', '/v', 'foo'); + break; + case 11: + expect(handleName).toBe('winreglibHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' + }); + reg('delete', 'HKCU\\Software\\winreglib\\foo', '/f'); + break; + case 12: + expect(handleName).toBe('bazHandle'); + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar\\baz' + }); + break; + case 13: + expect(handleName).toBe('barHandle'); + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo\\bar' + }); + break; + case 14: + expect(handleName).toBe('fooHandle'); + expect(evt).toMatchObject({ + type: 'delete', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib\\foo' + }); + break; + case 15: + expect(handleName).toBe('winreglibHandle'); + expect(evt).toMatchObject({ + type: 'change', + key: 'HKEY_CURRENT_USER\\SOFTWARE\\winreglib' + }); + resolve(); + break; + } + } catch (e) { + reject(e); + } + }; + winreglibHandle.on('change', evt => fn(evt, 'winreglibHandle')); + fooHandle.on('change', evt => fn(evt, 'fooHandle')); + barHandle.on('change', evt => fn(evt, 'barHandle')); + bazHandle.on('change', evt => fn(evt, 'bazHandle')); + setTimeout( + () => reg('add', 'HKCU\\Software\\winreglib\\foo\\bar'), + 250 + ); + }); + } finally { + winreglibHandle.stop(); + fooHandle.stop(); + barHandle.stop(); + bazHandle.stop(); + reg('delete', 'HKCU\\Software\\winreglib', '/f'); + } + }); +}); diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..58fbd1d --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "Bundler", + "rootDir": "./src", + "sourceMap": true + }, + "extends": "./tsconfig.json", + "include": ["./src"] +} diff --git a/tsconfig.check.json b/tsconfig.check.json new file mode 100644 index 0000000..c473fed --- /dev/null +++ b/tsconfig.check.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["./dist"], + "exclude": [] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f17b8a3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "allowJs": true, + "composite": false, + "declaration": false, + "declarationMap": false, + "esModuleInterop": false, + "forceConsistentCasingInFileNames": true, + "inlineSources": false, + "isolatedModules": true, + "lib": ["esnext"], + "module": "esnext", + "moduleResolution": "node", + "noImplicitAny": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "outDir": "./dist", + "preserveWatchOutput": true, + "removeComments": true, + "skipLibCheck": true, + "strict": true, + "sourceMap": false, + "target": "esnext", + "typeRoots": ["./node_modules/@types"], + "types": ["node"] + }, + "include": ["./rollup.config.ts", "./rollup.dts.config.ts", "./src"] +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..bfccd9a --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + coverage: { + include: ['src/**/*.ts'], + reporter: ['html', 'lcov', 'text'] + }, + environment: 'node', + globals: false, + include: ['test/**/*.test.ts'], + poolOptions: { + forks: { + singleFork: true + } + }, + watch: false + } +});