diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 06964de7..00000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -docs -build \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 88931492..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "athom" -} \ No newline at end of file diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 00000000..5b7bfa8d --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,23 @@ +# Categories for the notes GitHub generates when the deploy workflow creates a release. +# The labels are set from the conventional-commit prefix of the pull request title by +# .github/workflows/label-pr.yml. +changelog: + exclude: + labels: + - internal + - release + categories: + - title: Breaking changes + labels: + - breaking + - title: New features + labels: + - feature + - title: Fixes + labels: + - fix + # Titles without a conventional prefix, typically outside contributions. Retitle the pull + # request to move it. + - title: Other changes + labels: + - '*' diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6d375a26..7cbbc379 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,13 +1,14 @@ name: Deploy # About this workflow: -# It is triggered on push events to branches production and testing. Then it performs a checkout of the current repo -# and sets up a node environment (v12). Following, it will run `npm ci` to build the package. Next, it will look at your +# It is triggered on push events to the production branch. Then it performs a checkout of the current repo +# and sets up a node environment (see .nvmrc). Following, it will run `npm ci` to build the package. Next, it will look at your # commit message, if it includes '#patch', '#minor', or '#major' it will bump the package version accordingly. -# Finally, the `npm publish` command will be run, when on branch testing it will run `npm publish --tag beta` to publish -# it under the beta flag on npm. Note: if no '#patch', '#minor', or '#major' flag is present in the latest commit -# AND the package version is not bumped manually the publish step will fail because we can not publish to an existing -# version. +# Finally, the `npm publish` command will be run. Note: if no '#patch', '#minor', or '#major' flag is present in the latest +# commit AND the package version is not bumped manually the publish step will fail because we can not publish to an +# existing version. +# Once npm has accepted the version, a GitHub release with generated notes is created. +# See .github/release.yml for how the notes are grouped. # GitHub repo configuration: # 1. Go to Manage access and add 'Github Actions' team with role: admin. @@ -16,13 +17,12 @@ name: Deploy # Note: make sure to commit package-lock.json, this is needed for `npm ci`. -# Defines the trigger for this action, in general you want it to run when pushing to production | testing. For more +# Defines the trigger for this action, in general you want it to run when pushing to production. For more # information see: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#about-workflow-events) on: push: branches: - production - - testing workflow_dispatch: inputs: versionBumpType: @@ -33,10 +33,10 @@ jobs: deploy_to_npm: name: Version Bump & Deploy to NPM - # Only run this job if initiator is not the Homey Github Actions Bot to prevent loops and check if if a version bump is provided and current branch is production or testing + # Only run this job if initiator is not the Homey Github Actions Bot to prevent loops and check if a version bump is provided and current branch is production if: github.actor != 'homey-bot' - && (github.ref == 'refs/heads/production' || github.ref == 'refs/heads/testing') - && (github.event.inputs.versionBumpType == 'patch' || github.event.inputs.versionBumpType == 'minor' || github.event.inputs.versionBumpType == 'major' || contains(github.event.head_commit.message, '#patch') || contains(github.event.head_commit.message, '#minor') || contains(github.event.head_commit.message, '#major')) + && github.ref == 'refs/heads/production' + && (github.event.inputs.versionBumpType == 'patch' || github.event.inputs.versionBumpType == 'minor' || github.event.inputs.versionBumpType == 'major' || contains(github.event.head_commit.message, '#patch') || contains(github.event.head_commit.message, '#minor') || contains(github.event.head_commit.message, '#major')) runs-on: ubuntu-latest @@ -47,13 +47,14 @@ jobs: id-token: write steps: - # Checks out the current repository. - name: Checkout git repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: # The token below is only necessary if you want to push the version bump to a protected branch token: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }} + # Full history and tags, so the release step can find the previous tag. + fetch-depth: 0 # Set git config to reflect Homey Github Actions Bot user - name: Set up HomeyGithubActionsBot git user @@ -64,16 +65,32 @@ jobs: # Configures a Node.js environment pointed at the public npm registry so # `npm publish` uses OIDC against npmjs.org. - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version-file: .nvmrc + cache: 'npm' registry-url: https://registry.npmjs.org - # Run `npm ci && npm run build` to re-create your local environment (make sure to commit your - package-lock.json!). - - name: Build + # OIDC trusted publishing needs npm 11.5.1 or newer. Node 22 bundles npm 10, + # and setup-node installs whatever npm ships with the Node version. + - name: Upgrade npm for trusted publishing + run: npm install -g npm@^11.5.1 + + # Run `npm ci` to re-create your local environment (make sure to commit your - package-lock.json!). + - name: Install + run: npm ci + + # Nothing below this point runs if the package does not lint, format or test + # cleanly, so nothing reaches npm that was never checked. Ahead of the docs build, + # which is the slowest step here. + - name: Validate run: | - npm ci - npm run build + npm run lint + npm run format:check + npm test + + - name: Build + run: npm run build - name: Version bump patch if: github.event.inputs.versionBumpType == 'patch' || contains(github.event.head_commit.message, '#patch') && !contains(github.event.head_commit.message, '#minor') && !contains(github.event.head_commit.message, '#major') @@ -96,20 +113,33 @@ jobs: git pull git push --follow-tags - # Publish when this action is running on branch production. # No NPM_AUTH_TOKEN: auth is brokered via OIDC against the npm # Trusted Publisher configured on the package on npmjs.com. - name: Publish - if: github.ref == 'refs/heads/production' + run: npm publish --provenance + + # After the publish, and starting from the previous release rather than the previous tag, + # because a publish that fails after the version bump leaves a tag without an npm version + # behind (v2.7.0, v3.1.0). Until the first release exists, the start is the last version npm + # actually has, for the same reason. If this step fails, create the release by hand: a rerun + # would bump again. + - name: Create GitHub release + # Explicit, because only then does Actions add pipefail: without it a failing gh api still + # feeds the Node filter an empty input, and an empty release gets published. + shell: bash + env: + GH_TOKEN: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }} run: | - npm publish --provenance VERSION="$(node -p "require('./package.json').version")" - echo package_version=${VERSION} >> $GITHUB_ENV - - # Publish to beta when this action is running on branch testing. - - name: Publish to beta - if: github.ref == 'refs/heads/testing' - run: | - npm publish --provenance --tag beta - VERSION="$(node -p "require('./package.json').version")@beta" - echo package_version=${VERSION} >> $GITHUB_ENV + TAG="v$VERSION" + if ! PREVIOUS_TAG="$(gh release view --json tagName -q .tagName)"; then + PREVIOUS_TAG="v$(npm view "zigbee-clusters@<$VERSION" version --json \ + | node -p "[].concat(JSON.parse(require('node:fs').readFileSync(0, 'utf8'))).at(-1)")" + fi + # The notes list each pull request title as is. Drop its conventional-commit prefix, which the + # category heading above it already says. + gh api "repos/$GITHUB_REPOSITORY/releases/generate-notes" \ + -f tag_name="$TAG" -f previous_tag_name="$PREVIOUS_TAG" --jq .body \ + | node -e "process.stdout.write(require('node:fs').readFileSync(0, 'utf8').replace(/^\* \w+(\([^)]*\))?!?: (.)/gm, (_, _scope, first) => '* ' + first.toUpperCase()))" \ + > release-notes.md + gh release create "$TAG" --verify-tag --title "$TAG" --notes-file release-notes.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 67806c8b..2b247f14 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,11 +15,9 @@ name: Deploy Documentation To GitHub Pages # Note: make sure to commit package-lock.json, this is needed for `npm ci`. -# Note: add `.github` to .npmignore - on: push: - branches: [ production ] + branches: [production] workflow_dispatch: jobs: @@ -27,22 +25,23 @@ jobs: name: Build & Deploy to GitHub Pages runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - - # Build - - name: Build - run: | - npm ci - npm run build - - # Deploy - - name: Deploy To GitHub Pages - uses: peaceiris/actions-gh-pages@v3.8.0 - with: - personal_token: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }} - publish_dir: ./build \ No newline at end of file + - uses: actions/checkout@v7 + + - name: Setup Node.js + uses: actions/setup-node@v7 + with: + node-version-file: .nvmrc + cache: 'npm' + + # Build + - name: Build + run: | + npm ci + npm run build + + # Deploy + - name: Deploy To GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + personal_token: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }} + publish_dir: ./build diff --git a/.github/workflows/generate-types.yml b/.github/workflows/generate-types.yml index e37e92af..aa17c5a7 100644 --- a/.github/workflows/generate-types.yml +++ b/.github/workflows/generate-types.yml @@ -4,14 +4,13 @@ on: push: branches-ignore: - production - - testing paths: - - "lib/clusters/**/*.js" - - "scripts/generate-types.mts" - - "scripts/template.d.ts.txt" - - "index.js" - - "lib/Cluster.js" - - "lib/constants.js" + - 'lib/clusters/**/*.js' + - 'scripts/generate-types.mts' + - 'scripts/template.d.ts.txt' + - 'index.js' + - 'lib/Cluster.js' + - 'lib/constants.js' workflow_dispatch: jobs: @@ -23,16 +22,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: ref: ${{ github.ref_name }} token: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }} - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version-file: .nvmrc - cache: "npm" + cache: 'npm' - name: Install dependencies run: npm ci diff --git a/.github/workflows/label-pr.yml b/.github/workflows/label-pr.yml new file mode 100644 index 00000000..3123d344 --- /dev/null +++ b/.github/workflows/label-pr.yml @@ -0,0 +1,67 @@ +name: Label pull request + +# Labels each pull request from the conventional-commit prefix of its title, so the release +# notes can sort it (see .github/release.yml). Re-runs when the title or base branch is edited. +# The five labels below follow the title alone: to move a pull request, retitle it. +# +# pull_request_target so pull requests from forks get a token that can label. This is safe +# because the job never checks out or runs code from the pull request. +on: + pull_request_target: + types: [opened, edited, reopened] + +permissions: + pull-requests: write + +# One run at a time per pull request, so two quick edits cannot each add a label the other +# should have removed. +concurrency: + group: label-pr-${{ github.event.pull_request.number }} + +jobs: + label: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v9 + with: + script: | + const MANAGED_LABELS = ['breaking', 'feature', 'fix', 'internal', 'release']; + const INTERNAL_TYPES = ['build', 'chore', 'ci', 'docs', 'refactor', 'style', 'test']; + + function labelFor(title, baseRef) { + if (baseRef === 'production') return 'release'; + const match = /^(\w+)(?:\([^)]*\))?(!)?:/.exec(title); + if (!match) return null; + const [, type, breaking] = match; + if (breaking) return 'breaking'; + if (type === 'feat') return 'feature'; + if (type === 'fix' || type === 'perf') return 'fix'; + if (INTERNAL_TYPES.includes(type)) return 'internal'; + return null; + } + + const { action, changes = {} } = context.payload; + // The label depends on the title and the base branch; other edits change nothing. + if (action === 'edited' && !changes.title && !changes.base) return; + + // The payload is a snapshot from when the event fired. Read the pull request as it is + // now, so labels an earlier run added are seen and the latest title wins. + const { data: pullRequest } = await github.rest.pulls.get({ + ...context.repo, + pull_number: context.payload.pull_request.number, + }); + + // The managed labels are a function of the current title and base only, so whichever + // runs happen to execute, the last one leaves them right. No prefix means none of them. + const wanted = labelFor(pullRequest.title, pullRequest.base.ref); + const current = pullRequest.labels.map(label => label.name); + const issue = { ...context.repo, issue_number: pullRequest.number }; + + for (const name of current) { + if (MANAGED_LABELS.includes(name) && name !== wanted) { + await github.rest.issues.removeLabel({ ...issue, name }); + } + } + if (wanted && !current.includes(wanted)) { + await github.rest.issues.addLabels({ ...issue, labels: [wanted] }); + } diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ea438fc9..a738130f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,17 +20,19 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - # Checks out the current repository. - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 # Configures a Node.js environment. - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v7 with: node-version-file: .nvmrc + cache: 'npm' # Run `npm ci` to re-create your local environment (make sure to commit your package-lock.json!). # Finally run `npm run lint` (make sure you have defined a lint command in package.json e.g. "lint": "eslint ."). - run: npm ci - run: npm run lint + + - run: npm run format:check diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0c345f63..1eb649aa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,12 +22,13 @@ jobs: steps: # Checks out the current repository. - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 # Configures a Node.js environment. - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v7 with: node-version-file: .nvmrc + cache: 'npm' # Run `npm ci` to re-create your local environment (make sure to commit your package-lock.json!). # Finally run `npm test` (make sure you have defined a proper test command in package.json). diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..c18bba7c --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +# Both @athombv packages used here are published to npmjs.org. Without this, a +# machine that points the @athombv scope at GitHub Packages fails to install them. +@athombv:registry=https://registry.npmjs.org/ diff --git a/.nvmrc b/.nvmrc index a45fd52c..2bd5a0a9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24 +22 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..a3ed78cc --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +build +index.d.ts +*.pdf +.claude + +# Literal formatting is the content here, and Prettier mangles the M* emphasis markers. +AGENTS.md diff --git a/.prettierrc b/.prettierrc index 77e64750..24e8f6ce 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,6 +2,5 @@ "semi": true, "trailingComma": "all", "singleQuote": true, - "printWidth": 100, - "plugins": ["prettier-plugin-jsdoc"] + "printWidth": 100 } diff --git a/AGENTS.md b/AGENTS.md index a28a2e6f..56ac6c2c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,16 +5,27 @@ This file provides guidance to AI agents when working with code in this reposito ## Commands ```bash -npm test # Run all tests (mocha) -npm run lint # ESLint (extends athom config) -npm run build # Generate JSDoc documentation +npm test # Run all tests (node:test) +npm run lint # ESLint (flat config in eslint.config.js) +npm run format:check # Prettier check, run in CI next to lint +npm run format:write # Apply Prettier; run before committing +npm run generate-types # Regenerate index.d.ts from the cluster definitions +npm run build # Generate JSDoc documentation into build/ +npm run docs # Build the docs and open them in the browser (macOS `open`) ``` +The docs are a static site that works straight from disk, no server needed. Off macOS, run +`npm run build` and open `build/index.html` in a browser. + Run single test file: ```bash -npx mocha test/onOff.js +node --test test/onOff.js ``` +## Pull Requests and Releases + +Pull request titles use Conventional Commits, `type(scope): Description` with a capital letter after the prefix. The prefix decides where the change lands in the release notes: `feat` under New features, `fix` and `perf` under Fixes, a `!` before the colon under Breaking changes, and `build`, `chore`, `ci`, `docs`, `refactor`, `style` and `test` are left out. Use `feat` or `fix` for anything someone using the library would notice. How a release is cut is described under [Releasing](README.md#releasing). + ## Architecture Zigbee Cluster Library (ZCL) implementation for Node.js, designed for Homey's Zigbee stack. @@ -64,10 +75,16 @@ inputClusters: [0x0006] ### Test Pattern +Tests run on `node:test`, so `describe`, `it` and `mock` are imported, not globals. A +callback-style test takes the test context first: `it('...', function(t, done) { ... })`. +With `function(done)` node:test sees a synchronous test, passes it immediately and never +runs the assertions. + Tests use mock nodes from `test/util/mockNode.js`: **Single node with loopback** (command → same node's BoundCluster): ```javascript +const { describe, it } = require('node:test'); const { createMockNode } = require('./util'); const OnOffCluster = require('../lib/clusters/onOff'); @@ -172,7 +189,8 @@ const COMMANDS = { // --- Client to Server Commands --- // Description from spec. - commandName: { // Mandatory + // Mandatory + commandName: { id: 0x0000, args: { argName: ZCLDataTypes.uint8, @@ -186,7 +204,8 @@ const COMMANDS = { // --- Server to Client Commands --- // Description from spec. - notificationName: { // Optional + // Optional + notificationName: { id: 0x0020, // 32 direction: Cluster.DIRECTION_SERVER_TO_CLIENT, args: { @@ -224,11 +243,13 @@ module.exports = ExampleCluster; 1. **Description placement**: ABOVE the attribute/command 2. **M/O marker placement**: - Single-line: at END of line (`attrName: { ... }, // Mandatory`) - - Multi-line: on OPENING brace (`attrName: { // Mandatory`) + - Multi-line: on its own line ABOVE the key (`// Mandatory` then `attrName: {`), + below the description if there is one. Not on the opening brace: Prettier pulls a + comment there inside the braces, where it reads as if it belongs to `id`. - NEVER on closing brace 3. **Copy exactly**: Text from spec, 1-on-1 4. **Skip if >5 sentences**: Skip and only refer to section in spec -5. **Line wrap**: Respect 100 char limit (ESLint) +5. **Line wrap**: Respect 100 char limit (Prettier `printWidth`); run `npm run format:write` 6. **M/O source for attrs**: Server-side column in spec table 7. **M/O source for cmds**: - Server "receives" → server-side M/O @@ -252,7 +273,7 @@ pirUnoccupiedToOccupiedDelay: { id: 0x0011, type: ZCLDataTypes.uint16 }, // 17, | Field | Format | Notes | |-------|--------|-------| -| `id` | Hex (`0x0000`) | Always 4-digit format (0x0000); add decimal comment if > 9 | +| `id` | Hex (`0x0000`) | Always 4-digit format (0x0000), lowercase digits; add decimal comment if > 9 | | `type` | `ZCLDataTypes.*` | See type reference below | | M/O | Inline comment | `// Mandatory`, `// Optional`, or `// Conditional` | @@ -260,7 +281,7 @@ pirUnoccupiedToOccupiedDelay: { id: 0x0011, type: ZCLDataTypes.uint16 }, // 17, For hex values > 9 (where hex differs from decimal), add decimal in comment: ```javascript -id: 0x000A, // 10 +id: 0x000a, // 10 id: 0x0010, // 16 id: 0x0100, // 256 ``` @@ -271,9 +292,10 @@ id: 0x0000, id: 0x0009, ``` -For multi-line definitions, decimal goes on the `id:` line, M/O on opening brace: +For multi-line definitions, decimal goes on the `id:` line, M/O above the key: ```javascript -operatingMode: { // Optional +// Optional +operatingMode: { id: 0x0025, // 37 type: ZCLDataTypes.enum8({ normal: 0, @@ -300,7 +322,7 @@ attr3: { ... }, | Field | Required | Notes | |-------|----------|-------| -| `id` | Yes | Always 4-digit hex format (0x0000); add decimal comment if > 9 | +| `id` | Yes | Always 4-digit hex format (0x0000), lowercase digits; add decimal comment if > 9 | | `args` | If has params | Object with typed fields | | `response` | If expects response | Has own `id` and `args` | | `encodeMissingFieldsBehavior` | Controls the behavior of missing fields when encoding the struct | Set to `skip` if some fields are optional, omit if all fields are mandatory | @@ -313,7 +335,8 @@ attr3: { ... }, lockDoor: { id: 0x0000, ... }, // Mandatory // --- Server to Client Commands --- -operationEventNotification: { // Optional +// Optional +operationEventNotification: { id: 0x0020, // 32 direction: Cluster.DIRECTION_SERVER_TO_CLIENT, ... diff --git a/README.md b/README.md index c9284e81..38fd07aa 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,12 @@ v2.0.0 - Changed `Cluster.readAttributes` signature, attributes must now be specified as an array of strings. ```js -zclNode.endpoints[1].clusters.basic.readAttributes(["modelId", "manufacturerName"]); +zclNode.endpoints[1].clusters.basic.readAttributes(['modelId', 'manufacturerName']); ``` -## Release +## Changelog -Merge to production and include `#patch`, `#minor` or `#major` in the PR/commit message. Or merge to production and run the "Deploy" workflow and provide a version bump parameter. +What changed in each version is listed in the [GitHub releases](https://github.com/athombv/node-zigbee-clusters/releases). How those notes are put together is described under [Releasing](#releasing). ## About Zigbee Clusters @@ -70,8 +70,8 @@ In order to communicate with a Zigbee node retrieve a `node` instance from `Mana `/drivers/my-driver/device.js` ```js -const Homey = require("homey"); -const { ZCLNode, CLUSTER } = require("zigbee-clusters"); +const Homey = require('homey'); +const { ZCLNode, CLUSTER } = require('zigbee-clusters'); class MyDevice extends Homey.Device { onInit() { @@ -101,7 +101,7 @@ class MyDevice extends Homey.Device { // timeout (10000ms) before the command is considered rejected. // The timeout starts after sending the frame and receiving a low-level ack. timeout: 5000, - } + }, ); }); } @@ -113,8 +113,8 @@ class MyDevice extends Homey.Device { `/drivers/my-driver/device.js` ```js -const Homey = require("homey"); -const { ZCLNode, CLUSTER } = require("zigbee-clusters"); +const Homey = require('homey'); +const { ZCLNode, CLUSTER } = require('zigbee-clusters'); class MyDevice extends Homey.Device { onInit() { @@ -134,10 +134,10 @@ class MyDevice extends Homey.Device { // And listen for incoming attribute reports by binding a listener on the cluster zclNode.endpoints[1].clusters[CLUSTER.COLOR_CONTROL.NAME].on( - "attr.currentSaturation", + 'attr.currentSaturation', (currentSaturation) => { // handle reported attribute value - } + }, ); }); } @@ -181,7 +181,7 @@ class OnOffCluster extends Cluster { } static get NAME() { - return "onOff"; // The cluster name + return 'onOff'; // The cluster name } static get ATTRIBUTES() { @@ -214,7 +214,7 @@ Zigbee nodes can send commands to Homey via bound clusters. This requires a bind `/lib/LevelControlBoundCluster.js` ```js -const { BoundCluster } = require("zigbee-clusters"); +const { BoundCluster } = require('zigbee-clusters'); class LevelControlBoundCluster extends BoundCluster { constructor({ onMove }) { @@ -237,7 +237,7 @@ module.exports = LevelControlBoundCluster; `/drivers/my-driver/device.js` ```js -const LevelControlBoundCluster = require("../../lib/LevelControlBoundCluster"); +const LevelControlBoundCluster = require('../../lib/LevelControlBoundCluster'); // Register the `BoundCluster` implementation with the `ZCLNode` zclNode.endpoints[1].bind( @@ -246,7 +246,7 @@ zclNode.endpoints[1].bind( onMove: (payload) => { // Do something with the received payload }, - }) + }), ); ``` @@ -257,7 +257,7 @@ There are cases where it is required to implement a custom cluster, for example `lib/IkeaSpecificSceneCluster.js` ```js -const { ScenesCluster, ZCLDataTypes } = require("zigbee-clusters"); +const { ScenesCluster, ZCLDataTypes } = require('zigbee-clusters'); class IkeaSpecificSceneCluster extends ScenesCluster { // Here we override the `COMMANDS` getter from the `ScenesClusters` by @@ -299,14 +299,14 @@ module.exports = IkeaSpecificSceneCluster; `/drivers/my-driver/device.js` ```js -const IkeaSpecificSceneCluster = require("../../lib/IkeaSpecificSceneCluster"); +const IkeaSpecificSceneCluster = require('../../lib/IkeaSpecificSceneCluster'); // Important: we have created a new `Cluster` instance which needs to be added before // it becomes available on any `ZCLNode` instance. Cluster.addCluster(IkeaSpecificSceneCluster); // Example invocation of custom cluster command -zclNode.endpoints[1].clusters["scenes"].ikeaSceneMove({ mode: 0, transitionTime: 10 }); +zclNode.endpoints[1].clusters['scenes'].ikeaSceneMove({ mode: 0, transitionTime: 10 }); ``` This also works for `BoundClusters`, if a node sends commands to Homey using a custom cluster it is necessary to implement a custom `BoundCluster` and bind it to the `ZCLNode` instance. For an example check the implementation in the `com.ikea.tradfri` driver [remote_control](https://github.com/athombv/com.ikea.tradfri-example/tree/master/drivers/remote_control/device.js). @@ -323,20 +323,54 @@ To regenerate TypeScript types after modifying cluster definitions: npm run generate-types ``` -This runs `scripts/generate-types.js` which loads all cluster modules and generates typed interfaces. +This runs `scripts/generate-types.mts` which loads all cluster modules and generates typed interfaces. ### Automatic Generation (GitHub Actions) -TypeScript types are automatically regenerated when changes are pushed to the `develop` branch that affect: +TypeScript types are automatically regenerated when a push to any branch other than `production` changes: + - `lib/clusters/**/*.js` - cluster definitions -- `scripts/generate-types.js` - the generator script +- `lib/Cluster.js`, `lib/constants.js` and `index.js` +- `scripts/generate-types.mts` and `scripts/template.d.ts.txt` - the generator and its template -The workflow commits updated types back to `develop` if changes are detected. +The workflow commits updated types back to that branch if changes are detected. ## Contributing Great if you'd like to contribute to this project, a few things to take note of before submitting a PR: -- This project enforces ESLint, validate by running `npm run lint`. -- This project implements a basic test framework based on mocha, see [test](https://github.com/athombv/node-zigbee-clusters/blob/production/test) directory. -- This project uses several [GitHub Action workflows](https://github.com/athombv/node-zigbee-clusters/blob/production/.github/workflows) (e.g. ESLint, running test and versioning/publishing). +- This project enforces ESLint and Prettier: check with `npm run lint` and `npm run format:check`, and fix formatting with `npm run format:write`. +- Tests use the built-in node:test runner, see the [test](https://github.com/athombv/node-zigbee-clusters/blob/production/test) directory. +- Pull request titles follow [Conventional Commits](https://www.conventionalcommits.org/), for example `fix(onOff): Handle a missing attribute`. The title becomes a line in the release notes, so write it for someone using the library. See [Release notes](#release-notes). +- [GitHub Action workflows](https://github.com/athombv/node-zigbee-clusters/blob/production/.github/workflows) run ESLint, Prettier and the tests, and publish releases. + +## Releasing + +Releases are published from the `production` branch by the Deploy workflow (`.github/workflows/deploy.yml`). + +1. Open a pull request from `master` into `production` with `#patch`, `#minor` or `#major` in its title, for example `Merge master into production (#minor)`. +2. Merge it with a merge commit or a squash merge, not a rebase merge. The workflow reads the marker from the commit message that lands on `production`, and only those two carry the pull request title into it. + +The workflow then lints, checks formatting and runs the tests, builds, bumps the version and pushes the version commit and tag, publishes to npm with [trusted publishing](https://docs.npmjs.com/trusted-publishers), and creates a GitHub release. + +Instead of using a marker, you can also start the Deploy workflow by hand on `production` and pass the version bump as input. + +If creating the GitHub release fails after the npm publish, create it by hand. Running the workflow again would bump the version a second time. + +### Release notes + +GitHub generates the notes from the titles of the pull requests merged since the previous release, grouped by label. A workflow sets that label from the title's prefix, so a pull request lands in the right section on its own: + +| Title prefix | Section | +| ----------------------------------------------------------- | ---------------- | +| `feat` | New features | +| `fix`, `perf` | Fixes | +| `!` before the colon, as in `feat!:` | Breaking changes | +| `build`, `chore`, `ci`, `docs`, `refactor`, `style`, `test` | Left out | +| No prefix | Other changes | + +The prefix itself is stripped from each line, and release pull requests into `production` are left out. + +To move a pull request to another section, change its title, also after it was merged: the label follows. To reword a line, edit the release on GitHub after it is published. + +The grouping is configured in `.github/release.yml`, the labeling in `.github/workflows/label-pr.yml`. diff --git a/docs/jsdoc.json b/docs/jsdoc.json index 32fedb29..803baca7 100755 --- a/docs/jsdoc.json +++ b/docs/jsdoc.json @@ -9,10 +9,7 @@ "readme": "./README.md", "destination": "./build" }, - "plugins": [ - "jsdoc-ts-utils", - "plugins/markdown" - ], + "plugins": ["jsdoc-ts-utils", "plugins/markdown"], "templates": { "default": { "outputSourceFiles": false diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..54c72dc5 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,31 @@ +'use strict'; + +const eslint = require('@eslint/js'); +const { defineConfig } = require('eslint/config'); +const globals = require('globals'); + +module.exports = defineConfig( + { + ignores: ['build/**'], + }, + eslint.configs.recommended, + { + languageOptions: { + sourceType: 'commonjs', + globals: { + ...globals.node, + }, + }, + rules: { + curly: ['error', 'multi-line'], + 'no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + }, + }, +); diff --git a/index.d.ts b/index.d.ts index 0947555d..c7b0a2b8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -490,7 +490,12 @@ declare module "zigbee-clusters" { timeout?: number, disableDefaultResponse?: boolean, }, - ): Promise; + ): Promise<{ + status?: types.ZCLEnum8Status, + alarmCode?: number, + clusterId?: number, + timeStamp?: number, + }>; resetAlarmLog( args?: { manufacturerId?: number, @@ -2793,12 +2798,14 @@ declare module "zigbee-clusters" { } /** - * Minimum shape an Endpoint needs from its owner. Endpoint only ever calls `sendFrame`, so a - * plain object is enough - a device serving bound clusters does not need a full ZCLNode, which - * models one remote peer and bakes that peer's address into its own `sendFrame`. + * Minimum shape an Endpoint needs from its owner. Endpoint only needs `sendFrame`, so a plain + * object is enough - a device serving bound clusters does not need a full ZCLNode, which + * models one remote peer and bakes that peer's address into its own `sendFrame`. Without + * `nextSeqNr` the Endpoint keeps its own transaction sequence number counter. */ type EndpointInput = { sendFrame(endpointId: number, clusterId: number, frame: Buffer): Promise; + nextSeqNr?(): number; }; class Endpoint extends EventEmitter { @@ -3013,7 +3020,7 @@ declare module "zigbee-clusters" { static removeCluster(clusterIdOrName: string | number): void; static getCluster(clusterIdOrName: string | number): Cluster; - on>(eventName: `attr.${Event}`, listener: (value: types.AttributesFromDefinition[Event]) => void): this; + on>(eventName: `attr.${Event}`, listener: (value: types.AttributesFromDefinition[Event], meta: types.AttributeReportMeta) => void): this; on = unknown[]>(eventName: string, listener: (...args: Values) => void): this; } @@ -3388,6 +3395,14 @@ declare module "zigbee-clusters" { } } + type AttributeReportMeta = { + /** + * ZCL transaction sequence number of the report frame. It wraps at 256 and some devices + * reuse a fixed value, so only treat equal values as a duplicate within a short time window. + */ + transactionSequenceNumber: number; + }; + type ReadReportingConfigurationResponse = { status: ZCLEnum8Status, direction: 'reported'|'received'; diff --git a/index.js b/index.js index b02760de..048c3315 100644 --- a/index.js +++ b/index.js @@ -39,11 +39,7 @@ function debug(flag = true, namespaces = '*') { _debug.disable(); } -const { - ZCLDataTypes, - ZCLDataType, - ZCLStruct, -} = zclTypes; +const { ZCLDataTypes, ZCLDataType, ZCLStruct } = zclTypes; const { ZIGBEE_PROFILE_ID, ZIGBEE_DEVICE_ID, IAS_ZONE_TYPE } = require('./lib/constants'); diff --git a/lib/BoundCluster.js b/lib/BoundCluster.js index 2f3f59a7..63031bd7 100644 --- a/lib/BoundCluster.js +++ b/lib/BoundCluster.js @@ -25,7 +25,6 @@ debug = debug.extend('bound-cluster'); * zclNode.endpoints[1].bind('onOff', new MyBoundCluster()); */ class BoundCluster { - /** * Create a new BoundCluster instance. */ @@ -52,43 +51,42 @@ class BoundCluster { async readAttributes({ attributes }) { debug(this.logId, 'received read attributes command'); const result = Buffer.alloc(255); - const attributeMap = attributes - .map(aId => { - const attr = this.cluster.attributesById[aId]; - try { - if (!attr) { - throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); - } - const value = this[attr.name]; - if (typeof value === 'undefined') { - throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); - } - attr.type.toBuffer(result, value, 0); + const attributeMap = attributes.map((aId) => { + const attr = this.cluster.attributesById[aId]; + try { + if (!attr) { + throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); + } + const value = this[attr.name]; + if (typeof value === 'undefined') { + throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); + } + attr.type.toBuffer(result, value, 0); + return { + id: aId, + status: 'SUCCESS', + value, + }; + } catch (e) { + // A ZCLError names the status to report for this one attribute. Thrown just above for an + // attribute that does not exist here, but a getter may throw one too - honour that rather + // than flattening it to FAILURE, so an implementation can pick its own per-attribute + // status. + if (e instanceof ZCLError) { + debug(this.logId, 'Attribute rejected:', attr ? attr.name || aId : aId, e.zclStatus); return { id: aId, - status: 'SUCCESS', - value, + status: e.zclStatus, }; - } catch (e) { - // A ZCLError names the status to report for this one attribute. Thrown just above for an - // attribute that does not exist here, but a getter may throw one too - honour that rather - // than flattening it to FAILURE, so an implementation can pick its own per-attribute - // status. - if (e instanceof ZCLError) { - debug(this.logId, 'Attribute rejected:', attr ? attr.name || aId : aId, e.zclStatus); - return { - id: aId, - status: e.zclStatus, - }; - } - debug(this.logId, 'Failed to parse attribute:', attr ? attr.name || aId : aId, e.message); } + debug(this.logId, 'Failed to parse attribute:', attr ? attr.name || aId : aId, e.message); + } - return { - id: aId, - status: 'FAILURE', - }; - }); + return { + id: aId, + status: 'FAILURE', + }; + }); const len = this.cluster.attributeArrayStatusDataType.toBuffer(result, attributeMap, 0); const attributesResult = { attributes: result.slice(0, len) }; @@ -108,49 +106,58 @@ class BoundCluster { debug(this.logId, 'received write attributes command', attributes); attributes = this.cluster.attributeArrayDataType.fromBuffer(attributes, 0); - const attributeMap = attributes - .map(attrValue => { - const attr = this.cluster.attributesById[attrValue.id]; - try { - if (!attr) { - throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); - } - if (typeof attrValue.value === 'undefined') { - throw new Error('not_parsable'); - } - const descriptor = getPropertyDescriptor(this, attr.name); - if (!descriptor) { - // Neither a getter nor a setter: this device does not implement the attribute at all. - throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); - } - if (!descriptor.set) { - throw new ZCLError('READ_ONLY'); - } - - this[attr.name] = attrValue.value; + const attributeMap = attributes.map((attrValue) => { + const attr = this.cluster.attributesById[attrValue.id]; + try { + if (!attr) { + throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); + } + if (typeof attrValue.value === 'undefined') { + throw new Error('not_parsable'); + } + const descriptor = getPropertyDescriptor(this, attr.name); + if (!descriptor) { + // Neither a getter nor a setter: this device does not implement the attribute at all. + throw new ZCLError('UNSUPPORTED_ATTRIBUTE'); + } + if (!descriptor.set) { + throw new ZCLError('READ_ONLY'); + } + + this[attr.name] = attrValue.value; + return { + id: attrValue.id, + status: 'SUCCESS', + }; + } catch (e) { + // As in readAttributes: a ZCLError carries the status for this record, whether it came + // from the checks above or from a setter that wants to reject the write on its own terms. + if (e instanceof ZCLError) { + debug( + this.logId, + 'Rejected write to attribute:', + attr ? attr.name || attrValue.id : attrValue.id, + e.zclStatus, + ); return { id: attrValue.id, - status: 'SUCCESS', + status: e.zclStatus, }; - } catch (e) { - // As in readAttributes: a ZCLError carries the status for this record, whether it came - // from the checks above or from a setter that wants to reject the write on its own terms. - if (e instanceof ZCLError) { - debug(this.logId, 'Rejected write to attribute:', attr ? attr.name || attrValue.id : attrValue.id, e.zclStatus); - return { - id: attrValue.id, - status: e.zclStatus, - }; - } - debug(this.logId, 'Error: failed to parse attribute:', attr ? attr.name || attrValue.id : attrValue.id, e.message); } + debug( + this.logId, + 'Error: failed to parse attribute:', + attr ? attr.name || attrValue.id : attrValue.id, + e.message, + ); + } - return { - id: attrValue.id, - status: 'FAILURE', - }; - }); + return { + id: attrValue.id, + status: 'FAILURE', + }; + }); return { attributes: attributeMap }; } @@ -167,11 +174,12 @@ class BoundCluster { async discoverCommandsReceived({ startValue = 0, maxResults = 250 } = {}) { debug(this.logId, 'received discover commands received command'); - const cmds = [].concat(...Object.values(this.cluster.commandsById)) - .filter(c => !c.global && !c.isResponse && this[c.name]) - .map(c => c.id) + const cmds = [] + .concat(...Object.values(this.cluster.commandsById)) + .filter((c) => !c.global && !c.isResponse && this[c.name]) + .map((c) => c.id) .sort() - .filter(cId => cId >= startValue); + .filter((cId) => cId >= startValue); const result = cmds.slice(0, maxResults); const response = { @@ -194,11 +202,12 @@ class BoundCluster { async discoverCommandsGenerated({ startValue = 0, maxResults = 250 } = {}) { debug(this.logId, 'received discover commands generated command'); - const cmds = [].concat(...Object.values(this.cluster.commandsById)) - .filter(c => !c.global && c.response && this[c.name]) - .map(c => c.response.id) + const cmds = [] + .concat(...Object.values(this.cluster.commandsById)) + .filter((c) => !c.global && c.response && this[c.name]) + .map((c) => c.response.id) .sort() - .filter(cId => cId >= startValue); + .filter((cId) => cId >= startValue); const result = cmds.slice(0, maxResults); const response = { @@ -229,14 +238,18 @@ class BoundCluster { * @param {number} [options.startValue=0] * @param {number} [options.maxResults=250] * @returns {Promise} + * + * TODO: paginate. startValue and maxResults are ignored, so every call answers with all + * attributes and lastResponse true, whatever the device asked for. */ - async discoverAttributes({ startValue = 0, maxResults = 250 } = {}) { - const attributes = Object.values(this.cluster.attributesById) - .filter(attr => attr.type instanceof ZCLDataType && getPropertyDescriptor(this, attr.name)); + async discoverAttributes({ startValue: _startValue = 0, maxResults: _maxResults = 250 } = {}) { + const attributes = Object.values(this.cluster.attributesById).filter( + (attr) => attr.type instanceof ZCLDataType && getPropertyDescriptor(this, attr.name), + ); const response = { lastResponse: true, - attributes: attributes.map(a => ({ id: a.id, dataTypeId: a.type.id })), + attributes: attributes.map((a) => ({ id: a.id, dataTypeId: a.type.id })), }; debug(this.logId, 'received discover attributes command, response:', response); return response; @@ -263,17 +276,24 @@ class BoundCluster { * @param {number} [options.startValue=0] * @param {number} [options.maxResults=250] * @returns {Promise} + * + * TODO: paginate. startValue and maxResults are ignored, so every call answers with all + * attributes and lastResponse true, whatever the device asked for. */ - async discoverAttributesExtended({ startValue = 0, maxResults = 250 } = {}) { - const attributes = Object.values(this.cluster.attributesById) - .filter(attr => attr.type instanceof ZCLDataType && getPropertyDescriptor(this, attr.name)); + async discoverAttributesExtended({ + startValue: _startValue = 0, + maxResults: _maxResults = 250, + } = {}) { + const attributes = Object.values(this.cluster.attributesById).filter( + (attr) => attr.type instanceof ZCLDataType && getPropertyDescriptor(this, attr.name), + ); let { REPORTABLE_ATTRIBUTES } = this; if (!Array.isArray(REPORTABLE_ATTRIBUTES)) REPORTABLE_ATTRIBUTES = []; const response = { lastResponse: true, - attributes: attributes.map(a => { + attributes: attributes.map((a) => { const acl = []; const prop = getPropertyDescriptor(this, a.name); @@ -309,11 +329,14 @@ class BoundCluster { async handleFrame(frame, meta, rawFrame) { const commands = this.cluster.commandsById[frame.cmdId] || []; - let filteredCommands = commands - .filter(cmd => frame.frameControl.clusterSpecific === !cmd.global - && (cmd.global || frame.frameControl.manufacturerSpecific === !!cmd.manufacturerId) - && (cmd.global || !frame.frameControl.manufacturerSpecific - || frame.manufacturerId === cmd.manufacturerId)); + let filteredCommands = commands.filter( + (cmd) => + frame.frameControl.clusterSpecific === !cmd.global && + (cmd.global || frame.frameControl.manufacturerSpecific === !!cmd.manufacturerId) && + (cmd.global || + !frame.frameControl.manufacturerSpecific || + frame.manufacturerId === cmd.manufacturerId), + ); // Try to filter based on frame direction, note: this is optional as a cluster command // does not always have a 'direction' property. The filter ensure that multiple commands @@ -321,13 +344,15 @@ class BoundCluster { // to both command definitions (see iasZone.js as an example). Cluster.js only receives // frames with directionToClient=true. BoundCluster.js receives frames with // directionToClient=false. - filteredCommands = filteredCommands.filter(command => { + filteredCommands = filteredCommands.filter((command) => { // Only filter commands that have a direction string property if (typeof command.direction === 'string') { // Filter out commands marked as DIRECTION_SERVER_TO_CLIENT when // frameControl.directionToClient = false - if (frame.frameControl.directionToClient === false - && command.direction === Cluster.DIRECTION_SERVER_TO_CLIENT) { + if ( + frame.frameControl.directionToClient === false && + command.direction === Cluster.DIRECTION_SERVER_TO_CLIENT + ) { return false; } } @@ -339,34 +364,30 @@ class BoundCluster { .pop(); if (command) { - const args = command.args - ? command.args.fromBuffer(frame.data, 0) - : undefined; + const args = command.args ? command.args.fromBuffer(frame.data, 0) : undefined; if (this[command.name]) { debug(this.logId, 'received command', command.name, args); const result = await this[command.name](args, meta, frame, rawFrame); if (command.response && command.response.args) { - // eslint-disable-next-line new-cap return [command.response.id, new command.response.args(result), command.response]; } - // eslint-disable-next-line consistent-return return; } } - throw new Error(`unknown_command_received:${(command || {}).name || frame.cmdId}`); + throw new ZCLError('UNSUP_CLUSTER_COMMAND'); } // TODO: implement when needed - async writeAttributesAtomic(args) { + async writeAttributesAtomic(_args) { throw new Error('not_implemented'); // TODO: actually make atomic, capture current state of attrs, exec and restore upon failure // return writeAttributesAtomic(args); } // TODO: implement when needed - async writeAttributesNoResponse(args) { + async writeAttributesNoResponse(_args) { throw new Error('not_implemented'); // TODO: actually disable response // return writeAttributesAtomic(args); @@ -396,7 +417,7 @@ class BoundCluster { // TODO: implement when needed async readReportingConfiguration({ - attributes = { + attributes: _attributes = { // direction, // attributeId, }, @@ -407,10 +428,12 @@ class BoundCluster { // TODO: implement when needed async readAttributesStructured({ - attributes = [{ - // attributeId, - // indexPath, - }], + attributes: _attributes = [ + { + // attributeId, + // indexPath, + }, + ], }) { throw new Error('not_implemented'); // return { attributes }; @@ -418,17 +441,18 @@ class BoundCluster { // TODO: implement when needed async writeAttributesStructured({ - attributes = [{ - // attributeId, - // indexPath, - // dataTypeId, - // value, - }], + attributes: _attributes = [ + { + // attributeId, + // indexPath, + // dataTypeId, + // value, + }, + ], }) { throw new Error('not_implemented'); // return { attributes }; } - } module.exports = BoundCluster; diff --git a/lib/Cluster.js b/lib/Cluster.js index e66f7dfb..371c65d2 100644 --- a/lib/Cluster.js +++ b/lib/Cluster.js @@ -1,14 +1,17 @@ 'use strict'; -const EventEmitter = require('events'); +const EventEmitter = require('node:events'); let { debug } = require('./util'); -const { getLogId } = require('./util'); +const { getLogId, ZCLError } = require('./util'); debug = debug.extend('cluster'); const { - ZCLStandardHeader, ZCLMfgSpecificHeader, ZCLAttributeDataRecord, ZCLConfigureReportingRecords, + ZCLStandardHeader, + ZCLMfgSpecificHeader, + ZCLAttributeDataRecord, + ZCLConfigureReportingRecords, } = require('./zclFrames'); const { ZCLStruct, ZCLDataTypes } = require('./zclTypes'); @@ -46,10 +49,12 @@ const GLOBAL_COMMANDS = { response: { id: 0x04, args: { - attributes: ZCLDataTypes.Array0(ZCLStruct('AttributeResponse', { - status: ZCLDataTypes.enum8Status, - id: ZCLDataTypes.uint16, - })), + attributes: ZCLDataTypes.Array0( + ZCLStruct('AttributeResponse', { + status: ZCLDataTypes.enum8Status, + id: ZCLDataTypes.uint16, + }), + ), }, }, global: true, @@ -63,10 +68,12 @@ const GLOBAL_COMMANDS = { response: { id: 0x04, args: { - attributes: ZCLDataTypes.Array0(ZCLStruct('AttributeResponse', { - status: ZCLDataTypes.enum8Status, - id: ZCLDataTypes.uint16, - })), + attributes: ZCLDataTypes.Array0( + ZCLStruct('AttributeResponse', { + status: ZCLDataTypes.enum8Status, + id: ZCLDataTypes.uint16, + }), + ), }, }, global: true, @@ -88,14 +95,16 @@ const GLOBAL_COMMANDS = { response: { id: 0x07, args: { - reports: ZCLDataTypes.Array0(ZCLStruct('ConfigureReportingResponse', { - status: ZCLDataTypes.enum8Status, - direction: ZCLDataTypes.enum8({ - reported: 0, - received: 1, + reports: ZCLDataTypes.Array0( + ZCLStruct('ConfigureReportingResponse', { + status: ZCLDataTypes.enum8Status, + direction: ZCLDataTypes.enum8({ + reported: 0, + received: 1, + }), + attributeId: ZCLDataTypes.uint16, }), - attributeId: ZCLDataTypes.uint16, - })), + ), }, }, global: true, @@ -104,13 +113,15 @@ const GLOBAL_COMMANDS = { readReportingConfiguration: { id: 0x08, args: { - attributes: ZCLDataTypes.Array0(ZCLStruct('ReadReportingConfiguration', { - direction: ZCLDataTypes.enum8({ - reported: 0, - received: 1, + attributes: ZCLDataTypes.Array0( + ZCLStruct('ReadReportingConfiguration', { + direction: ZCLDataTypes.enum8({ + reported: 0, + received: 1, + }), + attributeId: ZCLDataTypes.uint16, }), - attributeId: ZCLDataTypes.uint16, - })), + ), }, response: { id: 0x09, @@ -122,7 +133,7 @@ const GLOBAL_COMMANDS = { }, reportAttributes: { - id: 0x0A, + id: 0x0a, args: { attributes: ZCLDataTypes.buffer, }, @@ -130,7 +141,7 @@ const GLOBAL_COMMANDS = { }, defaultResponse: { - id: 0x0B, + id: 0x0b, args: { cmdId: ZCLDataTypes.uint8, status: ZCLDataTypes.enum8Status, @@ -139,31 +150,35 @@ const GLOBAL_COMMANDS = { }, discoverAttributes: { - id: 0x0C, + id: 0x0c, args: { startValue: ZCLDataTypes.uint16, maxResults: ZCLDataTypes.uint8, }, response: { - id: 0x0D, + id: 0x0d, args: { lastResponse: ZCLDataTypes.bool, - attributes: ZCLDataTypes.Array0(ZCLStruct('DiscoveredAttribute', { - id: ZCLDataTypes.uint16, - dataTypeId: ZCLDataTypes.uint8, - })), + attributes: ZCLDataTypes.Array0( + ZCLStruct('DiscoveredAttribute', { + id: ZCLDataTypes.uint16, + dataTypeId: ZCLDataTypes.uint8, + }), + ), }, }, global: true, }, readAttributesStructured: { - id: 0x0E, + id: 0x0e, args: { - attributes: ZCLDataTypes.Array0(ZCLStruct('AttributeSelector', { - attributeId: ZCLDataTypes.uint16, - indexPath: ZCLDataTypes.Array8(ZCLDataTypes.uint16), - })), + attributes: ZCLDataTypes.Array0( + ZCLStruct('AttributeSelector', { + attributeId: ZCLDataTypes.uint16, + indexPath: ZCLDataTypes.Array8(ZCLDataTypes.uint16), + }), + ), }, response: { id: 0x01, @@ -175,14 +190,16 @@ const GLOBAL_COMMANDS = { }, writeAttributesStructured: { - id: 0x0F, + id: 0x0f, args: { - attributes: ZCLDataTypes.Array0(ZCLStruct('AttributeSelector', { - attributeId: ZCLDataTypes.uint16, - indexPath: ZCLDataTypes.Array8(ZCLDataTypes.uint16), - dataTypeId: ZCLDataTypes.uint8, - value: ZCLDataTypes.buffer, - })), + attributes: ZCLDataTypes.Array0( + ZCLStruct('AttributeSelector', { + attributeId: ZCLDataTypes.uint16, + indexPath: ZCLDataTypes.Array8(ZCLDataTypes.uint16), + dataTypeId: ZCLDataTypes.uint8, + value: ZCLDataTypes.buffer, + }), + ), }, response: { id: 0x10, @@ -235,11 +252,13 @@ const GLOBAL_COMMANDS = { id: 0x16, args: { lastResponse: ZCLDataTypes.bool, - attributes: ZCLDataTypes.Array0(ZCLStruct('DiscoveredAttributeExtended', { - id: ZCLDataTypes.uint16, - dataTypeId: ZCLDataTypes.uint8, - acl: ZCLDataTypes.map8('readable', 'writable', 'reportable'), - })), + attributes: ZCLDataTypes.Array0( + ZCLStruct('DiscoveredAttributeExtended', { + id: ZCLDataTypes.uint16, + dataTypeId: ZCLDataTypes.uint8, + acl: ZCLDataTypes.map8('readable', 'writable', 'reportable'), + }), + ), }, }, global: true, @@ -250,7 +269,6 @@ const GLOBAL_COMMANDS = { * The base cluster class every other cluster implementation must extend from. */ class Cluster extends EventEmitter { - /** * Create a new cluster instance. * @param {Endpoint} endpoint - A node {@link Endpoint} instance @@ -259,7 +277,6 @@ class Cluster extends EventEmitter { super(); this._endpoint = endpoint; - this._nextTrxSeqNr = 0; this.name = this.constructor.NAME; this._trxHandlers = {}; } @@ -348,16 +365,23 @@ class Cluster extends EventEmitter { * @returns {Promise} */ async discoverCommandsGenerated({ startValue = 0, maxResults = 250 } = {}, opts) { - const { commandIds } = await super.discoverCommandsGenerated({ - startValue, - maxResults, - }, opts); + const { commandIds } = await super.discoverCommandsGenerated( + { + startValue, + maxResults, + }, + opts, + ); - const res = commandIds.map(cId => ((this.constructor.commandsById[cId] || []) - .filter(c => !c.global) - .sort((a, b) => (a.isResponse ? 1 : 0) - (b.isResponse ? 1 : 0)) // TODO - .pop() || {}) - .name || cId); + const res = commandIds.map( + (cId) => + ( + (this.constructor.commandsById[cId] || []) + .filter((c) => !c.global) + .sort((a, b) => (a.isResponse ? 1 : 0) - (b.isResponse ? 1 : 0)) // TODO + .pop() || {} + ).name || cId, + ); debug(this.logId, 'discoverCommandsGenerated', res); return res; @@ -385,16 +409,23 @@ class Cluster extends EventEmitter { * @returns {Promise} */ async discoverCommandsReceived({ startValue = 0, maxResults = 255 } = {}, opts) { - const { commandIds } = await super.discoverCommandsReceived({ - startValue, - maxResults, - }, opts); + const { commandIds } = await super.discoverCommandsReceived( + { + startValue, + maxResults, + }, + opts, + ); - const res = commandIds.map(cId => ((this.constructor.commandsById[cId] || []) - .filter(c => !c.global) - .sort((a, b) => (a.isResponse ? 0 : 1) - (b.isResponse ? 0 : 1)) // TODO - .pop() || {}) - .name || cId); + const res = commandIds.map( + (cId) => + ( + (this.constructor.commandsById[cId] || []) + .filter((c) => !c.global) + .sort((a, b) => (a.isResponse ? 0 : 1) - (b.isResponse ? 0 : 1)) // TODO + .pop() || {} + ).name || cId, + ); debug(this.logId, 'discoverCommandsReceived', res); return res; @@ -411,7 +442,9 @@ class Cluster extends EventEmitter { */ async readAttributes(attributes, opts) { if (attributes instanceof Array === false) { - throw new Error('Expected attributes array, as of zigbee-clusters@2.0.0 call readAttributes([\'myAttr\'])'); + throw new Error( + "Expected attributes array, as of zigbee-clusters@2.0.0 call readAttributes(['myAttr'])", + ); } if (!attributes.length) { @@ -423,8 +456,10 @@ class Cluster extends EventEmitter { const attrIds = new Set(); for (const attr of attributes) { if (typeof attr === 'number') { - if (!Number.isInteger(attr) || attr < 0 || attr > 0xFFFF) { - throw new TypeError(`${attr} is not a valid numeric attribute ID for ${this.name}, must be an integer between 0 and 0xFFFF`); + if (!Number.isInteger(attr) || attr < 0 || attr > 0xffff) { + throw new TypeError( + `${attr} is not a valid numeric attribute ID for ${this.name}, must be an integer between 0 and 0xFFFF`, + ); } numericIds.add(attr); if (idToName[attr] === undefined) idToName[attr] = attr; @@ -441,19 +476,27 @@ class Cluster extends EventEmitter { while (attrIds.size) { // Check if command should get manufacturerSpecific flag const manufacturerId = this._checkForManufacturerSpecificAttributes(Array.from(attrIds)); - debug(this.logId, 'read attributes', [...attrIds], manufacturerId ? `manufacturer specific id ${manufacturerId}` : ''); + debug( + this.logId, + 'read attributes', + [...attrIds], + manufacturerId ? `manufacturer specific id ${manufacturerId}` : '', + ); - const response = await super.readAttributes({ - attributes: [...attrIds], - manufacturerId, - }, opts); + const response = await super.readAttributes( + { + attributes: [...attrIds], + manufacturerId, + }, + opts, + ); debug(this.logId, 'read attributes result', response); const { attributeArrayStatusDataType } = this.constructor; const result = attributeArrayStatusDataType.fromBuffer(response.attributes, 0); if (!result.length) break; - result.forEach(a => { + result.forEach((a) => { attrIds.delete(a.id); if (a.status === 'SUCCESS') { resultObj[idToName[a.id]] = a.value; @@ -477,7 +520,7 @@ class Cluster extends EventEmitter { * @returns {Promise<*|{attributes: *}>} */ async writeAttributes(attributes = {}, opts) { - const arr = Object.keys(attributes).map(n => { + const arr = Object.keys(attributes).map((n) => { const attr = this.constructor.attributes[n]; if (!attr) { throw new TypeError(`${n} is not a valid attribute of ${this.name}`); @@ -490,13 +533,18 @@ class Cluster extends EventEmitter { // Check if command should get manufacturerSpecific flag const manufacturerId = this._checkForManufacturerSpecificAttributes( - Object.keys(attributes).map(n => this.constructor.attributes[n].id), + Object.keys(attributes).map((n) => this.constructor.attributes[n].id), ); let data = Buffer.alloc(1024); data = data.slice(0, this.constructor.attributeArrayDataType.toBuffer(data, arr, 0)); - debug(this.logId, 'write attributes', attributes, manufacturerId ? `manufacturer specific id ${manufacturerId}` : ''); + debug( + this.logId, + 'write attributes', + attributes, + manufacturerId ? `manufacturer specific id ${manufacturerId}` : '', + ); return super.writeAttributes({ attributes: data, manufacturerId }, opts); } @@ -512,7 +560,6 @@ class Cluster extends EventEmitter { */ async configureReporting(attributes = {}, opts) { const req = []; - // eslint-disable-next-line guard-for-in,no-restricted-syntax for (const attributeName in attributes) { const attr = this.constructor.attributes[attributeName]; if (!attr) throw new TypeError(`${attributeName} Does not exist (${this.constructor.name})`); @@ -542,10 +589,15 @@ class Cluster extends EventEmitter { if (req.length) { // Check if command should get manufacturerSpecific flag const manufacturerId = this._checkForManufacturerSpecificAttributes( - Object.keys(attributes).map(n => this.constructor.attributes[n].id), + Object.keys(attributes).map((n) => this.constructor.attributes[n].id), ); - debug(this.logId, 'configure reporting', req, manufacturerId ? `manufacturer specific id ${manufacturerId}` : ''); + debug( + this.logId, + 'configure reporting', + req, + manufacturerId ? `manufacturer specific id ${manufacturerId}` : '', + ); const { reports } = await super.configureReporting({ reports: req, manufacturerId }, opts); @@ -611,22 +663,29 @@ class Cluster extends EventEmitter { // Check if command should get manufacturerSpecific flag const manufacturerId = this._checkForManufacturerSpecificAttributes( - attributes - .map(attributeNameOrId => { - if (typeof attributeNameOrId === 'number') return attributeNameOrId; - return this.constructor.attributes[attributeNameOrId].id; - }), + attributes.map((attributeNameOrId) => { + if (typeof attributeNameOrId === 'number') return attributeNameOrId; + return this.constructor.attributes[attributeNameOrId].id; + }), ); - debug(this.logId, 'read reporting configuration', req, manufacturerId ? `manufacturer specific id ${manufacturerId}` : ''); + debug( + this.logId, + 'read reporting configuration', + req, + manufacturerId ? `manufacturer specific id ${manufacturerId}` : '', + ); // If a request has been constructed execute it if (req.length) { // Perform request, it returns a buffer that needs to be parsed - const { reports } = await super.readReportingConfiguration({ - attributes: req, - manufacturerId, - }, opts); + const { reports } = await super.readReportingConfiguration( + { + attributes: req, + manufacturerId, + }, + opts, + ); debug(this.logId, 'read reporting configuration result', reports); // Return the parsed reports @@ -656,17 +715,22 @@ class Cluster extends EventEmitter { * is implemented in zigbee-clusters or not). */ async discoverAttributes(opts) { - const { attributes } = await super.discoverAttributes({ - startValue: 0, - maxResults: 255, - }, opts); + const { attributes } = await super.discoverAttributes( + { + startValue: 0, + maxResults: 255, + }, + opts, + ); const result = []; for (const attr of attributes) { // Push the name if attribute is implemented in zigbee-clusters otherwise push attribute id - result.push(this.constructor.attributesById[attr.id] - ? this.constructor.attributesById[attr.id].name - : attr.id); + result.push( + this.constructor.attributesById[attr.id] + ? this.constructor.attributesById[attr.id].name + : attr.id, + ); } debug(this.logId, 'discover attributes', result); return result; @@ -695,10 +759,13 @@ class Cluster extends EventEmitter { * attribute is implemented in zigbee-clusters. */ async discoverAttributesExtended(opts) { - const { attributes } = await super.discoverAttributesExtended({ - startValue: 0, - maxResults: 250, - }, opts); + const { attributes } = await super.discoverAttributesExtended( + { + startValue: 0, + maxResults: 250, + }, + opts, + ); const result = []; for (const attr of attributes) { @@ -743,10 +810,14 @@ class Cluster extends EventEmitter { // Filter commands of this cluster based on cluster specific vs global, // and manufacturer specific vs not manufacturer specific. - let filteredCommands = commands.filter(cmd => frame.frameControl.clusterSpecific === !cmd.global - && (cmd.global || frame.frameControl.manufacturerSpecific === !!cmd.manufacturerId) - && (cmd.global || !frame.frameControl.manufacturerSpecific - || frame.manufacturerId === cmd.manufacturerId)); + let filteredCommands = commands.filter( + (cmd) => + frame.frameControl.clusterSpecific === !cmd.global && + (cmd.global || frame.frameControl.manufacturerSpecific === !!cmd.manufacturerId) && + (cmd.global || + !frame.frameControl.manufacturerSpecific || + frame.manufacturerId === cmd.manufacturerId), + ); // Try to filter based on frame direction, note: this is optional as a cluster command // does not always have a 'direction' property. The filter ensure that multiple commands @@ -754,13 +825,15 @@ class Cluster extends EventEmitter { // to both command definitions (see iasZone.js as an example). Cluster.js only receives // frames with directionToClient=true. BoundCluster.js receives frames with // directionToClient=false. - filteredCommands = filteredCommands.filter(command => { + filteredCommands = filteredCommands.filter((command) => { // Only filter commands that have a direction string property if (typeof command.direction === 'string') { // Filter out commands marked as DIRECTION_CLIENT_TO_SERVER when // frameControl.directionToClient = true - if (frame.frameControl.directionToClient - && command.direction === Cluster.DIRECTION_CLIENT_TO_SERVER) { + if ( + frame.frameControl.directionToClient && + command.direction === Cluster.DIRECTION_CLIENT_TO_SERVER + ) { return false; } } @@ -776,29 +849,54 @@ class Cluster extends EventEmitter { const handlerName = `on${command.name.charAt(0).toUpperCase()}${command.name.slice(1)}`; // Parse the command arguments - const args = command.args - ? command.args.fromBuffer(frame.data, 0) - : undefined; + const args = command.args ? command.args.fromBuffer(frame.data, 0) : undefined; debug(this.logId, 'received frame', command.name, args); + // A matching TSN alone is not enough: devices number their own frames (e.g. attribute + // reports) from their own counter, so also require a response to the sent command. + const pendingTrx = this._trxHandlers[frame.trxSequenceNumber]; + let isTrxResponse = false; + if (pendingTrx) { + const isDefaultResponseToCommand = + command.name === 'defaultResponse' && args.cmdId === pendingTrx.cmdId; + + let isReply; + if (pendingTrx.responseCmdId === undefined) { + // No declared response (e.g. app-defined Tuya datapoints): any cluster-specific reply + isReply = !pendingTrx.global && frame.frameControl.clusterSpecific; + } else { + const isSameFrameType = frame.frameControl.clusterSpecific === !pendingTrx.global; + isReply = frame.cmdId === pendingTrx.responseCmdId && isSameFrameType; + } + + isTrxResponse = isReply || isDefaultResponseToCommand; + } + if (pendingTrx && !isTrxResponse) { + debug( + this.logId, + 'frame with pending trx', + frame.trxSequenceNumber, + 'is not its response:', + command.name, + ); + } + // Invoke the right handler - const handler = this._trxHandlers[frame.trxSequenceNumber] || this[handlerName]; - delete this._trxHandlers[frame.trxSequenceNumber]; + const handler = isTrxResponse ? pendingTrx.handle : this[handlerName]; if (handler) { const response = await handler.call(this, args, meta, frame, rawFrame); if (command.response && command.response.args) { - // eslint-disable-next-line new-cap return [command.response.id, new command.response.args(response), command.response]; } - // eslint-disable-next-line consistent-return return; } } debug(this.logId, 'unknown command received:', frame, meta); - throw new Error('unknown_command_received'); + // ZCL R8 2.5.12.2: UNSUP_COMMAND (0x81, UNSUP_CLUSTER_COMMAND here) + throw new ZCLError('UNSUP_CLUSTER_COMMAND'); } /** @@ -829,14 +927,19 @@ class Cluster extends EventEmitter { /** * Message handler which is called from `handleFrame` when the incoming frame is a attribute - * report. This handler will emit the received attribute properties. + * report. This handler will emit the received attribute properties, together with the + * transaction sequence number of the report frame. * @param {object} attributes - The received report object. + * @param {object} meta - The meta data of the received frame. + * @param {object} frame - The parsed ZCL frame. * @returns {Promise} * @private */ - async onReportAttributes({ attributes } = {}) { + async onReportAttributes({ attributes } = {}, meta, frame) { attributes = this.constructor.attributeArrayDataType.fromBuffer(attributes, 0); - attributes.forEach(attr => this.emit(`attr.${attr.name}`, attr.value)); + // Only expose fields chosen here, not the stack's frame meta + const reportMeta = { transactionSequenceNumber: frame.trxSequenceNumber }; + attributes.forEach((attr) => this.emit(`attr.${attr.name}`, attr.value, reportMeta)); } /** @@ -848,11 +951,12 @@ class Cluster extends EventEmitter { * @private */ async onDiscoverCommandsGenerated({ startValue = 0, maxResults = 250 } = {}) { - const cmds = [].concat(...Object.values(this.constructor.commandsById)) - .filter(c => !c.global && !c.isResponse && this[c.name]) - .map(c => c.id) + const cmds = [] + .concat(...Object.values(this.constructor.commandsById)) + .filter((c) => !c.global && !c.isResponse && this[c.name]) + .map((c) => c.id) .sort() - .filter(cId => cId >= startValue); + .filter((cId) => cId >= startValue); const result = cmds.slice(0, maxResults); debug(this.logId, 'onDiscoverCommandsGenerated', { @@ -875,12 +979,17 @@ class Cluster extends EventEmitter { * @private */ async onDiscoverCommandsReceived({ startValue = 0, maxResults = 250 } = {}) { - const cmds = [].concat(...Object.values(this.constructor.commandsById)) - .filter(c => !c.global && c.response - && (this[c.name] || this[`on${c.name.charAt(0).toUpperCase()}${c.name.slice(1)}`])) - .map(c => c.response.id) + const cmds = [] + .concat(...Object.values(this.constructor.commandsById)) + .filter( + (c) => + !c.global && + c.response && + (this[c.name] || this[`on${c.name.charAt(0).toUpperCase()}${c.name.slice(1)}`]), + ) + .map((c) => c.response.id) .sort() - .filter(cId => cId >= startValue); + .filter((cId) => cId >= startValue); const result = cmds.slice(0, maxResults); debug(this.logId, 'onDiscoverCommandsReceived', { @@ -964,7 +1073,6 @@ class Cluster extends EventEmitter { */ static removeCluster(clusterIdOrName) { if (this.clusters[clusterIdOrName]) { - // eslint-disable-next-line no-shadow const Cluster = this.clusters[clusterIdOrName]; delete this.clusters[Cluster.NAME]; delete this.clusters[Cluster.ID]; @@ -986,8 +1094,7 @@ class Cluster extends EventEmitter { * @private */ nextSeqNr() { - this._nextTrxSeqNr = (this._nextTrxSeqNr + 1) % 256; - return this._nextTrxSeqNr; + return this._endpoint.nextSeqNr(); } // / START STATIC METHODS @@ -1063,7 +1170,6 @@ class Cluster extends EventEmitter { return r; }, {}); - // eslint-disable-next-line guard-for-in,no-restricted-syntax for (const cmdName in commands) { Object.defineProperty(proto, cmdName, { value: { @@ -1149,10 +1255,19 @@ class Cluster extends EventEmitter { rejectAwaitResponse = reject; resolveAwaitResponse = resolve; - this._trxHandlers[payload.trxSequenceNumber] = async frame => { - delete this._trxHandlers[payload.trxSequenceNumber]; - if (awaitResponseTimeout) clearTimeout(awaitResponseTimeout); - resolveAwaitResponse(frame); + this._trxHandlers[payload.trxSequenceNumber] = { + // Lets handleFrame accept only a response to this command + cmdId: cmd.id, + // A declared response without id reuses the command id (see _addPrototypeMethods) + responseCmdId: + cmd.response && + (typeof cmd.response.id === 'number' ? cmd.response.id : cmd.id), + global: !!cmd.global, + handle: async (frame) => { + delete this._trxHandlers[payload.trxSequenceNumber]; + if (awaitResponseTimeout) clearTimeout(awaitResponseTimeout); + resolveAwaitResponse(frame); + }, }; }), @@ -1171,7 +1286,10 @@ class Cluster extends EventEmitter { rejectAwaitResponse(new Error('Timeout: Expected Response')); }, responseTimeout); }) - .catch(err => { + .catch((err) => { + // The stack can report a send failure (e.g. no APS ACK in time) while the device + // already answered; that response proves delivery, so don't fail the command. + if (this._trxHandlers[payload.trxSequenceNumber] == null) return; delete this._trxHandlers[payload.trxSequenceNumber]; if (awaitResponseTimeout) clearTimeout(awaitResponseTimeout); rejectAwaitResponse(err); @@ -1183,7 +1301,6 @@ class Cluster extends EventEmitter { if (response.status !== 'SUCCESS') { throw new Error(response.status); } - // eslint-disable-next-line consistent-return return; } @@ -1216,20 +1333,25 @@ class Cluster extends EventEmitter { // Do not allow different manufacturer ids in one command if (new Set(manufacturerIds).size > 1) { - throw new Error('Error: detected multiple manufacturer ids, can only read from one at a time'); + throw new Error( + 'Error: detected multiple manufacturer ids, can only read from one at a time', + ); } // Show warning if a manufacturer specific attribute was found amongst non-manufacturer // specific attributes if (manufacturerIds.length > 0 && attrIdsSet.size !== manufacturerIds.length) { - debug(this.logId, 'WARNING expected only manufacturer specific attributes got:', manufacturerIds); + debug( + this.logId, + 'WARNING expected only manufacturer specific attributes got:', + manufacturerIds, + ); } // Return the manufacturerId that was found in the attributes if (attrIdsSet.size === manufacturerIds.length) return manufacturerIds[0]; return null; } - } Cluster.clusters = {}; diff --git a/lib/Endpoint.js b/lib/Endpoint.js index a4a9ffaa..fa273bae 100644 --- a/lib/Endpoint.js +++ b/lib/Endpoint.js @@ -1,6 +1,6 @@ 'use strict'; -const EventEmitter = require('events'); +const EventEmitter = require('node:events'); const Cluster = require('./Cluster'); const BoundCluster = require('./BoundCluster'); @@ -16,7 +16,6 @@ debug = debug.extend('endpoint'); * Class representing an endpoint on a node. It contains a reference to its clusters and bindings. */ class Endpoint extends EventEmitter { - /** * Creates a new Endpoint instance. * @param {ZCLNode} node @@ -31,9 +30,10 @@ class Endpoint extends EventEmitter { this._node = node; this._descriptor = descriptor; this._endpointId = descriptor.endpointId; + this._nextTrxSeqNr = Math.floor(Math.random() * 256); // Iterate all the input clusters and instantiate a Cluster for each - descriptor.inputClusters.forEach(cId => { + descriptor.inputClusters.forEach((cId) => { const InputCluster = Cluster.getCluster(cId); if (InputCluster) { this.clusters[InputCluster.NAME] = new InputCluster(this); @@ -95,6 +95,19 @@ class Endpoint extends EventEmitter { return this._node.sendFrame(this._endpointId, clusterId, data); } + /** + * Generates next transaction sequence number from the owning {@link ZCLNode}, or from this + * endpoint when its owner has no counter. + * @returns {number} - Transaction sequence number. + * @private + */ + nextSeqNr() { + if (typeof this._node.nextSeqNr === 'function') return this._node.nextSeqNr(); + + this._nextTrxSeqNr = (this._nextTrxSeqNr + 1) % 256; + return this._nextTrxSeqNr; + } + /** * Handles an incoming frame and passes it from the {@link ZCLNode} to the {@link Cluster}. * @param {number} clusterId @@ -113,20 +126,33 @@ class Endpoint extends EventEmitter { clusterSpecificResponse = await this.handleZCLFrame(clusterId, frame, meta, rawFrame); } catch (err) { clusterSpecificError = err; - debug(`${this.getLogId(clusterId)}, error while handling frame`, err.message, { meta, frame }); + debug(`${this.getLogId(clusterId)}, error while handling frame`, err.message, { + meta, + frame, + }); } - // Don't respond to this frame if it is a default response or a group cast (ZCL spec 2.5.12.2) - if (frame.cmdId === 11 || (meta && typeof meta.groupId === 'number')) return; + // Don't respond to a default response or a group cast (ZCL spec 2.5.12.2). Only global + // command 0x0B is a default response, cluster-specific ids are per cluster (2.4.1.4). + const isDefaultResponse = frame.cmdId === 0x0b && !frame.frameControl.clusterSpecific; + if (isDefaultResponse || (meta && typeof meta.groupId === 'number')) return; + + // Default responses are for unicast only (ZCL spec 2.5.12.2). `broadcast` is set by the stack; + // a unicast to the broadcast endpoint 0xFF still gets one. + const isBroadcast = Boolean(meta && meta.broadcast === true); // If cluster specific error, respond with a default response error frame if (clusterSpecificError) { - const status = clusterSpecificError instanceof ZCLError - ? clusterSpecificError.zclStatus : undefined; + if (isBroadcast) return; + + const status = + clusterSpecificError instanceof ZCLError ? clusterSpecificError.zclStatus : undefined; const defaultResponseErrorFrame = this.makeDefaultResponseFrame(frame, false, status); - this.sendFrame(clusterId, defaultResponseErrorFrame.toBuffer()).catch(err => { - debug(`${this.getLogId(clusterId)}, error while sending default error response`, err, { response: defaultResponseErrorFrame }); + this.sendFrame(clusterId, defaultResponseErrorFrame.toBuffer()).catch((err) => { + debug(`${this.getLogId(clusterId)}, error while sending default error response`, err, { + response: defaultResponseErrorFrame, + }); }); // No further handling for this frame @@ -149,13 +175,18 @@ class Endpoint extends EventEmitter { // If there was no cluster specific response and the default response is disabled, don't // send a response. - if (!clusterSpecificResponse && frame.frameControl.disableDefaultResponse) return; + const noDefaultResponse = frame.frameControl.disableDefaultResponse || isBroadcast; + if (!clusterSpecificResponse && noDefaultResponse) return; // Send either cluster specific, or default response frame try { await this.sendFrame(clusterId, responseFrame.toBuffer()); } catch (err) { - debug(`${this.getLogId(clusterId)}, error while sending cluster specific or default success response`, err, { response: responseFrame }); + debug( + `${this.getLogId(clusterId)}, error while sending cluster specific or default success response`, + err, + { response: responseFrame }, + ); } } @@ -177,12 +208,13 @@ class Endpoint extends EventEmitter { if (this.bindings[clusterName]) { response = await this.bindings[clusterName].handleFrame(frame, meta, rawFrame); } else { - throw new Error('binding_unavailable'); + // ZCL R8 2.5.12.2 + throw new ZCLError('UNSUPPORTED_CLUSTER'); } } else if (this.clusters[clusterName]) { response = await this.clusters[clusterName].handleFrame(frame, meta, rawFrame); } else { - throw new Error('cluster_unavailable'); + throw new ZCLError('UNSUPPORTED_CLUSTER'); } return response; @@ -211,7 +243,7 @@ class Endpoint extends EventEmitter { responseFrame.frameControl.directionToClient = !receivedFrame.frameControl.directionToClient; responseFrame.trxSequenceNumber = receivedFrame.trxSequenceNumber; - responseFrame.cmdId = 0x0B; + responseFrame.cmdId = 0x0b; responseFrame.data = Buffer.from([receivedFrame.cmdId, success ? 0 : 1]); // If not successful, set the status code in the response frame data @@ -221,7 +253,7 @@ class Endpoint extends EventEmitter { if (!success && typeof status === 'string') { try { ZCLDataTypes.enum8Status.toBuffer(responseFrame.data, status, 1); - } catch (err) { + } catch { // Ignore invalid status codes and keep the default FAILURE status. } } @@ -235,7 +267,6 @@ class Endpoint extends EventEmitter { } return ZCLStandardHeader.fromBuffer(frame); } - } module.exports = Endpoint; diff --git a/lib/Node.js b/lib/Node.js index e836aa1d..8029d4c6 100644 --- a/lib/Node.js +++ b/lib/Node.js @@ -1,6 +1,6 @@ 'use strict'; -const EventEmitter = require('events'); +const EventEmitter = require('node:events'); let { debug } = require('./util'); const { getLogId } = require('./util'); @@ -26,7 +26,6 @@ debug = debug.extend('node'); * @alias ZCLNode */ class Node extends EventEmitter { - /** * Create a new ZCLNode instance. * @param {Homey.ZigBeeNode} node - As provided by `Homey.ManagerZigBee.getNode()`. @@ -55,15 +54,29 @@ class Node extends EventEmitter { return node.sendFrame(...args); }; + // One counter for all endpoints and clusters: some devices (e.g. Aqara) ignore a command whose + // TSN they recently saw on any cluster. A random start makes reuse after a restart unlikely. + this._nextTrxSeqNr = Math.floor(Math.random() * 256); + this.endpoints = {}; if (Array.isArray(node.endpointDescriptors)) { - node.endpointDescriptors.forEach(ep => { + node.endpointDescriptors.forEach((ep) => { this.endpoints[ep.endpointId] = new Endpoint(this, ep); }); } } + /** + * Generates next transaction sequence number. + * @returns {number} - Transaction sequence number. + * @private + */ + nextSeqNr() { + this._nextTrxSeqNr = (this._nextTrxSeqNr + 1) % 256; + return this._nextTrxSeqNr; + } + /** * Returns log id string for this node. * @param {number} endpointId @@ -87,7 +100,6 @@ class Node extends EventEmitter { */ async handleFrame(endpointId, clusterId, frame, meta) { if (!Buffer.isBuffer(frame)) { - // eslint-disable-next-line prefer-rest-params debug(`${this.getLogId(endpointId, clusterId)}, invalid frame received`, arguments, frame); return; } @@ -95,10 +107,12 @@ class Node extends EventEmitter { if (this.endpoints[endpointId]) { await this.endpoints[endpointId].handleFrame(clusterId, frame, meta); } else { - debug(`${this.getLogId(endpointId, clusterId)}, error while handling frame, endpoint unavailable`, { meta, frame }); + debug( + `${this.getLogId(endpointId, clusterId)}, error while handling frame, endpoint unavailable`, + { meta, frame }, + ); } } - } module.exports = Node; diff --git a/lib/clusters/alarms.js b/lib/clusters/alarms.js index 5da6f87e..d153596b 100644 --- a/lib/clusters/alarms.js +++ b/lib/clusters/alarms.js @@ -1,6 +1,7 @@ 'use strict'; const Cluster = require('../Cluster'); +const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = {}; @@ -10,6 +11,17 @@ const COMMANDS = { }, getAlarm: { id: 2, + response: { + id: 1, + encodeMissingFieldsBehavior: 'skip', + args: { + status: ZCLDataTypes.enum8Status, + // Remaining fields only present when status is SUCCESS + alarmCode: ZCLDataTypes.uint8, + clusterId: ZCLDataTypes.uint16, + timeStamp: ZCLDataTypes.uint32, + }, + }, }, resetAlarmLog: { id: 3, @@ -17,7 +29,6 @@ const COMMANDS = { }; class AlarmsCluster extends Cluster { - static get ID() { return 9; // 0x9 } @@ -33,7 +44,6 @@ class AlarmsCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(AlarmsCluster); diff --git a/lib/clusters/analogInput.js b/lib/clusters/analogInput.js index db6536b3..eff398bd 100644 --- a/lib/clusters/analogInput.js +++ b/lib/clusters/analogInput.js @@ -25,14 +25,16 @@ const ATTRIBUTES = { }), }, resolution: { id: 106, type: ZCLDataTypes.single }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class AnalogInputCluster extends Cluster { - static get ID() { return 12; // 0x0c } @@ -48,7 +50,6 @@ class AnalogInputCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(AnalogInputCluster); diff --git a/lib/clusters/analogOutput.js b/lib/clusters/analogOutput.js index d8ef234c..302339b2 100644 --- a/lib/clusters/analogOutput.js +++ b/lib/clusters/analogOutput.js @@ -24,14 +24,16 @@ const ATTRIBUTES = { }, relinquishDefault: { id: 104, type: ZCLDataTypes.single }, resolution: { id: 106, type: ZCLDataTypes.single }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class AnalogOutputCluster extends Cluster { - static get ID() { return 13; } @@ -47,7 +49,6 @@ class AnalogOutputCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(AnalogOutputCluster); diff --git a/lib/clusters/analogValue.js b/lib/clusters/analogValue.js index 073a7cdc..a7fdd8fa 100644 --- a/lib/clusters/analogValue.js +++ b/lib/clusters/analogValue.js @@ -21,14 +21,16 @@ const ATTRIBUTES = { }), }, relinquishDefault: { id: 104, type: ZCLDataTypes.single }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class AnalogValueCluster extends Cluster { - static get ID() { return 14; } @@ -44,7 +46,6 @@ class AnalogValueCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(AnalogValueCluster); diff --git a/lib/clusters/ballastConfiguration.js b/lib/clusters/ballastConfiguration.js index 92b1f0a5..d66114a5 100644 --- a/lib/clusters/ballastConfiguration.js +++ b/lib/clusters/ballastConfiguration.js @@ -6,7 +6,6 @@ const { ZCLDataTypes } = require('../zclTypes'); const COMMANDS = {}; const ATTRIBUTES = { - /* 0x0000: PhysicalMinLevel (optional, read-only) * Description: Minimum light level the ballast can achieve. * Default: 0x01 @@ -185,7 +184,6 @@ const ATTRIBUTES = { }; class BallastConfigurationCluster extends Cluster { - static get ID() { return 769; // 0x0301 } @@ -201,7 +199,6 @@ class BallastConfigurationCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(BallastConfigurationCluster); diff --git a/lib/clusters/basic.js b/lib/clusters/basic.js index 9f91fce4..ac926f71 100644 --- a/lib/clusters/basic.js +++ b/lib/clusters/basic.js @@ -191,7 +191,6 @@ const COMMANDS = { }; class BasicCluster extends Cluster { - static get ID() { return 0; } @@ -207,7 +206,6 @@ class BasicCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(BasicCluster); diff --git a/lib/clusters/binaryInput.js b/lib/clusters/binaryInput.js index a6d62f6b..0192de38 100644 --- a/lib/clusters/binaryInput.js +++ b/lib/clusters/binaryInput.js @@ -31,14 +31,16 @@ const ATTRIBUTES = { configurationError: 10, // CONFIGURATION-ERROR (10) }), }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class BinaryInputCluster extends Cluster { - static get ID() { return 15; } @@ -54,7 +56,6 @@ class BinaryInputCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(BinaryInputCluster); diff --git a/lib/clusters/binaryOutput.js b/lib/clusters/binaryOutput.js index bd7b33f4..163b11bb 100644 --- a/lib/clusters/binaryOutput.js +++ b/lib/clusters/binaryOutput.js @@ -32,14 +32,16 @@ const ATTRIBUTES = { }), }, relinquishDefault: { id: 104, type: ZCLDataTypes.bool }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class BinaryOutputCluster extends Cluster { - static get ID() { return 16; } @@ -55,7 +57,6 @@ class BinaryOutputCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(BinaryOutputCluster); diff --git a/lib/clusters/binaryValue.js b/lib/clusters/binaryValue.js index 718263b9..170047c5 100644 --- a/lib/clusters/binaryValue.js +++ b/lib/clusters/binaryValue.js @@ -32,14 +32,16 @@ const ATTRIBUTES = { }), }, relinquishDefault: { id: 104, type: ZCLDataTypes.bool }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class BinaryValueCluster extends Cluster { - static get ID() { return 17; } @@ -55,7 +57,6 @@ class BinaryValueCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(BinaryValueCluster); diff --git a/lib/clusters/colorControl.js b/lib/clusters/colorControl.js index ef699186..90a3a10e 100644 --- a/lib/clusters/colorControl.js +++ b/lib/clusters/colorControl.js @@ -113,7 +113,16 @@ const ATTRIBUTES = { // Bit 4: colorTemperature mandatory commands: moveToColorTemperature, moveColorTemperature, // stepColorTemperature, stopMoveStep, related attributes: colorTemperatureMireds, // colorTempPhysicalMinMireds, colorTempPhysicalMaxMireds - colorCapabilities: { id: 16394, type: ZCLDataTypes.map16('hueAndSaturation', 'enhancedHue', 'colorLoop', 'xy', 'colorTemperature') }, + colorCapabilities: { + id: 16394, + type: ZCLDataTypes.map16( + 'hueAndSaturation', + 'enhancedHue', + 'colorLoop', + 'xy', + 'colorTemperature', + ), + }, // Mandatory if colorCapabilities = colorTemperature // Read-only @@ -193,7 +202,10 @@ const COMMANDS = { // action, direction, time and startHue fields below are ignored by the device unless their // flag is set here. updateFlags: ZCLDataTypes.map8( - 'updateAction', 'updateDirection', 'updateTime', 'updateStartHue', + 'updateAction', + 'updateDirection', + 'updateTime', + 'updateStartHue', ), // Action to take for the color loop, only applied when updateFlags.updateAction is set @@ -222,7 +234,6 @@ const COMMANDS = { }; class ColorControlCluster extends Cluster { - static get ID() { return 768; // 0x0300 } @@ -238,7 +249,6 @@ class ColorControlCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(ColorControlCluster); diff --git a/lib/clusters/dehumidificationControl.js b/lib/clusters/dehumidificationControl.js index cae9ca67..a8338967 100644 --- a/lib/clusters/dehumidificationControl.js +++ b/lib/clusters/dehumidificationControl.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class DehumidificationControlCluster extends Cluster { - static get ID() { return 515; } @@ -24,7 +22,6 @@ class DehumidificationControlCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(DehumidificationControlCluster); diff --git a/lib/clusters/deviceTemperature.js b/lib/clusters/deviceTemperature.js index 2b73ede0..62588bc1 100644 --- a/lib/clusters/deviceTemperature.js +++ b/lib/clusters/deviceTemperature.js @@ -8,7 +8,10 @@ const ATTRIBUTES = { minTempExperienced: { id: 1, type: ZCLDataTypes.int16 }, maxTempExperienced: { id: 2, type: ZCLDataTypes.int16 }, overTempTotalDwell: { id: 3, type: ZCLDataTypes.uint16 }, - deviceTempAlarmMask: { id: 16, type: ZCLDataTypes.map8('deviceTemperatureTooLow', 'deviceTemperatureTooHigh') }, + deviceTempAlarmMask: { + id: 16, + type: ZCLDataTypes.map8('deviceTemperatureTooLow', 'deviceTemperatureTooHigh'), + }, lowTempThreshold: { id: 17, type: ZCLDataTypes.int16 }, highTempThreshold: { id: 18, type: ZCLDataTypes.int16 }, lowTempDwellTripPoint: { id: 19, type: ZCLDataTypes.uint24 }, @@ -18,7 +21,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class DeviceTemperatureCluster extends Cluster { - static get ID() { return 2; } @@ -34,7 +36,6 @@ class DeviceTemperatureCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(DeviceTemperatureCluster); diff --git a/lib/clusters/diagnostics.js b/lib/clusters/diagnostics.js index f13d27bb..61cc151e 100644 --- a/lib/clusters/diagnostics.js +++ b/lib/clusters/diagnostics.js @@ -7,7 +7,6 @@ const ATTRIBUTES = {}; const COMMANDS = {}; class DiagnosticsCluster extends Cluster { - static get ID() { return 2821; // 0x0b05 } @@ -23,7 +22,6 @@ class DiagnosticsCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(DiagnosticsCluster); diff --git a/lib/clusters/doorLock.js b/lib/clusters/doorLock.js index 831fa88f..03beb134 100644 --- a/lib/clusters/doorLock.js +++ b/lib/clusters/doorLock.js @@ -5,7 +5,8 @@ const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = { // Lock Information (0x0000 - 0x000F) - lockState: { // Mandatory + // Mandatory + lockState: { id: 0x0000, type: ZCLDataTypes.enum8({ notFullyLocked: 0, @@ -14,7 +15,8 @@ const ATTRIBUTES = { undefined: 255, }), }, - lockType: { // Mandatory + // Mandatory + lockType: { id: 0x0001, type: ZCLDataTypes.enum8({ deadBolt: 0, @@ -31,7 +33,8 @@ const ATTRIBUTES = { }), }, actuatorEnabled: { id: 0x0002, type: ZCLDataTypes.bool }, // Mandatory - doorState: { // Optional + // Optional + doorState: { id: 0x0003, type: ZCLDataTypes.enum8({ open: 0, @@ -51,11 +54,13 @@ const ATTRIBUTES = { numberOfTotalUsersSupported: { id: 0x0011, type: ZCLDataTypes.uint16 }, // 17, Optional numberOfPINUsersSupported: { id: 0x0012, type: ZCLDataTypes.uint16 }, // 18, Conditional¹ numberOfRFIDUsersSupported: { id: 0x0013, type: ZCLDataTypes.uint16 }, // 19, Conditional² - numberOfWeekDaySchedulesSupportedPerUser: { // Conditional³ + // Conditional³ + numberOfWeekDaySchedulesSupportedPerUser: { id: 0x0014, // 20 type: ZCLDataTypes.uint8, }, - numberOfYearDaySchedulesSupportedPerUser: { // Conditional⁴ + // Conditional⁴ + numberOfYearDaySchedulesSupportedPerUser: { id: 0x0015, // 21 type: ZCLDataTypes.uint8, }, @@ -63,7 +68,7 @@ const ATTRIBUTES = { maxPINCodeLength: { id: 0x0017, type: ZCLDataTypes.uint8 }, // 23, Conditional¹ minPINCodeLength: { id: 0x0018, type: ZCLDataTypes.uint8 }, // 24, Conditional¹ maxRFIDCodeLength: { id: 0x0019, type: ZCLDataTypes.uint8 }, // 25, Conditional² - minRFIDCodeLength: { id: 0x001A, type: ZCLDataTypes.uint8 }, // 26, Conditional² + minRFIDCodeLength: { id: 0x001a, type: ZCLDataTypes.uint8 }, // 26, Conditional² // ¹ PIN credential support // ² RFID credential support // ³ Week Day Schedule support @@ -76,7 +81,8 @@ const ATTRIBUTES = { ledSettings: { id: 0x0022, type: ZCLDataTypes.uint8 }, // 34, Optional autoRelockTime: { id: 0x0023, type: ZCLDataTypes.uint32 }, // 35, Optional soundVolume: { id: 0x0024, type: ZCLDataTypes.uint8 }, // 36, Optional - operatingMode: { // Optional + // Optional + operatingMode: { id: 0x0025, // 37 type: ZCLDataTypes.enum8({ normal: 0, @@ -86,17 +92,13 @@ const ATTRIBUTES = { passage: 4, }), }, - supportedOperatingModes: { // Mandatory + // Mandatory + supportedOperatingModes: { id: 0x0026, // 38 - type: ZCLDataTypes.map16( - 'normal', - 'vacation', - 'privacy', - 'noRFLockOrUnlock', - 'passage', - ), + type: ZCLDataTypes.map16('normal', 'vacation', 'privacy', 'noRFLockOrUnlock', 'passage'), }, - defaultConfigurationRegister: { // Optional + // Optional + defaultConfigurationRegister: { id: 0x0027, // 39 type: ZCLDataTypes.map16( 'enableLocalProgramming', @@ -111,15 +113,16 @@ const ATTRIBUTES = { }, enableLocalProgramming: { id: 0x0028, type: ZCLDataTypes.bool }, // 40, Optional enableOneTouchLocking: { id: 0x0029, type: ZCLDataTypes.bool }, // 41, Optional - enableInsideStatusLED: { id: 0x002A, type: ZCLDataTypes.bool }, // 42, Optional - enablePrivacyModeButton: { id: 0x002B, type: ZCLDataTypes.bool }, // 43, Optional + enableInsideStatusLED: { id: 0x002a, type: ZCLDataTypes.bool }, // 42, Optional + enablePrivacyModeButton: { id: 0x002b, type: ZCLDataTypes.bool }, // 43, Optional // Security Settings (0x0030 - 0x003F) wrongCodeEntryLimit: { id: 0x0030, type: ZCLDataTypes.uint8 }, // 48, Optional userCodeTemporaryDisableTime: { id: 0x0031, type: ZCLDataTypes.uint8 }, // 49, Optional sendPINOverTheAir: { id: 0x0032, type: ZCLDataTypes.bool }, // 50, Optional requirePINforRFOperation: { id: 0x0033, type: ZCLDataTypes.bool }, // 51, Optional - securityLevel: { // Optional + // Optional + securityLevel: { id: 0x0034, // 52 type: ZCLDataTypes.enum8({ network: 0, @@ -128,7 +131,8 @@ const ATTRIBUTES = { }, // Alarm and Event Masks (0x0040 - 0x004F) - alarmMask: { // Optional + // Optional + alarmMask: { id: 0x0040, // 64 type: ZCLDataTypes.map16( 'deadboltJammed', @@ -140,7 +144,8 @@ const ATTRIBUTES = { 'forcedDoorOpenUnderDoorLockedCondition', ), }, - keypadOperationEventMask: { // Optional + // Optional + keypadOperationEventMask: { id: 0x0041, // 65 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificKeypadOperationEvent', @@ -153,7 +158,8 @@ const ATTRIBUTES = { 'nonAccessUserOperationEventSourceKeypad', ), }, - rfOperationEventMask: { // Optional + // Optional + rfOperationEventMask: { id: 0x0042, // 66 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificKeypadOperationEvent', @@ -165,7 +171,8 @@ const ATTRIBUTES = { 'unlockSourceRFErrorInvalidSchedule', ), }, - manualOperationEventMask: { // Optional + // Optional + manualOperationEventMask: { id: 0x0043, // 67 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificManualOperationEvent', @@ -181,7 +188,8 @@ const ATTRIBUTES = { 'manualUnlock', ), }, - rfidOperationEventMask: { // Optional + // Optional + rfidOperationEventMask: { id: 0x0044, // 68 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificKeypadOperationEvent', @@ -193,7 +201,8 @@ const ATTRIBUTES = { 'unlockSourceRFIDErrorInvalidSchedule', ), }, - keypadProgrammingEventMask: { // Optional + // Optional + keypadProgrammingEventMask: { id: 0x0045, // 69 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificKeypadProgrammingEvent', @@ -203,7 +212,8 @@ const ATTRIBUTES = { 'pinCodeChanged', ), }, - rfProgrammingEventMask: { // Optional + // Optional + rfProgrammingEventMask: { id: 0x0046, // 70 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificRFProgrammingEvent', @@ -215,7 +225,8 @@ const ATTRIBUTES = { 'rfidCodeDeleted', ), }, - rfidProgrammingEventMask: { // Optional + // Optional + rfidProgrammingEventMask: { id: 0x0047, // 71 type: ZCLDataTypes.map16( 'unknownOrManufacturerSpecificRFIDProgrammingEvent', @@ -254,7 +265,8 @@ const COMMANDS = { // --- Client to Server Commands --- // Lock/Unlock Commands - lockDoor: { // Mandatory + // Mandatory + lockDoor: { id: 0x0000, args: { pinCode: ZCLDataTypes.octstr, @@ -264,7 +276,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - unlockDoor: { // Mandatory + // Mandatory + unlockDoor: { id: 0x0001, args: { pinCode: ZCLDataTypes.octstr, @@ -274,7 +287,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - toggle: { // Optional + // Optional + toggle: { id: 0x0002, args: { pinCode: ZCLDataTypes.octstr, @@ -284,7 +298,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - unlockWithTimeout: { // Optional + // Optional + unlockWithTimeout: { id: 0x0003, args: { timeout: ZCLDataTypes.uint16, @@ -297,7 +312,8 @@ const COMMANDS = { }, // Logging Commands - getLogRecord: { // Optional + // Optional + getLogRecord: { id: 0x0004, args: { logIndex: ZCLDataTypes.uint16, @@ -317,7 +333,8 @@ const COMMANDS = { }, // PIN Code Commands - setPINCode: { // Optional + // Optional + setPINCode: { id: 0x0005, args: { userId: ZCLDataTypes.uint16, @@ -330,7 +347,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - getPINCode: { // Optional + // Optional + getPINCode: { id: 0x0006, args: { userId: ZCLDataTypes.uint16, @@ -345,7 +363,8 @@ const COMMANDS = { }, }, }, - clearPINCode: { // Optional + // Optional + clearPINCode: { id: 0x0007, args: { userId: ZCLDataTypes.uint16, @@ -355,14 +374,16 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - clearAllPINCodes: { // Optional + // Optional + clearAllPINCodes: { id: 0x0008, response: { id: 0x0008, args: { status: ZCLDataTypes.uint8 }, }, }, - setUserStatus: { // Optional + // Optional + setUserStatus: { id: 0x0009, args: { userId: ZCLDataTypes.uint16, @@ -373,13 +394,14 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - getUserStatus: { // Optional - id: 0x000A, // 10 + // Optional + getUserStatus: { + id: 0x000a, // 10 args: { userId: ZCLDataTypes.uint16, }, response: { - id: 0x000A, // 10 + id: 0x000a, // 10 args: { userId: ZCLDataTypes.uint16, userStatus: USER_STATUS_ENUM, @@ -388,35 +410,53 @@ const COMMANDS = { }, // Schedule Commands - setWeekDaySchedule: { // Optional - id: 0x000B, // 11 + // Optional + setWeekDaySchedule: { + id: 0x000b, // 11 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, - daysMask: ZCLDataTypes.map8('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'), + daysMask: ZCLDataTypes.map8( + 'sunday', + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + ), startHour: ZCLDataTypes.uint8, startMinute: ZCLDataTypes.uint8, endHour: ZCLDataTypes.uint8, endMinute: ZCLDataTypes.uint8, }, response: { - id: 0x000B, // 11 + id: 0x000b, // 11 args: { status: ZCLDataTypes.uint8 }, }, }, - getWeekDaySchedule: { // Optional - id: 0x000C, // 12 + // Optional + getWeekDaySchedule: { + id: 0x000c, // 12 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, }, response: { - id: 0x000C, // 12 + id: 0x000c, // 12 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, status: ZCLDataTypes.uint8, - daysMask: ZCLDataTypes.map8('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'), + daysMask: ZCLDataTypes.map8( + 'sunday', + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + ), startHour: ZCLDataTypes.uint8, startMinute: ZCLDataTypes.uint8, endHour: ZCLDataTypes.uint8, @@ -424,19 +464,21 @@ const COMMANDS = { }, }, }, - clearWeekDaySchedule: { // Optional - id: 0x000D, // 13 + // Optional + clearWeekDaySchedule: { + id: 0x000d, // 13 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, }, response: { - id: 0x000D, // 13 + id: 0x000d, // 13 args: { status: ZCLDataTypes.uint8 }, }, }, - setYearDaySchedule: { // Optional - id: 0x000E, // 14 + // Optional + setYearDaySchedule: { + id: 0x000e, // 14 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, @@ -444,18 +486,19 @@ const COMMANDS = { localEndTime: ZCLDataTypes.uint32, }, response: { - id: 0x000E, // 14 + id: 0x000e, // 14 args: { status: ZCLDataTypes.uint8 }, }, }, - getYearDaySchedule: { // Optional - id: 0x000F, // 15 + // Optional + getYearDaySchedule: { + id: 0x000f, // 15 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, }, response: { - id: 0x000F, // 15 + id: 0x000f, // 15 args: { scheduleId: ZCLDataTypes.uint8, userId: ZCLDataTypes.uint16, @@ -465,7 +508,8 @@ const COMMANDS = { }, }, }, - clearYearDaySchedule: { // Optional + // Optional + clearYearDaySchedule: { id: 0x0010, // 16 args: { scheduleId: ZCLDataTypes.uint8, @@ -476,7 +520,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - setHolidaySchedule: { // Optional + // Optional + setHolidaySchedule: { id: 0x0011, // 17 args: { holidayScheduleId: ZCLDataTypes.uint8, @@ -489,7 +534,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - getHolidaySchedule: { // Optional + // Optional + getHolidaySchedule: { id: 0x0012, // 18 args: { holidayScheduleId: ZCLDataTypes.uint8, @@ -505,7 +551,8 @@ const COMMANDS = { }, }, }, - clearHolidaySchedule: { // Optional + // Optional + clearHolidaySchedule: { id: 0x0013, // 19 args: { holidayScheduleId: ZCLDataTypes.uint8, @@ -517,7 +564,8 @@ const COMMANDS = { }, // User Type Commands - setUserType: { // Optional + // Optional + setUserType: { id: 0x0014, // 20 args: { userId: ZCLDataTypes.uint16, @@ -528,7 +576,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - getUserType: { // Optional + // Optional + getUserType: { id: 0x0015, // 21 args: { userId: ZCLDataTypes.uint16, @@ -543,7 +592,8 @@ const COMMANDS = { }, // RFID Code Commands - setRFIDCode: { // Optional + // Optional + setRFIDCode: { id: 0x0016, // 22 args: { userId: ZCLDataTypes.uint16, @@ -556,7 +606,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - getRFIDCode: { // Optional + // Optional + getRFIDCode: { id: 0x0017, // 23 args: { userId: ZCLDataTypes.uint16, @@ -571,7 +622,8 @@ const COMMANDS = { }, }, }, - clearRFIDCode: { // Optional + // Optional + clearRFIDCode: { id: 0x0018, // 24 args: { userId: ZCLDataTypes.uint16, @@ -581,7 +633,8 @@ const COMMANDS = { args: { status: ZCLDataTypes.uint8 }, }, }, - clearAllRFIDCodes: { // Optional + // Optional + clearAllRFIDCodes: { id: 0x0019, // 25 response: { id: 0x0019, // 25 @@ -591,7 +644,8 @@ const COMMANDS = { // --- Server to Client Commands --- - operationEventNotification: { // Optional + // Optional + operationEventNotification: { id: 0x0020, // 32 direction: Cluster.DIRECTION_SERVER_TO_CLIENT, args: { @@ -603,7 +657,8 @@ const COMMANDS = { data: ZCLDataTypes.octstr, }, }, - programmingEventNotification: { // Optional + // Optional + programmingEventNotification: { id: 0x0021, // 33 direction: Cluster.DIRECTION_SERVER_TO_CLIENT, args: { @@ -620,7 +675,6 @@ const COMMANDS = { }; class DoorLockCluster extends Cluster { - static get ID() { return 0x0101; // 257 } @@ -636,7 +690,6 @@ class DoorLockCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(DoorLockCluster); diff --git a/lib/clusters/electricalMeasurement.js b/lib/clusters/electricalMeasurement.js index 8474f859..ccfa69b9 100644 --- a/lib/clusters/electricalMeasurement.js +++ b/lib/clusters/electricalMeasurement.js @@ -4,7 +4,20 @@ const Cluster = require('../Cluster'); const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = { - measurementType: { id: 0, type: ZCLDataTypes.map32('activeMeasurementAC', 'reactiveMeasurementAC', 'apparentMeasurementAC', 'phaseAMeasurement', 'phaseBMeasurement', 'phaseCMeasurement', 'dcMeasurement', 'harmonicsMeasurement', 'powerQualityMeasurement') }, + measurementType: { + id: 0, + type: ZCLDataTypes.map32( + 'activeMeasurementAC', + 'reactiveMeasurementAC', + 'apparentMeasurementAC', + 'phaseAMeasurement', + 'phaseBMeasurement', + 'phaseCMeasurement', + 'dcMeasurement', + 'harmonicsMeasurement', + 'powerQualityMeasurement', + ), + }, acFrequency: { id: 768, type: ZCLDataTypes.uint16 }, measuredPhase1stHarmonicCurrent: { id: 781, type: ZCLDataTypes.int16 }, acFrequencyMultiplier: { id: 1024, type: ZCLDataTypes.uint16 }, @@ -20,7 +33,21 @@ const ATTRIBUTES = { acCurrentDivisor: { id: 1539, type: ZCLDataTypes.uint16 }, acPowerMultiplier: { id: 1540, type: ZCLDataTypes.uint16 }, acPowerDivisor: { id: 1541, type: ZCLDataTypes.uint16 }, - acAlarmsMask: { id: 2048, type: ZCLDataTypes.map16('voltageOverload', 'currentOverload', 'activePowerOverload', 'reactivePowerOverload', 'averageRMSOverVoltage', 'averageRMSUnderVoltage', 'rmsExtremeOverVoltage', 'rmsExtremeUnderVoltage', 'rmsVoltageSag', 'rmsVoltageSwell') }, + acAlarmsMask: { + id: 2048, + type: ZCLDataTypes.map16( + 'voltageOverload', + 'currentOverload', + 'activePowerOverload', + 'reactivePowerOverload', + 'averageRMSOverVoltage', + 'averageRMSUnderVoltage', + 'rmsExtremeOverVoltage', + 'rmsExtremeUnderVoltage', + 'rmsVoltageSag', + 'rmsVoltageSwell', + ), + }, acVoltageOverload: { id: 2049, type: ZCLDataTypes.uint16 }, acCurrentOverload: { id: 2050, type: ZCLDataTypes.uint16 }, acActivePowerOverload: { id: 2051, type: ZCLDataTypes.uint16 }, @@ -29,7 +56,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class ElectricalMeasurementCluster extends Cluster { - static get ID() { return 2820; // 0x0b04 } @@ -45,7 +71,6 @@ class ElectricalMeasurementCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(ElectricalMeasurementCluster); diff --git a/lib/clusters/fanControl.js b/lib/clusters/fanControl.js index 82c83bb9..367c217b 100644 --- a/lib/clusters/fanControl.js +++ b/lib/clusters/fanControl.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class FanControlCluster extends Cluster { - static get ID() { return 514; } @@ -24,7 +22,6 @@ class FanControlCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(FanControlCluster); diff --git a/lib/clusters/flowMeasurement.js b/lib/clusters/flowMeasurement.js index 1e3936b8..79c25a29 100644 --- a/lib/clusters/flowMeasurement.js +++ b/lib/clusters/flowMeasurement.js @@ -13,7 +13,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class FlowMeasurementCluster extends Cluster { - static get ID() { return 1028; } @@ -29,7 +28,6 @@ class FlowMeasurementCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(FlowMeasurementCluster); diff --git a/lib/clusters/groups.js b/lib/clusters/groups.js index 878228fc..15863672 100644 --- a/lib/clusters/groups.js +++ b/lib/clusters/groups.js @@ -4,7 +4,10 @@ const Cluster = require('../Cluster'); const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = { - nameSupport: { id: 0, type: ZCLDataTypes.map8(null, null, null, null, null, null, null, 'groupNames') }, + nameSupport: { + id: 0, + type: ZCLDataTypes.map8(null, null, null, null, null, null, null, 'groupNames'), + }, }; const COMMANDS = { @@ -73,7 +76,6 @@ const COMMANDS = { }; class GroupsCluster extends Cluster { - static get ID() { return 4; } @@ -89,7 +91,6 @@ class GroupsCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(GroupsCluster); diff --git a/lib/clusters/iasACE.js b/lib/clusters/iasACE.js index 250b1d84..43f0b2e7 100644 --- a/lib/clusters/iasACE.js +++ b/lib/clusters/iasACE.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class IASACECluster extends Cluster { - static get ID() { return 1281; } @@ -24,7 +22,6 @@ class IASACECluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(IASACECluster); diff --git a/lib/clusters/iasWD.js b/lib/clusters/iasWD.js index 91ce66b3..ddef804e 100644 --- a/lib/clusters/iasWD.js +++ b/lib/clusters/iasWD.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class IASWDCluster extends Cluster { - static get ID() { return 1282; } @@ -24,7 +22,6 @@ class IASWDCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(IASWDCluster); diff --git a/lib/clusters/iasZone.js b/lib/clusters/iasZone.js index fbb13287..c4079124 100644 --- a/lib/clusters/iasZone.js +++ b/lib/clusters/iasZone.js @@ -3,7 +3,18 @@ const Cluster = require('../Cluster'); const { ZCLDataTypes } = require('../zclTypes'); -const ZONE_STATUS_DATA_TYPE = ZCLDataTypes.map16('alarm1', 'alarm2', 'tamper', 'battery', 'supervisionReports', 'restoreReports', 'trouble', 'acMains', 'test', 'batteryDefect'); +const ZONE_STATUS_DATA_TYPE = ZCLDataTypes.map16( + 'alarm1', + 'alarm2', + 'tamper', + 'battery', + 'supervisionReports', + 'restoreReports', + 'trouble', + 'acMains', + 'test', + 'batteryDefect', +); const ZONE_TYPE_VALUES = { standardCIE: 0x0000, @@ -93,7 +104,6 @@ const COMMANDS = { }; class IASZoneCluster extends Cluster { - static get ID() { return 1280; } @@ -109,7 +119,6 @@ class IASZoneCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(IASZoneCluster); diff --git a/lib/clusters/identify.js b/lib/clusters/identify.js index 2da309d4..eb907cbd 100644 --- a/lib/clusters/identify.js +++ b/lib/clusters/identify.js @@ -40,7 +40,6 @@ const COMMANDS = { }; class IdentifyCluster extends Cluster { - static get ID() { return 3; } @@ -56,7 +55,6 @@ class IdentifyCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(IdentifyCluster); diff --git a/lib/clusters/illuminanceLevelSensing.js b/lib/clusters/illuminanceLevelSensing.js index 8b07c1ae..6f7fe862 100644 --- a/lib/clusters/illuminanceLevelSensing.js +++ b/lib/clusters/illuminanceLevelSensing.js @@ -27,7 +27,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class IlluminanceLevelSensingCluster extends Cluster { - static get ID() { return 1025; } @@ -43,7 +42,6 @@ class IlluminanceLevelSensingCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(IlluminanceLevelSensingCluster); diff --git a/lib/clusters/illuminanceMeasurement.js b/lib/clusters/illuminanceMeasurement.js index 656cc226..2bcdf1d8 100644 --- a/lib/clusters/illuminanceMeasurement.js +++ b/lib/clusters/illuminanceMeasurement.js @@ -21,7 +21,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class IlluminanceMeasurementCluster extends Cluster { - static get ID() { return 1024; // 0x0400 } @@ -37,7 +36,6 @@ class IlluminanceMeasurementCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(IlluminanceMeasurementCluster); diff --git a/lib/clusters/index.js b/lib/clusters/index.js index cf5718b3..25e81d72 100644 --- a/lib/clusters/index.js +++ b/lib/clusters/index.js @@ -57,11 +57,12 @@ const TouchLinkCluster = require('./touchlink'); * @returns {Readonly<{ATTRIBUTES: *, COMMANDS: *, ID: *, NAME: *}>} * @private */ -function destructConstProps({ - ID, NAME, ATTRIBUTES, COMMANDS, -}) { +function destructConstProps({ ID, NAME, ATTRIBUTES, COMMANDS }) { return Object.freeze({ - ID, NAME, ATTRIBUTES, COMMANDS, + ID, + NAME, + ATTRIBUTES, + COMMANDS, }); } diff --git a/lib/clusters/levelControl.js b/lib/clusters/levelControl.js index 04c20816..bd1bab0a 100644 --- a/lib/clusters/levelControl.js +++ b/lib/clusters/levelControl.js @@ -76,7 +76,6 @@ const COMMANDS = { }; class LevelControlCluster extends Cluster { - static get ID() { return 8; } @@ -92,7 +91,6 @@ class LevelControlCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(LevelControlCluster); diff --git a/lib/clusters/metering.js b/lib/clusters/metering.js index 93ededa5..5c3ea486 100644 --- a/lib/clusters/metering.js +++ b/lib/clusters/metering.js @@ -15,10 +15,10 @@ const ATTRIBUTES = { readingSnapShotTime: { id: 0x0007, type: ZCLDataTypes.uint32 }, // Optional currentMaxDemandDeliveredTime: { id: 0x0008, type: ZCLDataTypes.uint32 }, // Optional currentMaxDemandReceivedTime: { id: 0x0009, type: ZCLDataTypes.uint32 }, // Optional - defaultUpdatePeriod: { id: 0x000A, type: ZCLDataTypes.uint8 }, // 10, Optional - fastPollUpdatePeriod: { id: 0x000B, type: ZCLDataTypes.uint8 }, // 11, Optional - currentBlockPeriodConsumptionDelivered: { id: 0x000C, type: ZCLDataTypes.uint48 }, // 12, Optional - dailyConsumptionTarget: { id: 0x000D, type: ZCLDataTypes.uint24 }, // 13, Optional + defaultUpdatePeriod: { id: 0x000a, type: ZCLDataTypes.uint8 }, // 10, Optional + fastPollUpdatePeriod: { id: 0x000b, type: ZCLDataTypes.uint8 }, // 11, Optional + currentBlockPeriodConsumptionDelivered: { id: 0x000c, type: ZCLDataTypes.uint48 }, // 12, Optional + dailyConsumptionTarget: { id: 0x000d, type: ZCLDataTypes.uint24 }, // 13, Optional // currentBlock: { id: 0x000E, type: ZCLDataTypes.enum8({/* TODO fix */}) }, // 14, Optional // profileIntervalPeriod: { // Optional // id: 0x000F, // 15 @@ -36,7 +36,8 @@ const ATTRIBUTES = { currentTier4SummationReceived: { id: 0x0107, type: ZCLDataTypes.uint48 }, // 263, Optional // Meter Status (0x0200 - 0x02FF) - status: { // 512, Optional + // 512, Optional + status: { id: 0x0200, type: ZCLDataTypes.map8( 'checkMeter', @@ -75,8 +76,8 @@ const ATTRIBUTES = { // temperatureUnitOfMeasure: { id: 0x030C, type: ZCLDataTypes.enum8({/* TODO fix */}) }, // TODO: map8 packed fields — bits 0-2: right digits, 3-6: left digits, 7: suppress zeros // temperatureFormatting: { id: 0x030D, type: ZCLDataTypes.map8() }, // 781, Optional - moduleSerialNumber: { id: 0x030E, type: ZCLDataTypes.octstr }, // 782, Optional - operatingTariffLabelDelivered: { id: 0x030F, type: ZCLDataTypes.octstr }, // 783, Optional + moduleSerialNumber: { id: 0x030e, type: ZCLDataTypes.octstr }, // 782, Optional + operatingTariffLabelDelivered: { id: 0x030f, type: ZCLDataTypes.octstr }, // 783, Optional operatingTariffLabelReceived: { id: 0x0310, type: ZCLDataTypes.octstr }, // 784, Optional customerIdNumber: { id: 0x0311, type: ZCLDataTypes.octstr }, // 785, Optional /* 786, Optional */ @@ -91,29 +92,33 @@ const ATTRIBUTES = { currentDayConsumptionReceived: { id: 0x0402, type: ZCLDataTypes.uint24 }, // 1026, Optional previousDayConsumptionDelivered: { id: 0x0403, type: ZCLDataTypes.uint24 }, // 1027, Optional previousDayConsumptionReceived: { id: 0x0404, type: ZCLDataTypes.uint24 }, // 1028, Optional - currentPartialProfileIntervalStartTimeDelivered: { // Optional + // Optional + currentPartialProfileIntervalStartTimeDelivered: { id: 0x0405, // 1029 type: ZCLDataTypes.uint32, }, - currentPartialProfileIntervalStartTimeReceived: { // Optional + // Optional + currentPartialProfileIntervalStartTimeReceived: { id: 0x0406, // 1030 type: ZCLDataTypes.uint32, }, - currentPartialProfileIntervalValueDelivered: { // Optional + // Optional + currentPartialProfileIntervalValueDelivered: { id: 0x0407, // 1031 type: ZCLDataTypes.uint24, }, - currentPartialProfileIntervalValueReceived: { // Optional + // Optional + currentPartialProfileIntervalValueReceived: { id: 0x0408, // 1032 type: ZCLDataTypes.uint24, }, currentDayMaxPressure: { id: 0x0409, type: ZCLDataTypes.uint48 }, // 1033, Optional - currentDayMinPressure: { id: 0x040A, type: ZCLDataTypes.uint48 }, // 1034, Optional - previousDayMaxPressure: { id: 0x040B, type: ZCLDataTypes.uint48 }, // 1035, Optional - previousDayMinPressure: { id: 0x040C, type: ZCLDataTypes.uint48 }, // 1036, Optional - currentDayMaxDemand: { id: 0x040D, type: ZCLDataTypes.int24 }, // 1037, Optional - previousDayMaxDemand: { id: 0x040E, type: ZCLDataTypes.int24 }, // 1038, Optional - currentMonthMaxDemand: { id: 0x040F, type: ZCLDataTypes.int24 }, // 1039, Optional + currentDayMinPressure: { id: 0x040a, type: ZCLDataTypes.uint48 }, // 1034, Optional + previousDayMaxPressure: { id: 0x040b, type: ZCLDataTypes.uint48 }, // 1035, Optional + previousDayMinPressure: { id: 0x040c, type: ZCLDataTypes.uint48 }, // 1036, Optional + currentDayMaxDemand: { id: 0x040d, type: ZCLDataTypes.int24 }, // 1037, Optional + previousDayMaxDemand: { id: 0x040e, type: ZCLDataTypes.int24 }, // 1038, Optional + currentMonthMaxDemand: { id: 0x040f, type: ZCLDataTypes.int24 }, // 1039, Optional currentYearMaxDemand: { id: 0x0410, type: ZCLDataTypes.int24 }, // 1040, Optional currentDayMaxEnergyCarrierDemand: { id: 0x0411, type: ZCLDataTypes.int24 }, // 1041, Optional previousDayMaxEnergyCarrierDemand: { id: 0x0412, type: ZCLDataTypes.int24 }, // 1042, Optional @@ -144,12 +149,12 @@ const ATTRIBUTES = { currentNoTierBlock8SummationDelivered: { id: 0x0707, type: ZCLDataTypes.uint48 }, currentNoTierBlock9SummationDelivered: { id: 0x0708, type: ZCLDataTypes.uint48 }, currentNoTierBlock10SummationDelivered: { id: 0x0709, type: ZCLDataTypes.uint48 }, - currentNoTierBlock11SummationDelivered: { id: 0x070A, type: ZCLDataTypes.uint48 }, - currentNoTierBlock12SummationDelivered: { id: 0x070B, type: ZCLDataTypes.uint48 }, - currentNoTierBlock13SummationDelivered: { id: 0x070C, type: ZCLDataTypes.uint48 }, - currentNoTierBlock14SummationDelivered: { id: 0x070D, type: ZCLDataTypes.uint48 }, - currentNoTierBlock15SummationDelivered: { id: 0x070E, type: ZCLDataTypes.uint48 }, - currentNoTierBlock16SummationDelivered: { id: 0x070F, type: ZCLDataTypes.uint48 }, + currentNoTierBlock11SummationDelivered: { id: 0x070a, type: ZCLDataTypes.uint48 }, + currentNoTierBlock12SummationDelivered: { id: 0x070b, type: ZCLDataTypes.uint48 }, + currentNoTierBlock13SummationDelivered: { id: 0x070c, type: ZCLDataTypes.uint48 }, + currentNoTierBlock14SummationDelivered: { id: 0x070d, type: ZCLDataTypes.uint48 }, + currentNoTierBlock15SummationDelivered: { id: 0x070e, type: ZCLDataTypes.uint48 }, + currentNoTierBlock16SummationDelivered: { id: 0x070f, type: ZCLDataTypes.uint48 }, currentTier1Block1SummationDelivered: { id: 0x0710, type: ZCLDataTypes.uint48 }, currentTier1Block2SummationDelivered: { id: 0x0711, type: ZCLDataTypes.uint48 }, currentTier1Block3SummationDelivered: { id: 0x0712, type: ZCLDataTypes.uint48 }, @@ -160,12 +165,12 @@ const ATTRIBUTES = { currentTier1Block8SummationDelivered: { id: 0x0717, type: ZCLDataTypes.uint48 }, currentTier1Block9SummationDelivered: { id: 0x0718, type: ZCLDataTypes.uint48 }, currentTier1Block10SummationDelivered: { id: 0x0719, type: ZCLDataTypes.uint48 }, - currentTier1Block11SummationDelivered: { id: 0x071A, type: ZCLDataTypes.uint48 }, - currentTier1Block12SummationDelivered: { id: 0x071B, type: ZCLDataTypes.uint48 }, - currentTier1Block13SummationDelivered: { id: 0x071C, type: ZCLDataTypes.uint48 }, - currentTier1Block14SummationDelivered: { id: 0x071D, type: ZCLDataTypes.uint48 }, - currentTier1Block15SummationDelivered: { id: 0x071E, type: ZCLDataTypes.uint48 }, - currentTier1Block16SummationDelivered: { id: 0x071F, type: ZCLDataTypes.uint48 }, + currentTier1Block11SummationDelivered: { id: 0x071a, type: ZCLDataTypes.uint48 }, + currentTier1Block12SummationDelivered: { id: 0x071b, type: ZCLDataTypes.uint48 }, + currentTier1Block13SummationDelivered: { id: 0x071c, type: ZCLDataTypes.uint48 }, + currentTier1Block14SummationDelivered: { id: 0x071d, type: ZCLDataTypes.uint48 }, + currentTier1Block15SummationDelivered: { id: 0x071e, type: ZCLDataTypes.uint48 }, + currentTier1Block16SummationDelivered: { id: 0x071f, type: ZCLDataTypes.uint48 }, currentTier2Block1SummationDelivered: { id: 0x0720, type: ZCLDataTypes.uint48 }, currentTier2Block2SummationDelivered: { id: 0x0721, type: ZCLDataTypes.uint48 }, currentTier2Block3SummationDelivered: { id: 0x0722, type: ZCLDataTypes.uint48 }, @@ -176,12 +181,12 @@ const ATTRIBUTES = { currentTier2Block8SummationDelivered: { id: 0x0727, type: ZCLDataTypes.uint48 }, currentTier2Block9SummationDelivered: { id: 0x0728, type: ZCLDataTypes.uint48 }, currentTier2Block10SummationDelivered: { id: 0x0729, type: ZCLDataTypes.uint48 }, - currentTier2Block11SummationDelivered: { id: 0x072A, type: ZCLDataTypes.uint48 }, - currentTier2Block12SummationDelivered: { id: 0x072B, type: ZCLDataTypes.uint48 }, - currentTier2Block13SummationDelivered: { id: 0x072C, type: ZCLDataTypes.uint48 }, - currentTier2Block14SummationDelivered: { id: 0x072D, type: ZCLDataTypes.uint48 }, - currentTier2Block15SummationDelivered: { id: 0x072E, type: ZCLDataTypes.uint48 }, - currentTier2Block16SummationDelivered: { id: 0x072F, type: ZCLDataTypes.uint48 }, + currentTier2Block11SummationDelivered: { id: 0x072a, type: ZCLDataTypes.uint48 }, + currentTier2Block12SummationDelivered: { id: 0x072b, type: ZCLDataTypes.uint48 }, + currentTier2Block13SummationDelivered: { id: 0x072c, type: ZCLDataTypes.uint48 }, + currentTier2Block14SummationDelivered: { id: 0x072d, type: ZCLDataTypes.uint48 }, + currentTier2Block15SummationDelivered: { id: 0x072e, type: ZCLDataTypes.uint48 }, + currentTier2Block16SummationDelivered: { id: 0x072f, type: ZCLDataTypes.uint48 }, currentTier3Block1SummationDelivered: { id: 0x0730, type: ZCLDataTypes.uint48 }, currentTier3Block2SummationDelivered: { id: 0x0731, type: ZCLDataTypes.uint48 }, currentTier3Block3SummationDelivered: { id: 0x0732, type: ZCLDataTypes.uint48 }, @@ -192,12 +197,12 @@ const ATTRIBUTES = { currentTier3Block8SummationDelivered: { id: 0x0737, type: ZCLDataTypes.uint48 }, currentTier3Block9SummationDelivered: { id: 0x0738, type: ZCLDataTypes.uint48 }, currentTier3Block10SummationDelivered: { id: 0x0739, type: ZCLDataTypes.uint48 }, - currentTier3Block11SummationDelivered: { id: 0x073A, type: ZCLDataTypes.uint48 }, - currentTier3Block12SummationDelivered: { id: 0x073B, type: ZCLDataTypes.uint48 }, - currentTier3Block13SummationDelivered: { id: 0x073C, type: ZCLDataTypes.uint48 }, - currentTier3Block14SummationDelivered: { id: 0x073D, type: ZCLDataTypes.uint48 }, - currentTier3Block15SummationDelivered: { id: 0x073E, type: ZCLDataTypes.uint48 }, - currentTier3Block16SummationDelivered: { id: 0x073F, type: ZCLDataTypes.uint48 }, + currentTier3Block11SummationDelivered: { id: 0x073a, type: ZCLDataTypes.uint48 }, + currentTier3Block12SummationDelivered: { id: 0x073b, type: ZCLDataTypes.uint48 }, + currentTier3Block13SummationDelivered: { id: 0x073c, type: ZCLDataTypes.uint48 }, + currentTier3Block14SummationDelivered: { id: 0x073d, type: ZCLDataTypes.uint48 }, + currentTier3Block15SummationDelivered: { id: 0x073e, type: ZCLDataTypes.uint48 }, + currentTier3Block16SummationDelivered: { id: 0x073f, type: ZCLDataTypes.uint48 }, currentTier4Block1SummationDelivered: { id: 0x0740, type: ZCLDataTypes.uint48 }, currentTier4Block2SummationDelivered: { id: 0x0741, type: ZCLDataTypes.uint48 }, currentTier4Block3SummationDelivered: { id: 0x0742, type: ZCLDataTypes.uint48 }, @@ -208,12 +213,12 @@ const ATTRIBUTES = { currentTier4Block8SummationDelivered: { id: 0x0747, type: ZCLDataTypes.uint48 }, currentTier4Block9SummationDelivered: { id: 0x0748, type: ZCLDataTypes.uint48 }, currentTier4Block10SummationDelivered: { id: 0x0749, type: ZCLDataTypes.uint48 }, - currentTier4Block11SummationDelivered: { id: 0x074A, type: ZCLDataTypes.uint48 }, - currentTier4Block12SummationDelivered: { id: 0x074B, type: ZCLDataTypes.uint48 }, - currentTier4Block13SummationDelivered: { id: 0x074C, type: ZCLDataTypes.uint48 }, - currentTier4Block14SummationDelivered: { id: 0x074D, type: ZCLDataTypes.uint48 }, - currentTier4Block15SummationDelivered: { id: 0x074E, type: ZCLDataTypes.uint48 }, - currentTier4Block16SummationDelivered: { id: 0x074F, type: ZCLDataTypes.uint48 }, + currentTier4Block11SummationDelivered: { id: 0x074a, type: ZCLDataTypes.uint48 }, + currentTier4Block12SummationDelivered: { id: 0x074b, type: ZCLDataTypes.uint48 }, + currentTier4Block13SummationDelivered: { id: 0x074c, type: ZCLDataTypes.uint48 }, + currentTier4Block14SummationDelivered: { id: 0x074d, type: ZCLDataTypes.uint48 }, + currentTier4Block15SummationDelivered: { id: 0x074e, type: ZCLDataTypes.uint48 }, + currentTier4Block16SummationDelivered: { id: 0x074f, type: ZCLDataTypes.uint48 }, // Alarms (0x0800 - 0x08FF) // TODO: map16/32/48 alarm masks — bits map to alarm codes in their group (spec 10.4.2.2.9.1) @@ -238,49 +243,49 @@ const ATTRIBUTES = { currentNoTierBlock8SummationReceived: { id: 0x0907, type: ZCLDataTypes.uint48 }, currentNoTierBlock9SummationReceived: { id: 0x0908, type: ZCLDataTypes.uint48 }, currentNoTierBlock10SummationReceived: { id: 0x0909, type: ZCLDataTypes.uint48 }, - currentNoTierBlock11SummationReceived: { id: 0x090A, type: ZCLDataTypes.uint48 }, - currentNoTierBlock12SummationReceived: { id: 0x090B, type: ZCLDataTypes.uint48 }, - currentNoTierBlock13SummationReceived: { id: 0x090C, type: ZCLDataTypes.uint48 }, - currentNoTierBlock14SummationReceived: { id: 0x090D, type: ZCLDataTypes.uint48 }, - currentNoTierBlock15SummationReceived: { id: 0x090E, type: ZCLDataTypes.uint48 }, - currentNoTierBlock16SummationReceived: { id: 0x090F, type: ZCLDataTypes.uint48 }, + currentNoTierBlock11SummationReceived: { id: 0x090a, type: ZCLDataTypes.uint48 }, + currentNoTierBlock12SummationReceived: { id: 0x090b, type: ZCLDataTypes.uint48 }, + currentNoTierBlock13SummationReceived: { id: 0x090c, type: ZCLDataTypes.uint48 }, + currentNoTierBlock14SummationReceived: { id: 0x090d, type: ZCLDataTypes.uint48 }, + currentNoTierBlock15SummationReceived: { id: 0x090e, type: ZCLDataTypes.uint48 }, + currentNoTierBlock16SummationReceived: { id: 0x090f, type: ZCLDataTypes.uint48 }, // Meter Billing (0x0A00 - 0x0AFF) - billToDateDelivered: { id: 0x0A00, type: ZCLDataTypes.uint32 }, // 2560, Optional - billToDateTimeStampDelivered: { id: 0x0A01, type: ZCLDataTypes.uint32 }, // 2561, Optional - projectedBillDelivered: { id: 0x0A02, type: ZCLDataTypes.uint32 }, // 2562, Optional - projectedBillTimeStampDelivered: { id: 0x0A03, type: ZCLDataTypes.uint32 }, // 2563, Optional + billToDateDelivered: { id: 0x0a00, type: ZCLDataTypes.uint32 }, // 2560, Optional + billToDateTimeStampDelivered: { id: 0x0a01, type: ZCLDataTypes.uint32 }, // 2561, Optional + projectedBillDelivered: { id: 0x0a02, type: ZCLDataTypes.uint32 }, // 2562, Optional + projectedBillTimeStampDelivered: { id: 0x0a03, type: ZCLDataTypes.uint32 }, // 2563, Optional // TODO: map8 packed field — most significant nibble = digits right of decimal // billDeliveredTrailingDigit: { id: 0x0A04, type: ZCLDataTypes.map8() }, // 2564, Optional - billToDateReceived: { id: 0x0A10, type: ZCLDataTypes.uint32 }, // 2576, Optional - billToDateTimeStampReceived: { id: 0x0A11, type: ZCLDataTypes.uint32 }, // 2577, Optional - projectedBillReceived: { id: 0x0A12, type: ZCLDataTypes.uint32 }, // 2578, Optional - projectedBillTimeStampReceived: { id: 0x0A13, type: ZCLDataTypes.uint32 }, // 2579, Optional + billToDateReceived: { id: 0x0a10, type: ZCLDataTypes.uint32 }, // 2576, Optional + billToDateTimeStampReceived: { id: 0x0a11, type: ZCLDataTypes.uint32 }, // 2577, Optional + projectedBillReceived: { id: 0x0a12, type: ZCLDataTypes.uint32 }, // 2578, Optional + projectedBillTimeStampReceived: { id: 0x0a13, type: ZCLDataTypes.uint32 }, // 2579, Optional // TODO: map8 packed field — most significant nibble = digits right of decimal // billReceivedTrailingDigit: { id: 0x0A14, type: ZCLDataTypes.map8() }, // 2580, Optional // Supply Control (0x0B00 - 0x0BFF) - proposedChangeSupplyImplementationTime: { // Optional - id: 0x0B00, // 2816 + // Optional + proposedChangeSupplyImplementationTime: { + id: 0x0b00, // 2816 type: ZCLDataTypes.uint32, }, /* 2817, Optional */ // proposedChangeSupplyStatus: { id: 0x0B01, type: ZCLDataTypes.enum8({/* TODO fix */}) }, - uncontrolledFlowThreshold: { id: 0x0B10, type: ZCLDataTypes.uint16 }, // 2832, Optional + uncontrolledFlowThreshold: { id: 0x0b10, type: ZCLDataTypes.uint16 }, // 2832, Optional // uncontrolledFlowThresholdUnitOfMeasure: { // Optional // id: 0x0B11, // 2833 // type: ZCLDataTypes.enum8({/* TODO fix */}), // }, - uncontrolledFlowMultiplier: { id: 0x0B12, type: ZCLDataTypes.uint16 }, // 2834, Optional - uncontrolledFlowDivisor: { id: 0x0B13, type: ZCLDataTypes.uint16 }, // 2835, Optional - flowStabilisationPeriod: { id: 0x0B14, type: ZCLDataTypes.uint8 }, // 2836, Optional - flowMeasurementPeriod: { id: 0x0B15, type: ZCLDataTypes.uint16 }, // 2837, Optional + uncontrolledFlowMultiplier: { id: 0x0b12, type: ZCLDataTypes.uint16 }, // 2834, Optional + uncontrolledFlowDivisor: { id: 0x0b13, type: ZCLDataTypes.uint16 }, // 2835, Optional + flowStabilisationPeriod: { id: 0x0b14, type: ZCLDataTypes.uint8 }, // 2836, Optional + flowMeasurementPeriod: { id: 0x0b15, type: ZCLDataTypes.uint16 }, // 2837, Optional }; const COMMANDS = {}; class MeteringCluster extends Cluster { - static get ID() { return 0x0702; // 1794 } @@ -296,7 +301,6 @@ class MeteringCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(MeteringCluster); diff --git a/lib/clusters/multistateInput.js b/lib/clusters/multistateInput.js index 889c6eeb..882fce74 100644 --- a/lib/clusters/multistateInput.js +++ b/lib/clusters/multistateInput.js @@ -24,14 +24,16 @@ const ATTRIBUTES = { configurationError: 10, // CONFIGURATION-ERROR (10) }), }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class MultistateInputCluster extends Cluster { - static get ID() { return 18; // 0x12 } @@ -47,7 +49,6 @@ class MultistateInputCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(MultistateInputCluster); diff --git a/lib/clusters/multistateOutput.js b/lib/clusters/multistateOutput.js index b737fa42..636fc868 100644 --- a/lib/clusters/multistateOutput.js +++ b/lib/clusters/multistateOutput.js @@ -23,14 +23,16 @@ const ATTRIBUTES = { }), }, relinquishDefault: { id: 104, type: ZCLDataTypes.uint16 }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class MultistateOutputCluster extends Cluster { - static get ID() { return 19; } @@ -46,7 +48,6 @@ class MultistateOutputCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(MultistateOutputCluster); diff --git a/lib/clusters/multistateValue.js b/lib/clusters/multistateValue.js index 157bb6c6..d1f678ee 100644 --- a/lib/clusters/multistateValue.js +++ b/lib/clusters/multistateValue.js @@ -25,14 +25,16 @@ const ATTRIBUTES = { }), }, relinquishDefault: { id: 104, type: ZCLDataTypes.uint16 }, - statusFlags: { id: 111, type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService') }, + statusFlags: { + id: 111, + type: ZCLDataTypes.map8('inAlarm', 'fault', 'overridden', 'outOfService'), + }, applicationType: { id: 256, type: ZCLDataTypes.uint32 }, }; const COMMANDS = {}; class MultistateValueCluster extends Cluster { - static get ID() { return 20; } @@ -48,7 +50,6 @@ class MultistateValueCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(MultistateValueCluster); diff --git a/lib/clusters/occupancySensing.js b/lib/clusters/occupancySensing.js index 9a0aecce..905e2d52 100644 --- a/lib/clusters/occupancySensing.js +++ b/lib/clusters/occupancySensing.js @@ -6,7 +6,8 @@ const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = { // Occupancy Sensor Information (0x0000 - 0x000F) occupancy: { id: 0x0000, type: ZCLDataTypes.map8('occupied') }, // Mandatory - occupancySensorType: { // Mandatory + // Mandatory + occupancySensorType: { id: 0x0001, type: ZCLDataTypes.enum8({ pir: 0, @@ -15,7 +16,8 @@ const ATTRIBUTES = { physicalContact: 3, }), }, - occupancySensorTypeBitmap: { // Mandatory + // Mandatory + occupancySensorTypeBitmap: { id: 0x0002, type: ZCLDataTypes.map8('pir', 'ultrasonic', 'physicalContact'), }, @@ -27,30 +29,36 @@ const ATTRIBUTES = { // ¹ PIR sensor type supported // Ultrasonic Configuration (0x0020 - 0x002F) - ultrasonicOccupiedToUnoccupiedDelay: { // 32, Conditional² + // 32, Conditional² + ultrasonicOccupiedToUnoccupiedDelay: { id: 0x0020, type: ZCLDataTypes.uint16, }, - ultrasonicUnoccupiedToOccupiedDelay: { // 33, Conditional² + // 33, Conditional² + ultrasonicUnoccupiedToOccupiedDelay: { id: 0x0021, type: ZCLDataTypes.uint16, }, - ultrasonicUnoccupiedToOccupiedThreshold: { // 34, Conditional² + // 34, Conditional² + ultrasonicUnoccupiedToOccupiedThreshold: { id: 0x0022, type: ZCLDataTypes.uint8, }, // ² Ultrasonic sensor type supported // Physical Contact Configuration (0x0030 - 0x003F) - physicalContactOccupiedToUnoccupiedDelay: { // 48, Conditional³ + // 48, Conditional³ + physicalContactOccupiedToUnoccupiedDelay: { id: 0x0030, type: ZCLDataTypes.uint16, }, - physicalContactUnoccupiedToOccupiedDelay: { // 49, Conditional³ + // 49, Conditional³ + physicalContactUnoccupiedToOccupiedDelay: { id: 0x0031, type: ZCLDataTypes.uint16, }, - physicalContactUnoccupiedToOccupiedThreshold: { // 50, Conditional³ + // 50, Conditional³ + physicalContactUnoccupiedToOccupiedThreshold: { id: 0x0032, type: ZCLDataTypes.uint8, }, @@ -60,7 +68,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class OccupancySensing extends Cluster { - static get ID() { return 0x0406; // 1030 } @@ -76,7 +83,6 @@ class OccupancySensing extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(OccupancySensing); diff --git a/lib/clusters/onOff.js b/lib/clusters/onOff.js index 038e2e91..4717e2bc 100644 --- a/lib/clusters/onOff.js +++ b/lib/clusters/onOff.js @@ -42,7 +42,6 @@ const COMMANDS = { }; class OnOffCluster extends Cluster { - static get ID() { return 6; } @@ -58,7 +57,6 @@ class OnOffCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(OnOffCluster); diff --git a/lib/clusters/onOffSwitch.js b/lib/clusters/onOffSwitch.js index 81a32197..bd5e9404 100644 --- a/lib/clusters/onOffSwitch.js +++ b/lib/clusters/onOffSwitch.js @@ -11,7 +11,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class OnOffSwitchCluster extends Cluster { - static get ID() { return 7; } @@ -27,7 +26,6 @@ class OnOffSwitchCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(OnOffSwitchCluster); diff --git a/lib/clusters/ota.js b/lib/clusters/ota.js index b7d31f59..5a2cc13a 100644 --- a/lib/clusters/ota.js +++ b/lib/clusters/ota.js @@ -37,7 +37,8 @@ const ATTRIBUTES = { // The upgrade status of the client device. The status indicates where the client // device is at in terms of the download and upgrade process. - imageUpgradeStatus: { // Mandatory + // Mandatory + imageUpgradeStatus: { id: 0x0006, type: ZCLDataTypes.enum8({ normal: 0x00, @@ -65,12 +66,13 @@ const ATTRIBUTES = { // A 32 bit value used as a second verification to identify the image. The value // must be consistent during the lifetime of the same image and unique for each // different build of the image. - imageStamp: { id: 0x000A, type: ZCLDataTypes.uint32 }, // 10, Optional + imageStamp: { id: 0x000a, type: ZCLDataTypes.uint32 }, // 10, Optional // Indicates what behavior the client device supports for activating a fully // downloaded but not installed upgrade image. - upgradeActivationPolicy: { // Optional - id: 0x000B, // 11 + // Optional + upgradeActivationPolicy: { + id: 0x000b, // 11 type: ZCLDataTypes.enum8({ otaServerActivationAllowed: 0x00, outOfBandActivationOnly: 0x01, @@ -79,8 +81,9 @@ const ATTRIBUTES = { // Dictates the behavior of the device in situations where an explicit activation // command cannot be retrieved. - upgradeTimeoutPolicy: { // Optional - id: 0x000C, // 12 + // Optional + upgradeTimeoutPolicy: { + id: 0x000c, // 12 type: ZCLDataTypes.enum8({ applyUpgradeAfterTimeout: 0x00, doNotApplyUpgradeAfterTimeout: 0x01, @@ -128,7 +131,8 @@ const COMMANDS = { // The purpose of sending Image Notify command is so the server has a way to // notify client devices of when the OTA upgrade images are available for them. - imageNotify: { // Optional + // Optional + imageNotify: { id: 0x0000, direction: Cluster.DIRECTION_SERVER_TO_CLIENT, encodeMissingFieldsBehavior: 'skip', @@ -153,7 +157,8 @@ const COMMANDS = { // --- Client to Server Commands --- // Client queries the server if new OTA upgrade image is available. - queryNextImageRequest: { // Mandatory + // Mandatory + queryNextImageRequest: { id: 0x0001, encodeMissingFieldsBehavior: 'skip', args: { @@ -179,14 +184,12 @@ const COMMANDS = { }, // Client requests a block of data from the OTA upgrade image. - imageBlockRequest: { // Mandatory + // Mandatory + imageBlockRequest: { id: 0x0003, encodeMissingFieldsBehavior: 'skip', args: { - fieldControl: ZCLDataTypes.map8( - 'requestNodeAddressPresent', - 'minimumBlockPeriodPresent', - ), + fieldControl: ZCLDataTypes.map8('requestNodeAddressPresent', 'minimumBlockPeriodPresent'), manufacturerCode: ZCLDataTypes.uint16, imageType: ZCLDataTypes.uint16, fileVersion: ZCLDataTypes.uint32, @@ -203,7 +206,8 @@ const COMMANDS = { // Client requests pages of data from the OTA upgrade image. Using Image Page // Request reduces the number of requests sent from the client to the upgrade // server, compared to using Image Block Request command. - imagePageRequest: { // Optional + // Optional + imagePageRequest: { id: 0x0004, encodeMissingFieldsBehavior: 'skip', args: { @@ -221,7 +225,8 @@ const COMMANDS = { response: IMAGE_BLOCK_RESPONSE, }, - imageBlockResponse: { // Mandatory + // Mandatory + imageBlockResponse: { ...IMAGE_BLOCK_RESPONSE, direction: Cluster.DIRECTION_SERVER_TO_CLIENT, frameControl: ['directionToClient', 'clusterSpecific', 'disableDefaultResponse'], @@ -229,7 +234,8 @@ const COMMANDS = { // Sent by the client when it has completed downloading an image. The status // value SHALL be SUCCESS, INVALID_IMAGE, REQUIRE_MORE_IMAGE, or ABORT. - upgradeEndRequest: { // Mandatory + // Mandatory + upgradeEndRequest: { id: 0x0006, args: { status: ZCLDataTypes.enum8Status, @@ -244,7 +250,8 @@ const COMMANDS = { // Response to the Upgrade End Request, indicating when the client should upgrade // to the new image. - upgradeEndResponse: { // Mandatory + // Mandatory + upgradeEndResponse: { ...UPGRADE_END_RESPONSE, direction: Cluster.DIRECTION_SERVER_TO_CLIENT, frameControl: ['directionToClient', 'clusterSpecific', 'disableDefaultResponse'], @@ -252,7 +259,8 @@ const COMMANDS = { // Client requests a device specific file such as security credential, // configuration or log. - queryDeviceSpecificFileRequest: { // Optional + // Optional + queryDeviceSpecificFileRequest: { id: 0x0008, args: { requestNodeAddress: ZCLDataTypes.EUI64, @@ -274,11 +282,9 @@ const COMMANDS = { }, }, }, - }; class OTACluster extends Cluster { - static get ID() { return 0x0019; // 25 } @@ -294,7 +300,6 @@ class OTACluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(OTACluster); diff --git a/lib/clusters/pollControl.js b/lib/clusters/pollControl.js index a29aa485..681f9f0d 100644 --- a/lib/clusters/pollControl.js +++ b/lib/clusters/pollControl.js @@ -30,7 +30,6 @@ const COMMANDS = { }; class PollControlCluster extends Cluster { - static get ID() { return 32; // 0x0020 } @@ -46,7 +45,6 @@ class PollControlCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(PollControlCluster); diff --git a/lib/clusters/powerConfiguration.js b/lib/clusters/powerConfiguration.js index 7123b598..5ce20a95 100644 --- a/lib/clusters/powerConfiguration.js +++ b/lib/clusters/powerConfiguration.js @@ -65,7 +65,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class PowerConfigurationCluster extends Cluster { - static get ID() { return 1; } @@ -81,7 +80,6 @@ class PowerConfigurationCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(PowerConfigurationCluster); diff --git a/lib/clusters/powerProfile.js b/lib/clusters/powerProfile.js index a26a098f..e386dd5b 100644 --- a/lib/clusters/powerProfile.js +++ b/lib/clusters/powerProfile.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class PowerProfileCluster extends Cluster { - static get ID() { return 26; } @@ -24,7 +22,6 @@ class PowerProfileCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(PowerProfileCluster); diff --git a/lib/clusters/pressureMeasurement.js b/lib/clusters/pressureMeasurement.js index 4b8dbc47..92690122 100644 --- a/lib/clusters/pressureMeasurement.js +++ b/lib/clusters/pressureMeasurement.js @@ -18,7 +18,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class PressureMeasurementCluster extends Cluster { - static get ID() { return 1027; } @@ -34,7 +33,6 @@ class PressureMeasurementCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(PressureMeasurementCluster); diff --git a/lib/clusters/pumpConfigurationAndControl.js b/lib/clusters/pumpConfigurationAndControl.js index 3fd832c2..f69691e0 100644 --- a/lib/clusters/pumpConfigurationAndControl.js +++ b/lib/clusters/pumpConfigurationAndControl.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class PumpConfigurationAndControlCluster extends Cluster { - static get ID() { return 512; } @@ -24,7 +22,6 @@ class PumpConfigurationAndControlCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(PumpConfigurationAndControlCluster); diff --git a/lib/clusters/relativeHumidity.js b/lib/clusters/relativeHumidity.js index 526947c8..8f18fcbf 100644 --- a/lib/clusters/relativeHumidity.js +++ b/lib/clusters/relativeHumidity.js @@ -13,7 +13,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class RelativeHumidityCluster extends Cluster { - static get ID() { return 1029; } @@ -29,7 +28,6 @@ class RelativeHumidityCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(RelativeHumidityCluster); diff --git a/lib/clusters/scenes.js b/lib/clusters/scenes.js index c15deaac..4c56bb19 100644 --- a/lib/clusters/scenes.js +++ b/lib/clusters/scenes.js @@ -7,7 +7,6 @@ const ATTRIBUTES = {}; const COMMANDS = {}; class ScenesCluster extends Cluster { - static get ID() { return 5; } @@ -23,7 +22,6 @@ class ScenesCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(ScenesCluster); diff --git a/lib/clusters/shadeConfiguration.js b/lib/clusters/shadeConfiguration.js index 3ede3b26..939308c8 100644 --- a/lib/clusters/shadeConfiguration.js +++ b/lib/clusters/shadeConfiguration.js @@ -2,13 +2,11 @@ const Cluster = require('../Cluster'); -const ATTRIBUTES = { -}; +const ATTRIBUTES = {}; const COMMANDS = {}; class ShadeConfigurationCluster extends Cluster { - static get ID() { return 256; } @@ -24,7 +22,6 @@ class ShadeConfigurationCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(ShadeConfigurationCluster); diff --git a/lib/clusters/temperatureMeasurement.js b/lib/clusters/temperatureMeasurement.js index c5f8510b..b0f8ac8d 100644 --- a/lib/clusters/temperatureMeasurement.js +++ b/lib/clusters/temperatureMeasurement.js @@ -12,7 +12,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class TemperatureMeasurement extends Cluster { - static get ID() { return 1026; // 0x0402 } @@ -28,7 +27,6 @@ class TemperatureMeasurement extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(TemperatureMeasurement); diff --git a/lib/clusters/thermostat.js b/lib/clusters/thermostat.js index e8d73ce7..47101aed 100644 --- a/lib/clusters/thermostat.js +++ b/lib/clusters/thermostat.js @@ -23,7 +23,10 @@ const ATTRIBUTES = { minCoolSetpointLimit: { id: 23, type: ZCLDataTypes.int16 }, maxCoolSetpointLimit: { id: 24, type: ZCLDataTypes.int16 }, minSetpointDeadBand: { id: 25, type: ZCLDataTypes.int8 }, - remoteSensing: { id: 26, type: ZCLDataTypes.map8('localTemperature', 'outdoorTemperature', 'occupancy') }, + remoteSensing: { + id: 26, + type: ZCLDataTypes.map8('localTemperature', 'outdoorTemperature', 'occupancy'), + }, controlSequenceOfOperation: { id: 27, type: ZCLDataTypes.enum8({ @@ -49,7 +52,10 @@ const ATTRIBUTES = { sleep: 9, }), }, - alarmMask: { id: 29, type: ZCLDataTypes.map8('initializationFailure', 'hardwareFailure', 'selfCalibrationFailure') }, + alarmMask: { + id: 29, + type: ZCLDataTypes.map8('initializationFailure', 'hardwareFailure', 'selfCalibrationFailure'), + }, runningMode: { id: 30, type: ZCLDataTypes.enum8({ @@ -75,7 +81,6 @@ const COMMANDS = { }; class ThermostatCluster extends Cluster { - static get ID() { return 513; } @@ -91,7 +96,6 @@ class ThermostatCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(ThermostatCluster); diff --git a/lib/clusters/thermostatUserInterfaceConfiguration.js b/lib/clusters/thermostatUserInterfaceConfiguration.js index 09531e39..74ae5c3f 100644 --- a/lib/clusters/thermostatUserInterfaceConfiguration.js +++ b/lib/clusters/thermostatUserInterfaceConfiguration.js @@ -34,7 +34,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class ThermostatUserInterfaceConfigurationCluster extends Cluster { - static get ID() { return 516; } @@ -50,7 +49,6 @@ class ThermostatUserInterfaceConfigurationCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(ThermostatUserInterfaceConfigurationCluster); diff --git a/lib/clusters/time.js b/lib/clusters/time.js index bf2d8242..2bf0283e 100644 --- a/lib/clusters/time.js +++ b/lib/clusters/time.js @@ -5,7 +5,10 @@ const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = { time: { id: 0, type: ZCLDataTypes.UTC }, - timeStatus: { id: 1, type: ZCLDataTypes.map8('master', 'synchronized', 'masterZoneDst', 'superseding') }, + timeStatus: { + id: 1, + type: ZCLDataTypes.map8('master', 'synchronized', 'masterZoneDst', 'superseding'), + }, timeZone: { id: 2, type: ZCLDataTypes.int32 }, dstStart: { id: 3, type: ZCLDataTypes.uint32 }, dstEnd: { id: 4, type: ZCLDataTypes.uint32 }, @@ -19,7 +22,6 @@ const ATTRIBUTES = { const COMMANDS = {}; class TimeCluster extends Cluster { - static get ID() { return 10; // 0xA } @@ -35,7 +37,6 @@ class TimeCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(TimeCluster); diff --git a/lib/clusters/touchlink.js b/lib/clusters/touchlink.js index c548da4e..407aafed 100644 --- a/lib/clusters/touchlink.js +++ b/lib/clusters/touchlink.js @@ -16,17 +16,18 @@ const COMMANDS = { args: { total: ZCLDataTypes.uint8, startIndex: ZCLDataTypes.uint8, - groups: ZCLDataTypes.Array8(ZCLStruct('TLLGroupResponse', { - groupId: ZCLDataTypes.uint16, - groupType: ZCLDataTypes.uint8, - })), + groups: ZCLDataTypes.Array8( + ZCLStruct('TLLGroupResponse', { + groupId: ZCLDataTypes.uint16, + groupType: ZCLDataTypes.uint8, + }), + ), }, }, }, }; class TouchlinkCluster extends Cluster { - static get ID() { return 4096; // 0x1000 } @@ -42,7 +43,6 @@ class TouchlinkCluster extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(TouchlinkCluster); diff --git a/lib/clusters/windowCovering.js b/lib/clusters/windowCovering.js index 3e88aa9a..32f194e3 100644 --- a/lib/clusters/windowCovering.js +++ b/lib/clusters/windowCovering.js @@ -5,7 +5,8 @@ const { ZCLDataTypes } = require('../zclTypes'); const ATTRIBUTES = { // Window Covering Information (0x0000 - 0x000F) - windowCoveringType: { // Mandatory + // Mandatory + windowCoveringType: { id: 0x0000, type: ZCLDataTypes.enum8({ rollershade: 0, @@ -26,7 +27,8 @@ const ATTRIBUTES = { currentPositionTilt: { id: 0x0004, type: ZCLDataTypes.uint16 }, // Optional numberofActuationsLift: { id: 0x0005, type: ZCLDataTypes.uint16 }, // Optional numberofActuationsTilt: { id: 0x0006, type: ZCLDataTypes.uint16 }, // Optional - configStatus: { // Mandatory + // Mandatory + configStatus: { id: 0x0007, type: ZCLDataTypes.map8( 'operational', @@ -51,7 +53,8 @@ const ATTRIBUTES = { velocityLift: { id: 0x0014, type: ZCLDataTypes.uint16 }, // 20, Optional accelerationTimeLift: { id: 0x0015, type: ZCLDataTypes.uint16 }, // 21, Optional decelerationTimeLift: { id: 0x0016, type: ZCLDataTypes.uint16 }, // 22, Optional - mode: { // Mandatory + // Mandatory + mode: { id: 0x0017, // 23 type: ZCLDataTypes.map8( 'motorDirectionReversed', @@ -69,25 +72,29 @@ const COMMANDS = { upOpen: { id: 0x0000 }, // Mandatory downClose: { id: 0x0001 }, // Mandatory stop: { id: 0x0002 }, // Mandatory - goToLiftValue: { // Optional + // Optional + goToLiftValue: { id: 0x0004, args: { liftValue: ZCLDataTypes.uint16, }, }, - goToLiftPercentage: { // Optional + // Optional + goToLiftPercentage: { id: 0x0005, args: { percentageLiftValue: ZCLDataTypes.uint8, }, }, - goToTiltValue: { // Optional + // Optional + goToTiltValue: { id: 0x0007, args: { tiltValue: ZCLDataTypes.uint16, }, }, - goToTiltPercentage: { // Optional + // Optional + goToTiltPercentage: { id: 0x0008, args: { percentageTiltValue: ZCLDataTypes.uint8, @@ -96,7 +103,6 @@ const COMMANDS = { }; class WindowCovering extends Cluster { - static get ID() { return 0x0102; // 258 } @@ -112,7 +118,6 @@ class WindowCovering extends Cluster { static get COMMANDS() { return COMMANDS; } - } Cluster.addCluster(WindowCovering); diff --git a/lib/util/index.js b/lib/util/index.js index 5343125a..6d8d2a04 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -5,9 +5,10 @@ const debug = require('debug')('zigbee-clusters'); function getPropertyDescriptor(obj, name) { if (!obj) return; - // eslint-disable-next-line consistent-return - return Object.getOwnPropertyDescriptor(obj, name) - || getPropertyDescriptor(Object.getPrototypeOf(obj), name); + return ( + Object.getOwnPropertyDescriptor(obj, name) || + getPropertyDescriptor(Object.getPrototypeOf(obj), name) + ); } /** @@ -22,12 +23,10 @@ function getLogId(endpointId, clusterName, clusterId) { } class ZCLError extends Error { - constructor(zclStatus = 'FAILURE') { super(`ZCL Error: ${zclStatus}`); this.zclStatus = zclStatus; } - } module.exports = { diff --git a/lib/zclFrames.js b/lib/zclFrames.js index 4de85b81..9b0c3949 100644 --- a/lib/zclFrames.js +++ b/lib/zclFrames.js @@ -2,7 +2,13 @@ const { ZCLDataType, ZCLDataTypes, ZCLStruct } = require('./zclTypes'); -const ZCLFrameControlBitmap = ZCLDataTypes.map8('clusterSpecific', null, 'manufacturerSpecific', 'directionToClient', 'disableDefaultResponse'); +const ZCLFrameControlBitmap = ZCLDataTypes.map8( + 'clusterSpecific', + null, + 'manufacturerSpecific', + 'directionToClient', + 'disableDefaultResponse', +); const ZCLStandardHeader = ZCLStruct('ZCLStandardHeader', { frameControl: ZCLFrameControlBitmap, @@ -32,242 +38,278 @@ const ZCLConfigureReportingRecordStruct = ZCLStruct('ConfigureReportingRecord', timeoutPeriod: ZCLDataTypes.uint16, }); -const ZCLAttributeDataRecord = (withStatus, attributes) => new ZCLDataType(NaN, 'attributeRecord', -3, ((buf, v, i) => { - const startByte = i; - i += ZCLDataTypes.uint16.toBuffer(buf, v.id, i); - if (withStatus) { - i += ZCLDataTypes.enum8Status.toBuffer(buf, v.status, i); - } - if (!withStatus || v.status === 'SUCCESS') { - i += ZCLDataTypes.uint8.toBuffer(buf, attributes[v.id].type.id, i); - i += attributes[v.id].type.toBuffer(buf, v.value, i); - } - return i - startByte; -}), function fromBuf(buf, i, returnLength) { - i = i || 0; - const startByte = i; - const res = {}; - if (buf.length >= i + Math.abs(this.length)) { - res.id = ZCLDataTypes.uint16.fromBuffer(buf, i); - i += ZCLDataTypes.uint16.length; - - if (withStatus) { - res.status = ZCLDataTypes.enum8Status.fromBuffer(buf, i); - i += ZCLDataTypes.enum8Status.length; - } - - if (!withStatus || res.status === 'SUCCESS') { - const dataTypeId = ZCLDataTypes.uint8.fromBuffer(buf, i); - i += ZCLDataTypes.uint8.length; - - // don't use the attribute's type if the type in the data is 0 (noData). - // This breaks when the attribute ID is 0 - const DataType = attributes[res.id] && dataTypeId !== 0 - ? attributes[res.id].type - : Object.values(ZCLDataTypes).find(type => type && type.id === dataTypeId); - if (!DataType) throw new TypeError(`Invalid Type for Attribute: ${res.id}`); - - if (attributes[res.id]) { - res.name = attributes[res.id].name || `unknown_attr_${res.id}`; +const ZCLAttributeDataRecord = (withStatus, attributes) => + new ZCLDataType( + NaN, + 'attributeRecord', + -3, + (buf, v, i) => { + const startByte = i; + i += ZCLDataTypes.uint16.toBuffer(buf, v.id, i); + if (withStatus) { + i += ZCLDataTypes.enum8Status.toBuffer(buf, v.status, i); } - - const entry = DataType.fromBuffer(buf, i, true); - if (DataType.length > 0) { - i += DataType.length; - res.value = entry; - } else { - res.value = entry.result; - i += entry.length; + if (!withStatus || v.status === 'SUCCESS') { + i += ZCLDataTypes.uint8.toBuffer(buf, attributes[v.id].type.id, i); + i += attributes[v.id].type.toBuffer(buf, v.value, i); } - } - } - if (returnLength) { - return { result: res, length: i - startByte }; - } - return res; -}); + return i - startByte; + }, + function fromBuf(buf, i, returnLength) { + i = i || 0; + const startByte = i; + const res = {}; + if (buf.length >= i + Math.abs(this.length)) { + res.id = ZCLDataTypes.uint16.fromBuffer(buf, i); + i += ZCLDataTypes.uint16.length; + + if (withStatus) { + res.status = ZCLDataTypes.enum8Status.fromBuffer(buf, i); + i += ZCLDataTypes.enum8Status.length; + } -const ZCLConfigureReportingRecords = ({ withStatus } = {}) => new ZCLDataType( - NaN, - 'configureReportingRecords', - -0, - ((buf, value, i) => { - // toBuffer - const startByte = i; + if (!withStatus || res.status === 'SUCCESS') { + const dataTypeId = ZCLDataTypes.uint8.fromBuffer(buf, i); + i += ZCLDataTypes.uint8.length; - // Loop each configure reporting record - for (const configureReportingRecord of value) { - // Remove the minChange property (because its size will vary) - const { minChange, direction } = configureReportingRecord; + // don't use the attribute's type if the type in the data is 0 (noData). + // This breaks when the attribute ID is 0 + const DataType = + attributes[res.id] && dataTypeId !== 0 + ? attributes[res.id].type + : Object.values(ZCLDataTypes).find((type) => type && type.id === dataTypeId); + if (!DataType) throw new TypeError(`Invalid Type for Attribute: ${res.id}`); - // Check if this record is expected to have a status field - if (withStatus) { - ZCLDataTypes.enum8Status.toBuffer(buf, configureReportingRecord.status, i); - i += ZCLDataTypes.enum8Status.length; - } + if (attributes[res.id]) { + res.name = attributes[res.id].name || `unknown_attr_${res.id}`; + } - ZCLConfigureReportingRecordStruct.fields.direction - .toBuffer(buf, configureReportingRecord.direction, i); - i += ZCLConfigureReportingRecordStruct.fields.direction.length; + const entry = DataType.fromBuffer(buf, i, true); + if (DataType.length > 0) { + i += DataType.length; + res.value = entry; + } else { + res.value = entry.result; + i += entry.length; + } + } + } + if (returnLength) { + return { result: res, length: i - startByte }; + } + return res; + }, + ); + +const ZCLConfigureReportingRecords = ({ withStatus } = {}) => + new ZCLDataType( + NaN, + 'configureReportingRecords', + -0, + (buf, value, i) => { + // toBuffer + const startByte = i; + + // Loop each configure reporting record + for (const configureReportingRecord of value) { + // Remove the minChange property (because its size will vary) + const { minChange, direction } = configureReportingRecord; + + // Check if this record is expected to have a status field + if (withStatus) { + ZCLDataTypes.enum8Status.toBuffer(buf, configureReportingRecord.status, i); + i += ZCLDataTypes.enum8Status.length; + } - ZCLConfigureReportingRecordStruct.fields.attributeId - .toBuffer(buf, configureReportingRecord.attributeId, i); - i += ZCLConfigureReportingRecordStruct.fields.attributeId.length; + ZCLConfigureReportingRecordStruct.fields.direction.toBuffer( + buf, + configureReportingRecord.direction, + i, + ); + i += ZCLConfigureReportingRecordStruct.fields.direction.length; + + ZCLConfigureReportingRecordStruct.fields.attributeId.toBuffer( + buf, + configureReportingRecord.attributeId, + i, + ); + i += ZCLConfigureReportingRecordStruct.fields.attributeId.length; + + // Nothing further to parse if it was not a success + if (withStatus && configureReportingRecord.status !== 'SUCCESS') { + continue; + } - // Nothing further to parse if it was not a success - if (withStatus && configureReportingRecord.status !== 'SUCCESS') { - continue; + if (direction === 'reported') { + // Determine the type of the minChange property (equal to attributeDataType of this record) + const minChangeDataType = Object.values(ZCLDataTypes).find( + (DataType) => DataType.id === configureReportingRecord.attributeDataType, + ); + + ZCLConfigureReportingRecordStruct.fields.attributeDataType.toBuffer( + buf, + configureReportingRecord.attributeDataType, + i, + ); + i += ZCLConfigureReportingRecordStruct.fields.attributeDataType.length; + + ZCLConfigureReportingRecordStruct.fields.minInterval.toBuffer( + buf, + configureReportingRecord.minInterval, + i, + ); + i += ZCLConfigureReportingRecordStruct.fields.minInterval.length; + + ZCLConfigureReportingRecordStruct.fields.maxInterval.toBuffer( + buf, + configureReportingRecord.maxInterval, + i, + ); + i += ZCLConfigureReportingRecordStruct.fields.maxInterval.length; + + if (minChangeDataType && typeof minChange === 'number') { + minChangeDataType.toBuffer(buf, minChange, i); + i += minChangeDataType.length; + } + } else { + ZCLConfigureReportingRecordStruct.fields.timeoutPeriod.toBuffer( + buf, + configureReportingRecord.timeoutPeriod, + i, + ); + i += ZCLConfigureReportingRecordStruct.fields.timeoutPeriod.length; + } } - if (direction === 'reported') { - // Determine the type of the minChange property (equal to attributeDataType of this record) - const minChangeDataType = Object.values(ZCLDataTypes) - .find(DataType => DataType.id === configureReportingRecord.attributeDataType); + return i - startByte; + }, + (buf, i, returnLength) => { + // fromBuffer + i = i || 0; + // Keep a reference to the current buffer index while reading it + const startByte = i; + const res = []; + + // Read the entire buffer + while (buf.length > i) { + // Parse status only if part of record struct (the read configuration response has a + // status field whereas the configure reporting command does not) + let status; + + // Check if this record is expected to have a status field + if (withStatus) { + status = ZCLDataTypes.enum8Status.fromBuffer(buf, i); + i += ZCLDataTypes.enum8Status.length; + } - ZCLConfigureReportingRecordStruct.fields.attributeDataType - .toBuffer(buf, configureReportingRecord.attributeDataType, i); - i += ZCLConfigureReportingRecordStruct.fields.attributeDataType.length; + // Parse direction + const direction = ZCLConfigureReportingRecordStruct.fields.direction.fromBuffer(buf, i); + i += 1; - ZCLConfigureReportingRecordStruct.fields.minInterval - .toBuffer(buf, configureReportingRecord.minInterval, i); - i += ZCLConfigureReportingRecordStruct.fields.minInterval.length; + // Parse attributeId + const attributeId = ZCLConfigureReportingRecordStruct.fields.attributeId.fromBuffer(buf, i); + i += 2; - ZCLConfigureReportingRecordStruct.fields.maxInterval - .toBuffer(buf, configureReportingRecord.maxInterval, i); - i += ZCLConfigureReportingRecordStruct.fields.maxInterval.length; + // Check if the status is success, only then we need to continue parsing for other values + if (withStatus && status !== 'SUCCESS') { + // Buffer parsing is complete + res.push({ status, direction, attributeId }); - if (minChangeDataType && typeof minChange === 'number') { - minChangeDataType.toBuffer(buf, minChange, i); - i += minChangeDataType.length; + // Continue reading the buffer in a next iteration + continue; } - } else { - ZCLConfigureReportingRecordStruct.fields.timeoutPeriod - .toBuffer(buf, configureReportingRecord.timeoutPeriod, i); - i += ZCLConfigureReportingRecordStruct.fields.timeoutPeriod.length; - } - } - - return i - startByte; - }), ((buf, i, returnLength) => { - // fromBuffer - i = i || 0; - // Keep a reference to the current buffer index while reading it - const startByte = i; - const res = []; - - // Read the entire buffer - while (buf.length > i) { - // Parse status only if part of record struct (the read configuration response has a - // status field whereas the configure reporting command does not) - let status; - - // Check if this record is expected to have a status field - if (withStatus) { - status = ZCLDataTypes.enum8Status.fromBuffer(buf, i); - i += ZCLDataTypes.enum8Status.length; - } - // Parse direction - const direction = ZCLConfigureReportingRecordStruct.fields.direction.fromBuffer(buf, i); - i += 1; + switch (direction) { + // Only if the direction is 'reported' are the minInterval/maxInterval and minChange + // properties available + case 'reported': { + // Parse attributeDataType, we need this to find the respective ZCLDataType in the + // next step + const attributeDataType = + ZCLConfigureReportingRecordStruct.fields.attributeDataType.fromBuffer(buf, i); + i += 1; + + // Find the respective ZCLDataType, we need it later on to determine if the data type + // is analog or discrete + const parsedAttributeDataType = Object.values(ZCLDataTypes).find( + (x) => x.id === attributeDataType, + ); + + // Parse minInterval + const minInterval = ZCLDataTypes.uint16.fromBuffer(buf, i); + i += 2; + + // Parse maxInterval + const maxInterval = ZCLDataTypes.uint16.fromBuffer(buf, i); + i += 2; + + // If the ZCLDataType is not analog there will be no minChange field + if (!parsedAttributeDataType.isAnalog) { + const resultRecord = { + direction, + attributeId, + attributeDataType, + minInterval, + maxInterval, + }; + if (withStatus) resultRecord.status = status; + res.push(resultRecord); + + // Continue reading the buffer in a next iteration + continue; + } + + // Apparently the ZCLDataType is analog so we should parse the minChange field + const minChange = ZCLDataTypes[parsedAttributeDataType.shortName].fromBuffer(buf, i); + i += parsedAttributeDataType.length; - // Parse attributeId - const attributeId = ZCLConfigureReportingRecordStruct.fields.attributeId.fromBuffer(buf, i); - i += 2; - - // Check if the status is success, only then we need to continue parsing for other values - if (withStatus && status !== 'SUCCESS') { - // Buffer parsing is complete - res.push({ status, direction, attributeId }); - - // Continue reading the buffer in a next iteration - continue; - } - - // eslint-disable-next-line default-case - switch (direction) { - // Only if the direction is 'reported' are the minInterval/maxInterval and minChange - // properties available - case 'reported': { - // Parse attributeDataType, we need this to find the respective ZCLDataType in the - // next step - const attributeDataType = ZCLConfigureReportingRecordStruct.fields.attributeDataType - .fromBuffer(buf, i); - i += 1; - - // Find the respective ZCLDataType, we need it later on to determine if the data type - // is analog or discrete - const parsedAttributeDataType = Object.values(ZCLDataTypes) - .find(x => x.id === attributeDataType); - - // Parse minInterval - const minInterval = ZCLDataTypes.uint16.fromBuffer(buf, i); - i += 2; - - // Parse maxInterval - const maxInterval = ZCLDataTypes.uint16.fromBuffer(buf, i); - i += 2; - - // If the ZCLDataType is not analog there will be no minChange field - if (!parsedAttributeDataType.isAnalog) { const resultRecord = { - direction, attributeId, attributeDataType, minInterval, maxInterval, + direction, + attributeId, + attributeDataType, + minInterval, + maxInterval, + minChange, }; + if (withStatus) resultRecord.status = status; res.push(resultRecord); - // Continue reading the buffer in a next iteration - continue; + // Buffer parsing is complete + break; } - // Apparently the ZCLDataType is analog so we should parse the minChange field - const minChange = ZCLDataTypes[parsedAttributeDataType.shortName] - .fromBuffer(buf, i); - i += parsedAttributeDataType.length; - - const resultRecord = { - direction, - attributeId, - attributeDataType, - minInterval, - maxInterval, - minChange, - }; - - if (withStatus) resultRecord.status = status; - res.push(resultRecord); - - // Buffer parsing is complete - break; - } - - // If the direction is 'received' we only have to parse the - case 'received': { - // timeoutPeriod - // Parse timeout period - const timeoutPeriod = ZCLConfigureReportingRecordStruct.fields.timeoutPeriod - .fromBuffer(buf, i); - i += 2; + // If the direction is 'received' we only have to parse the + case 'received': { + // timeoutPeriod + // Parse timeout period + const timeoutPeriod = ZCLConfigureReportingRecordStruct.fields.timeoutPeriod.fromBuffer( + buf, + i, + ); + i += 2; - const resultRecord = { - direction, attributeId, timeoutPeriod, - }; + const resultRecord = { + direction, + attributeId, + timeoutPeriod, + }; - if (withStatus) resultRecord.status = status; - res.push(resultRecord); + if (withStatus) resultRecord.status = status; + res.push(resultRecord); - // Buffer parsing is complete - break; + // Buffer parsing is complete + break; + } } } - } - if (returnLength) { - return { result: res, length: i - startByte }; - } - return res; - }), -); + if (returnLength) { + return { result: res, length: i - startByte }; + } + return res; + }, + ); module.exports = { ZCLStandardHeader, diff --git a/lib/zclTypes.js b/lib/zclTypes.js index e52bc98a..e8706977 100644 --- a/lib/zclTypes.js +++ b/lib/zclTypes.js @@ -6,7 +6,7 @@ const ZCLDataType = DataType; const ZCLDataTypes = DataTypes; const ZCLStruct = Struct; -/* eslint-disable */ +// prettier-ignore ZCLDataTypes.enum8Status = ZCLDataTypes.enum8({ SUCCESS : 0x00, FAILURE : 0x01, @@ -44,7 +44,6 @@ ZCLDataTypes.enum8Status = ZCLDataTypes.enum8({ CALIBRATION_ERROR : 0xc2, UNSUPPORTED_CLUSTER : 0xc3, }); -/* eslint-enable */ module.exports = { ZCLDataTypes, diff --git a/package-lock.json b/package-lock.json index ce49eb31..7aa15111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "zigbee-clusters", "version": "3.8.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -14,19 +14,14 @@ }, "devDependencies": { "@athombv/jsdoc-template": "^1.7.0", + "@eslint/js": "^10.0.1", "@types/node": "^25.0.10", - "@types/sinon": "^17.0.3", - "concurrently": "^5.2.0", - "eslint": "^6.8.0", - "eslint-config-athom": "^2.1.0", - "jsdoc": "^3.6.7", - "jsdoc-ts-utils": "^2.0.0", - "mocha": "^10.1.0", - "serve": "^14.0.1", - "sinon": "^19.0.2", - "tsx": "^4.21.0", - "typescript": "^5.9.3", - "watch": "^1.0.2" + "eslint": "^10.13.0", + "globals": "^17.13.0", + "jsdoc": "^4.0.5", + "jsdoc-ts-utils": "^6.0.0", + "prettier": "^3.9.10", + "typescript": "^5.9.3" }, "engines": { "node": ">=22" @@ -53,84 +48,35 @@ "taffydb": "^2.7.3" } }, - "node_modules/@athombv/jsdoc-template/node_modules/taffydb": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", - "integrity": "sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg==", - "dev": true - }, - "node_modules/@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.8.3" - } - }, - "node_modules/@babel/generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz", - "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz", - "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.9.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -138,923 +84,598 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/template/node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "node_modules/@babel/template/node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/parser": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz", - "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@babel/traverse": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz", - "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.10.4" + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "node_modules/@babel/traverse/node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "hashery": "^1.5.1", + "keyv": "^5.6.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/parser": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz", - "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/types": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz", - "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "node_modules/@babel/types/node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "cpu": [ - "ppc64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=18" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": "18 || 20 || >=22" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "balanced-match": "^4.0.2" + }, "engines": { - "node": ">=18" + "node": "20 || >=22" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, "engines": { - "node": ">=18" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/plugin-kit": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", + "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "cpu": [ - "ia32" - ], + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { - "node": ">=18" + "node": ">=18.18.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "cpu": [ - "loong64" - ], + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, "engines": { - "node": ">=18" + "node": ">=18.18.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "cpu": [ - "mips64el" - ], + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=18.18.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "cpu": [ - "riscv64" - ], + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "cpu": [ - "s390x" - ], + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "cpu": [ - "x64" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "peer": true, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "cpu": [ - "x64" - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } + "peer": true }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "cpu": [ - "x64" - ], + "node_modules/@jsdoc/salty": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.12.tgz", + "integrity": "sha512-TuB0x50EoAvEX/UEWITd8Mkn3WhiTjSvbTMCLj0BhsQEl5iUzjXdA0bETEVpTk+5TGTLR6QktI9H4hLviVeaAQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.18.1" + }, "engines": { - "node": ">=18" + "node": ">=v12.0.0" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "cpu": [ - "arm64" - ], + "node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, "engines": { - "node": ">=18" + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "cpu": [ - "x64" - ], + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "cpu": [ - "arm64" - ], + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "cpu": [ - "ia32" - ], + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "peer": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "peer": true + "license": "MIT" }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", - "dev": true + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" }, "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "25.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", - "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } + "license": "MIT" }, - "node_modules/@types/sinon": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", + "node_modules/@types/node": { + "version": "25.9.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.9.tgz", + "integrity": "sha512-b4e2xxj/yMeT2hNlD6x7zNFiQK2Dlmkb9CQ6v3/1G2RezKN4YS2lcEv8lzGm1mhs4f2lM4yNAMI/zUDBZBBt7w==", "dev": true, "license": "MIT", "dependencies": { - "@types/sinonjs__fake-timers": "*" + "undici-types": ">=7.24.0 <7.24.7" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -1063,6 +684,7 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, + "license": "BSD-3-Clause", "peer": true }, "node_modules/@xtuc/long": { @@ -1070,32 +692,15 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, + "license": "Apache-2.0", "peer": true }, - "node_modules/@zeit/schemas": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.21.0.tgz", - "integrity": "sha512-/J4WBTpWtQ4itN1rb3ao8LfClmVcmz2pO6oYb7Qd4h7VSqUhIbJIvrykz9Ew1WMg6eFWsKdsMHc5uPbFxqlCpg==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1104,19 +709,21 @@ } }, "node_modules/acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1128,10176 +735,1992 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, "peerDependencies": { - "ajv": "^6.9.1" + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "string-width": "^4.1.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "license": "MIT", + "peer": true }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/baseline-browser-mapping": { + "version": "2.11.30", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.30.tgz", + "integrity": "sha512-YJs6Pz17RMNv8HoyKREtCY38E3BV1nPkWVmIb+XN1uHC1Vqt3KZCH/uJH9ZKRoiKb/icZ6tvehyee6RZNbFfRA==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "license": "Apache-2.0", + "peer": true, + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "node_modules/browserslist": { + "version": "4.29.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.4.tgz", + "integrity": "sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, "dependencies": { - "type-fest": "^0.11.0" + "baseline-browser-mapping": "^2.11.29", + "caniuse-lite": "^1.0.30001816", + "electron-to-chromium": "^1.5.459", + "node-releases": "^2.0.59", + "update-browserslist-db": "^1.3.4" }, - "engines": { - "node": ">=8" + "bin": { + "browserslist": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT", + "peer": true }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "node_modules/caniuse-lite": { + "version": "1.0.30001819", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001819.tgz", + "integrity": "sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==", "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" + "type": "opencollective", + "url": "https://opencollective.com/browserslist" }, { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "github", + "url": "https://github.com/sponsors/ai" } - ] - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + ], + "license": "CC-BY-4.0", + "peer": true }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dev": true, + "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" } }, - "node_modules/array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "node_modules/css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">= 0.4" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" } }, - "node_modules/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, "engines": { "node": ">=4" } }, - "node_modules/babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dev": true, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" + "ms": "^2.1.3" }, "engines": { - "node": ">=6" + "node": ">=6.0" }, - "peerDependencies": { - "eslint": ">= 4.12.1" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "node_modules/electron-to-chromium": { + "version": "1.5.463", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.463.tgz", + "integrity": "sha512-nVWNU6ltFjopvOdD44J4zoBkgO0M+WZiFKKFV7EjebOH9z0KNphk6bCEjplXtJofL21ARIuuwWOCsFkBVklm6w==", "dev": true, - "engines": { - "node": "*" - } + "license": "ISC", + "peer": true }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/boxen": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", - "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "node_modules/enhanced-resolve": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", + "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10.13.0" } }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" } }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/eslint": { + "version": "10.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.13.0.tgz", + "integrity": "sha512-UohDjD4zSzEwhf58M3O7vc/ycc8O1I7dNlhtD0WxE8Px8EHNJKtUwzBqrzeGhisRuv2ag4sAYswszCJRgKXYUg==", "dev": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "11.1.5 || >11.1.6 <12", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/boxen/node_modules/camelcase": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.0.tgz", - "integrity": "sha512-JToIvOmz6nhGsUhAYScbo2d6Py5wojjNfoxoc2mEVLUdJ70gJK2gnd+ABY1Tc3sVMyK7QDPtN0T/XdlCQWITyQ==", + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=14.16" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz", - "integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==", + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/boxen/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/eslint/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "18 || 20 || >=22" } }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "20 || >=22" } }, - "node_modules/boxen/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12.20" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boxen/node_modules/wrap-ansi": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", - "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "node_modules/eslint/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "brace-expansion": "^5.0.8" }, "engines": { - "node": ">=12" + "node": "18 || 20 || >=22" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "fill-range": "^7.0.1" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, + "license": "BSD-2-Clause", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" + "estraverse": "^5.2.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=4.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "peer": true - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.8" + "node": ">=4.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=6" + "node": ">=0.8.x" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001655", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", - "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz", + "integrity": "sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + "type": "github", + "url": "https://github.com/sponsors/fastify" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "opencollective", + "url": "https://opencollective.com/fastify" } ], + "license": "BSD-3-Clause", "peer": true }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "node_modules/file-entry-cache": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", "dev": true, + "license": "MIT", "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" + "flat-cache": "^6.1.23" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "node_modules/flat-cache": { + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" } }, - "node_modules/chalk-template/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=10.13.0" } }, - "node_modules/chalk-template/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/globals": { + "version": "17.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.13.0.tgz", + "integrity": "sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chalk-template/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } + "license": "ISC" }, - "node_modules/chalk-template/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/chalk-template/node_modules/has-flag": { + "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", + "peer": true, "engines": { "node": ">=8" } }, - "node_modules/chalk-template/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "hookified": "^1.15.0" }, "engines": { - "node": ">=8" + "node": ">=20" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } + "license": "MIT" }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, - "peer": true, + "license": "ISC", "engines": { - "node": ">=6.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.8.19" } }, - "node_modules/cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "node_modules/clipboardy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", - "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" - }, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/clipboardy/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { - "is-docker": "^2.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" + "node": ">=0.10.0" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "peer": true + "license": "ISC" }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "mime-db": ">= 1.43.0 < 2" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 10.13.0" } }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "ms": "2.0.0" + "xmlcreate": "^2.0.4" } }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concurrently": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.2.0.tgz", - "integrity": "sha512-XxcDbQ4/43d6CxR7+iV8IZXhur4KbmEJk1CetVMUqCy34z9l0DkszbY+/9wvmSnToTej0SYomc2WSRH+L0zVJw==", + "node_modules/jsdoc": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.5.tgz", + "integrity": "sha512-P4C6MWP9yIlMiK8nwoZvxN84vb6MsnXcHuy7XzVOvQoCizWX5JFCBsWIIWKXBltpoRZXddUOVQmCTOZt9yDj9g==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", - "tree-kill": "^1.2.2", - "yargs": "^13.3.0" + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" }, "bin": { - "concurrently": "bin/concurrently.js" + "jsdoc": "jsdoc.js" }, "engines": { - "node": ">=6.0.0" + "node": ">=12.0.0" } }, - "node_modules/confusing-browser-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", - "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", - "dev": true - }, - "node_modules/contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "node_modules/jsdoc-ts-utils": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-ts-utils/-/jsdoc-ts-utils-6.0.0.tgz", + "integrity": "sha512-iwYN06ZBtLfdl1KyhnDa+SXLHuQ8vwLTGY/M3cDGrczzPcWadj5XfCPMEUADSBX4ACjsc05IjD5vNePyUJEAIw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=20" + }, + "peerDependencies": { + "jsdoc": "*" } }, - "node_modules/content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">=4.8" + "node": ">=10" } }, - "node_modules/css-loader": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", - "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.27.0 || ^5.0.0" - } - }, - "node_modules/css-loader/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "node_modules/css-loader/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/css-loader/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "license": "MIT" }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/date-fns": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.14.0.tgz", - "integrity": "sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" + "json5": "lib/cli.js" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, "engines": { - "node": ">=4.0.0" + "node": ">=6" } }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, + "license": "MIT", "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" + "@keyv/serialize": "^1.1.1" } }, - "node_modules/doctrine": { + "node_modules/klaw": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "dev": true, + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", - "dev": true, - "peer": true - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" + "graceful-fs": "^4.1.9" } }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">= 0.8.0" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/linkify-it": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "uc.micro": "^2.0.0" } }, - "node_modules/es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, + "license": "MIT", "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.9.0" } }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true, - "peer": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "p-locate": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, - "engines": { - "node": ">=0.8.0" - } + "license": "MIT" }, - "node_modules/eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "node_modules/markdown-it": { + "version": "14.3.3", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.3.tgz", + "integrity": "sha512-L//tDAkjTjJCU6pBUSBTgs3Kg4InVaZuUZog/b6V12UKhcDQ7S78877ibbCanRExwPuYP1CZD7Gd2dxSy1GXRg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "argparse": "^2.0.1", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", - "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.9", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "eslint": "^5.16.0 || ^6.8.0 || ^7.2.0", - "eslint-plugin-import": "^2.21.2" + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/eslint-config-athom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-athom/-/eslint-config-athom-2.1.0.tgz", - "integrity": "sha512-e7rZyvqF+QEnfWXbDTGUnnqU5G7F1BsKYzwZYTEBEjtUmesj23S0mVFem4jg399iAzkn1IrhpaXAdeADUF7c1A==", + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", "dev": true, - "dependencies": { - "babel-eslint": "^10.0.3", - "eslint-config-airbnb-base": "^14.0.0", - "eslint-plugin-import": "^2.20.0", - "eslint-plugin-mocha": "^6.2.2", - "eslint-plugin-node": "^11.0.0" - }, - "engines": { - "node": ">=8.0.0" - }, + "license": "Unlicense", "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-es/node_modules/regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", - "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.3", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/eslint-plugin-mocha": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.3.0.tgz", - "integrity": "sha512-Cd2roo8caAyG21oKaaNTj7cqeYRWW1I2B5SfpKRp0Ip1gkfwoR1Ow0IGlPWnNjzywdF4n+kHL8/9vM6zCJUxdg==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "ramda": "^0.27.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "eslint": ">= 4.0.0" - } - }, - "node_modules/eslint-plugin-mocha/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-node/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", - "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", - "dev": true, - "dependencies": { - "estraverse": "^5.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", - "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "dependencies": { - "merge": "^1.2.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/execa/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dev": true, - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "dependencies": { - "flat-cache": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.7", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", - "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true - }, - "node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/inquirer/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/inquirer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-port-reachable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", - "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "dependencies": { - "xmlcreate": "^2.0.4" - } - }, - "node_modules/jsdoc": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", - "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.9.4", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsdoc-ts-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-ts-utils/-/jsdoc-ts-utils-2.0.0.tgz", - "integrity": "sha512-xTwLOGJ7K4xs1ZL+YHTl5cYHO2idNgY0FzRJPp/WCw7t61L2fU8odK5Hteos0B+1sEN+ZSLceoBfXXJnVJNokQ==", - "dev": true, - "dependencies": { - "jsdoc": "^3.6.6" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdoc/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jsdoc/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true, - "license": "MIT" - }, - "node_modules/klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it-anchor": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.5.tgz", - "integrity": "sha512-PI1qEHHkTNWT+X6Ip9w+paonfIQ+QZP9sCeMYi47oqhH+EsW8CrJ8J7CzV19QVOj6il8ATGbK2nTECj22ZHGvQ==", - "dev": true, - "peerDependencies": { - "@types/markdown-it": "*", - "markdown-it": "*" - } - }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/marked": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", - "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "node_modules/merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/mocha/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "peer": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/nise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", - "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.1", - "@sinonjs/text-encoding": "^0.7.3", - "just-extend": "^6.2.0", - "path-to-regexp": "^8.1.0" - } - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true, - "peer": true - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ramda": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz", - "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", - "dev": true, - "dependencies": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true, - "engines": { - "node": ">=6.5.0" - } - }, - "node_modules/registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", - "dev": true, - "dependencies": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", - "dev": true, - "dependencies": { - "rc": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", - "dev": true, - "dependencies": { - "is-promise": "^2.1.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/serve/-/serve-14.1.2.tgz", - "integrity": "sha512-luwVfJwbeE7dhCKeRU0vIBpt4bXdbAfzwsWJIQ5eqrIW2e+4nLWXbSlZ0WzelSFHQq+FlueOW6dr90jEewS9zw==", - "dev": true, - "dependencies": { - "@zeit/schemas": "2.21.0", - "ajv": "8.11.0", - "arg": "5.0.2", - "boxen": "7.0.0", - "chalk": "5.0.1", - "chalk-template": "0.4.0", - "clipboardy": "3.0.0", - "compression": "1.7.4", - "is-port-reachable": "4.0.0", - "serve-handler": "6.1.5", - "update-check": "1.5.4" - }, - "bin": { - "serve": "build/main.js" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", - "dev": true, - "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" - } - }, - "node_modules/serve-handler/node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-handler/node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, - "dependencies": { - "mime-db": "~1.33.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve/node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/serve/node_modules/chalk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", - "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/serve/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "node_modules/sinon": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", - "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.2", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "nise": "^6.1.1", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.31.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", - "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/terser/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", - "dev": true - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/update-check": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", - "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", - "dev": true, - "dependencies": { - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/watch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", - "dev": true, - "dependencies": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - }, - "bin": { - "watch": "cli.js" - }, - "engines": { - "node": ">=0.1.95" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/webpack/node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, - "peer": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", - "dev": true, - "dependencies": { - "string-width": "^5.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@athombv/data-types": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@athombv/data-types/-/data-types-1.3.0.tgz", - "integrity": "sha512-XJ7oMzKFcZdw2LpiBcr8QVmtQXkCpnOpDGpQ2iM2vuKjzosXQjAB0XUgKl+yubDNTFkTNa8mcFS5QdFP51O7pg==" - }, - "@athombv/jsdoc-template": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@athombv/jsdoc-template/-/jsdoc-template-1.7.0.tgz", - "integrity": "sha512-eO4Kna1DCmRLMm4SwHYrEehQWkWDt72j88aMIjW+HOWuWV6Nu296VTLjZ5EeoeSrD0Q/QYUakr9TCJKJ8hwIBA==", - "dev": true, - "requires": { - "css-loader": "^5.2.4", - "highlight.js": "^10.7.2", - "taffydb": "^2.7.3" - }, - "dependencies": { - "taffydb": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", - "integrity": "sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg==", - "dev": true - } - } - }, - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz", - "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz", - "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true - }, - "@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", - "dev": true - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz", - "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==", - "dev": true - } - } - }, - "@babel/traverse": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz", - "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz", - "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==", - "dev": true - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz", - "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - } - } - }, - "@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "dev": true, - "optional": true - }, - "@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "dev": true, - "optional": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "peer": true - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "peer": true - }, - "@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "peer": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.1" - } - }, - "@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" - }, - "dependencies": { - "type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true - } - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true - }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "peer": true - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", - "dev": true - }, - "@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", - "dev": true, - "requires": { - "@types/linkify-it": "*", - "@types/mdurl": "*" - } - }, - "@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "@types/node": { - "version": "25.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", - "integrity": "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==", - "dev": true, - "requires": { - "undici-types": "~7.16.0" - } - }, - "@types/sinon": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", - "dev": true, - "requires": { - "@types/sinonjs__fake-timers": "*" - } - }, - "@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "peer": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "peer": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true, - "peer": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "peer": true - }, - "@zeit/schemas": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.21.0.tgz", - "integrity": "sha512-/J4WBTpWtQ4itN1rb3ao8LfClmVcmz2pO6oYb7Qd4h7VSqUhIbJIvrykz9Ew1WMg6eFWsKdsMHc5uPbFxqlCpg==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", - "dev": true - }, - "acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "requires": { - "string-width": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" - }, - "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, - "arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - } - }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "boxen": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", - "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", - "dev": true, - "requires": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "camelcase": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.0.tgz", - "integrity": "sha512-JToIvOmz6nhGsUhAYScbo2d6Py5wojjNfoxoc2mEVLUdJ70gJK2gnd+ABY1Tc3sVMyK7QDPtN0T/XdlCQWITyQ==", - "dev": true - }, - "chalk": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz", - "integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - }, - "wrap-ansi": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", - "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "dev": true, - "peer": true, - "requires": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "peer": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001655", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", - "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", - "dev": true, - "peer": true - }, - "catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", - "dev": true, - "requires": { - "chalk": "^4.1.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "peer": true - }, - "cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "clipboardy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", - "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", - "dev": true, - "requires": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" - }, - "dependencies": { - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - } - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concurrently": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.2.0.tgz", - "integrity": "sha512-XxcDbQ4/43d6CxR7+iV8IZXhur4KbmEJk1CetVMUqCy34z9l0DkszbY+/9wvmSnToTej0SYomc2WSRH+L0zVJw==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", - "tree-kill": "^1.2.2", - "yargs": "^13.3.0" - } - }, - "confusing-browser-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", - "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", - "dev": true - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "css-loader": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", - "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.15", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.5" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "date-fns": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.14.0.tgz", - "integrity": "sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", - "dev": true, - "peer": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "peer": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true, - "peer": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", - "dev": true, - "requires": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" - } - }, - "escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-config-airbnb-base": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz", - "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==", - "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.9", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2" - } - }, - "eslint-config-athom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-athom/-/eslint-config-athom-2.1.0.tgz", - "integrity": "sha512-e7rZyvqF+QEnfWXbDTGUnnqU5G7F1BsKYzwZYTEBEjtUmesj23S0mVFem4jg399iAzkn1IrhpaXAdeADUF7c1A==", - "dev": true, - "requires": { - "babel-eslint": "^10.0.3", - "eslint-config-airbnb-base": "^14.0.0", - "eslint-plugin-import": "^2.20.0", - "eslint-plugin-mocha": "^6.2.2", - "eslint-plugin-node": "^11.0.0" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", - "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.3", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-mocha": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.3.0.tgz", - "integrity": "sha512-Cd2roo8caAyG21oKaaNTj7cqeYRWW1I2B5SfpKRp0Ip1gkfwoR1Ow0IGlPWnNjzywdF4n+kHL8/9vM6zCJUxdg==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "ramda": "^0.27.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - } - } - }, - "eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "requires": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - }, - "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", - "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", - "dev": true, - "requires": { - "estraverse": "^5.0.0" - }, - "dependencies": { - "estraverse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", - "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "peer": true - }, - "exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "requires": { - "merge": "^1.2.0" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dev": true, - "requires": { - "punycode": "^1.3.2" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - } - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-tsconfig": { - "version": "4.13.7", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", - "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", - "dev": true, - "requires": { - "resolve-pkg-maps": "^1.0.0" - } - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-port-reachable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", - "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "peer": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "peer": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.4" - } - }, - "jsdoc": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", - "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", - "dev": true, - "requires": { - "@babel/parser": "^7.9.4", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.2" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "jsdoc-ts-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-ts-utils/-/jsdoc-ts-utils-2.0.0.tgz", - "integrity": "sha512-xTwLOGJ7K4xs1ZL+YHTl5cYHO2idNgY0FzRJPp/WCw7t61L2fU8odK5Hteos0B+1sEN+ZSLceoBfXXJnVJNokQ==", - "dev": true, - "requires": { - "jsdoc": "^3.6.6" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true - }, - "klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "peer": true - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "@types/markdown-it": "*", + "markdown-it": "*" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } + "license": "Python-2.0" }, - "markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, - "requires": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "license": "MIT", + "bin": { + "marked": "bin/marked.js" }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - } + "engines": { + "node": ">= 12" } }, - "markdown-it-anchor": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.5.tgz", - "integrity": "sha512-PI1qEHHkTNWT+X6Ip9w+paonfIQ+QZP9sCeMYi47oqhH+EsW8CrJ8J7CzV19QVOj6il8ATGbK2nTECj22ZHGvQ==", + "node_modules/mdurl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", "dev": true, - "requires": {} - }, - "marked": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", - "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true + "license": "MIT" }, - "merge-stream": { + "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "dev": true, + "license": "MIT", + "peer": true }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, - "requires": { - "mime-db": "1.52.0" + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, + "node_modules/minimizer-webpack-plugin": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.13.1.tgz", + "integrity": "sha512-1mhAfvachWYYOm8tpmany5NLuvP+F2wxZWBSX8DC0uFS2wJpM9q3rWgN9wBooAH9d5V12wX0BjyJe4fMjHMarQ==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "@jridgewell/trace-mapping": "^0.3.31", + "jest-worker": "^27.4.5", + "schema-utils": "^4.6.0", + "terser": "^5.51.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "@napi-rs/image": { + "optional": true }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } + "@swc/core": { + "optional": true }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } + "@swc/css": { + "optional": true }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } + "@swc/html": { + "optional": true }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "clean-css": { + "optional": true }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } + "cssnano": { + "optional": true }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } + "csso": { + "optional": true }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "esbuild": { + "optional": true }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } + "html-minifier-terser": { + "optional": true }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } + "imagemin": { + "optional": true }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } + "lightningcss": { + "optional": true }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } + "postcss": { + "optional": true }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "sharp": { + "optional": true }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } + "svgo": { + "optional": true }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true + "uglify-js": { + "optional": true } } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, - "peer": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } }, - "nise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", - "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", + "node_modules/minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.1", - "@sinonjs/text-encoding": "^0.7.3", - "just-extend": "^6.2.0", - "path-to-regexp": "^8.1.0" - }, + "license": "MIT", + "peer": true, "dependencies": { - "path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true - } + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "node_modules/minimizer-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, + "license": "MIT", "peer": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.8.1.tgz", + "integrity": "sha512-x39pYlJPyH7Uge5QO64B9XGP9zLDc9WNmiQZc+CE3IzZPvMu3lHOuAMGpYNoPixEL7MSWlGhYTg5UlLSL8G6iw==", "dev": true, - "requires": { - "path-key": "^3.0.0" - }, + "license": "MIT", + "peer": true, "dependencies": { - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" + }, + "bin": { + "schema-utils": "bin/schema-utils.js" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.112.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true } } }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - } + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { + "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } + "license": "MIT" }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/node-releases": { + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.60.tgz", + "integrity": "sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==", "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "requires": { - "p-try": "^2.0.0" + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "requires": { - "p-limit": "^2.0.0" + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "requires": { - "callsites": "^3.0.0" + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "parse-json": { + "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", - "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "requires": { - "pify": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } + "license": "MIT", + "engines": { + "node": ">=8" } }, - "picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "node_modules/postcss": { + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", + "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", "dev": true, - "requires": { - "find-up": "^2.1.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.20", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" } }, - "postcss": { - "version": "8.4.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", - "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, - "requires": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", + "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "postcss-modules-values": { + "node_modules/postcss-modules-values": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "node_modules/postcss-selector-parser": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.7.tgz", + "integrity": "sha512-wWBro/7hJ40ye6TPiXkUQoXKCw23xSsjriUvqd7Uls9Sso3oLiON1flc18cCdnjgCRXw4fBVqUJJeOdDTh3P3g==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" } }, - "postcss-value-parser": { + "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "ramda": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz", - "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", - "dev": true - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true - } - } + "license": "MIT" }, - "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "requires": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">= 0.8.0" } }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "node_modules/prettier": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - } + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "requires": { - "picomatch": "^2.2.1" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", "dev": true, - "requires": { - "rc": "^1.0.1" + "license": "MIT", + "dependencies": { + "hookified": "^2.1.1" + }, + "engines": { + "node": ">=20" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "node_modules/qified/node_modules/hookified": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "dev": true, + "license": "MIT" }, - "require-from-string": { + "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", "dev": true, - "requires": { - "is-promise": "^2.1.0" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" } }, - "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", "dev": true, - "requires": { - "tslib": "^1.9.0" + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "schema-utils": { + "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/serve/-/serve-14.1.2.tgz", - "integrity": "sha512-luwVfJwbeE7dhCKeRU0vIBpt4bXdbAfzwsWJIQ5eqrIW2e+4nLWXbSlZ0WzelSFHQq+FlueOW6dr90jEewS9zw==", - "dev": true, - "requires": { - "@zeit/schemas": "2.21.0", - "ajv": "8.11.0", - "arg": "5.0.2", - "boxen": "7.0.0", - "chalk": "5.0.1", - "chalk-template": "0.4.0", - "clipboardy": "3.0.0", - "compression": "1.7.4", - "is-port-reachable": "4.0.0", - "serve-handler": "6.1.5", - "update-check": "1.5.4" }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "chalk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", - "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "serve-handler": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", - "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, - "requires": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "dependencies": { - "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, - "requires": { - "mime-db": "~1.33.0" - } - } + "engines": { + "node": ">=10" } }, - "set-blocking": { + "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "sinon": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", - "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.2", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "nise": "^6.1.1", - "supports-color": "^7.2.0" - }, + "license": "MIT", "dependencies": { - "diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "peer": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "shebang-regex": "^3.0.0" }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "peer": true - } - } - }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "engines": { + "node": ">=8" } }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" } }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "requires": { - "ansi-regex": "^4.1.0" + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { + "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, - "requires": { - "has-flag": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "node_modules/taffydb": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", + "integrity": "sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg==", "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - } - }, - "taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true + "license": "BSD-2-Clause" }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, - "peer": true + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } }, - "terser": { - "version": "5.31.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", - "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", + "node_modules/terser": { + "version": "5.51.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.51.2.tgz", + "integrity": "sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==", "dev": true, + "license": "BSD-2-Clause", "peer": true, - "requires": { + "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "peer": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "bin": { + "terser": "bin/terser" }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - } + "engines": { + "node": ">=10" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "requires": { - "is-number": "^7.0.0" + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", - "dev": true + "license": "MIT" }, - "tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", "dev": true, - "requires": { - "esbuild": "~0.27.0", - "fsevents": "~2.3.3", - "get-tsconfig": "^4.7.5" - } + "license": "MIT" }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true + "license": "MIT" }, - "typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "dev": true - }, - "undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "node_modules/update-browserslist-db": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "peer": true, - "requires": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - } - }, - "update-check": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", - "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", - "dev": true, - "requires": { - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0" + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "requires": { + "license": "BSD-2-Clause", + "dependencies": { "punycode": "^2.1.0" } }, - "util-deprecate": { + "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true - }, - "watch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - } + "license": "MIT" }, - "watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "node_modules/watchpack": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.6.3.tgz", + "integrity": "sha512-s3NZy0QpTY9qGqzc0wtz4qI28z3+5qKbbAec4MV4G9N3CfgZ9wgvQRr0cl2jh/tqkWG1NWHkmVMHZpCamev5Wg==", "dev": true, + "license": "MIT", "peer": true, - "requires": { - "glob-to-regexp": "^0.4.1", + "dependencies": { "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" } }, - "webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "node_modules/webpack": { + "version": "5.112.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.112.0.tgz", + "integrity": "sha512-NIBpsRuCll036haDDt/CfcTDfsWNR9Z782nMRMI9D377BsGcYzZDTNU5TyzhCJzPIcihAxMBaMAhq2WSaDrH8Q==", "dev": true, + "license": "MIT", "peer": true, - "requires": { - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", + "enhanced-resolve": "^5.26.0", + "es-module-lexer": "^2.1.0", "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.13.0", + "schema-utils": "^4.5.0", + "tapable": "^2.3.0", + "watchpack": "^2.6.1", + "webpack-sources": "^3.6.0" }, - "dependencies": { - "acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "peer": true - }, - "acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, - "peer": true, - "requires": {} + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true } } }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "node_modules/webpack-sources": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.6.0.tgz", + "integrity": "sha512-EIMmPVvNI0CYXyRPp34F2Qk7W37/BZVZIofS6LAUnrNjCVahS+hO4mxwFJDjQjODTGZDtVzLYoN2+1dYkhk9qA==", "dev": true, - "peer": true + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/webpack/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, - "requires": { - "isexe": "^2.0.0" + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, - "requires": { - "string-width": "^5.0.1" - }, + "license": "MIT", + "peer": true, "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" } }, - "word-wrap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", - "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "peer": true }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/webpack/node_modules/schema-utils": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.8.1.tgz", + "integrity": "sha512-x39pYlJPyH7Uge5QO64B9XGP9zLDc9WNmiQZc+CE3IzZPvMu3lHOuAMGpYNoPixEL7MSWlGhYTg5UlLSL8G6iw==", "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" + }, + "bin": { + "schema-utils": "bin/schema-utils.js" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.112.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "requires": { - "mkdirp": "^0.5.1" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "xmlcreate": { + "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } + "license": "Apache-2.0" }, - "yocto-queue": { + "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index e6fdd8e5..83aed586 100644 --- a/package.json +++ b/package.json @@ -9,13 +9,13 @@ "lib" ], "scripts": { - "test": "mocha --reporter list", + "test": "node --test --test-reporter=spec --test-timeout=5000 \"test/*.js\"", "lint": "eslint .", - "generate-types": "tsx scripts/generate-types.mts", - "serve": "concurrently \"serve build/\" \"npm run build:watch\"", + "generate-types": "node scripts/generate-types.mts", "build": "jsdoc --configure ./docs/jsdoc.json", - "build:clean": "rm -rf ./build", - "build:watch": "watch \"npm run build:clean && npm run build\" lib docs \"node_modules/@athombv/jsdoc-template\"" + "docs": "npm run build && open build/index.html", + "format:check": "prettier --check .", + "format:write": "prettier --write ." }, "repository": { "type": "git", @@ -37,19 +37,14 @@ "homepage": "https://github.com/athombv/node-zigbee-clusters#readme", "devDependencies": { "@athombv/jsdoc-template": "^1.7.0", + "@eslint/js": "^10.0.1", "@types/node": "^25.0.10", - "@types/sinon": "^17.0.3", - "concurrently": "^5.2.0", - "eslint": "^6.8.0", - "eslint-config-athom": "^2.1.0", - "jsdoc": "^3.6.7", - "jsdoc-ts-utils": "^2.0.0", - "mocha": "^10.1.0", - "serve": "^14.0.1", - "sinon": "^19.0.2", - "tsx": "^4.21.0", - "typescript": "^5.9.3", - "watch": "^1.0.2" + "eslint": "^10.13.0", + "globals": "^17.13.0", + "jsdoc": "^4.0.5", + "jsdoc-ts-utils": "^6.0.0", + "prettier": "^3.9.10", + "typescript": "^5.9.3" }, "dependencies": { "@athombv/data-types": "^1.3.0", diff --git a/scripts/generate-types.mts b/scripts/generate-types.mts index b480d340..02188170 100644 --- a/scripts/generate-types.mts +++ b/scripts/generate-types.mts @@ -1,7 +1,7 @@ -import type {Cluster, types} from "zigbee-clusters"; -import path from "node:path"; -import * as fs from "node:fs/promises"; -import type {DataType, DataTypes} from "@athombv/data-types"; +import type { Cluster, types } from 'zigbee-clusters'; +import path from 'node:path'; +import * as fs from 'node:fs/promises'; +import type { DataType, DataTypes } from '@athombv/data-types'; const INDENTATION_SPACES = 2; @@ -15,13 +15,13 @@ class StringBuilder { } public startLine(): void { - this.strings.push(" ".repeat(this.indentation)); + this.strings.push(' '.repeat(this.indentation)); } public print(...line: string[]): void { this.strings.push(...line); } public endLine(): void { - this.strings.push("\n"); + this.strings.push('\n'); } public printLine(...line: string[]): void { @@ -30,7 +30,6 @@ class StringBuilder { this.endLine(); } - public increaseIndent(levels = 1): void { this.indentation += INDENTATION_SPACES * levels; } @@ -45,7 +44,7 @@ class StringBuilder { } public toString(): string { - return this.strings.join(""); + return this.strings.join(''); } } @@ -62,12 +61,12 @@ async function main(): Promise { const stringBuilder = new StringBuilder(); // Write preamble and open module declaration - stringBuilder.printLine('declare module "zigbee-clusters" {') + stringBuilder.printLine('declare module "zigbee-clusters" {'); stringBuilder.increaseIndent(); - stringBuilder.printLine('import {Bitmap} from "@athombv/data-types";') + stringBuilder.printLine('import {Bitmap} from "@athombv/data-types";'); // @ts-expect-error No type declarations - const clustersModule = await import("../lib/clusters/index.js"); + const clustersModule = await import('../lib/clusters/index.js'); for (const [name, value] of Object.entries(clustersModule.default)) { if (name !== 'Cluster' && name !== 'CLUSTER') { await formatCluster(stringBuilder, name, value as typeof Cluster); @@ -75,7 +74,7 @@ async function main(): Promise { } // Open CLUSTER - stringBuilder.printLine("const CLUSTER: {"); + stringBuilder.printLine('const CLUSTER: {'); stringBuilder.increaseIndent(); // Collect (NAME, ClassName) pairs to emit a typed lookup map after the @@ -84,7 +83,7 @@ async function main(): Promise { const clusterClassByName: Array<{ name: string; className: string }> = []; for (const [key, value] of Object.entries(clustersModule.default.CLUSTER)) { - const definition = value as {ID: number, NAME: string}; + const definition = value as { ID: number; NAME: string }; // `lib/clusters/index.js` no longer re-exports `Cluster` (PR #182), so // reach the static `Cluster.clusters` registry via the top-level entry. const clusterClass = topModule.Cluster.clusters[definition.ID]; @@ -93,13 +92,13 @@ async function main(): Promise { if (clusterName === 'TouchlinkCluster') { clusterName = 'TouchLinkCluster'; } - if (!clusterName.endsWith("Cluster")) { + if (!clusterName.endsWith('Cluster')) { clusterName = `${clusterName}Cluster`; } clusterClassByName.push({ name: definition.NAME, className: clusterName }); stringBuilder.printLine(`${key}: {`); stringBuilder.increaseIndent(); - stringBuilder.printLine(`ID: 0x${definition.ID.toString(16).padStart(4, "0")},`); + stringBuilder.printLine(`ID: 0x${definition.ID.toString(16).padStart(4, '0')},`); stringBuilder.printLine(`NAME: ${JSON.stringify(definition.NAME)},`); stringBuilder.printLine(`ATTRIBUTES: Readonly<${clusterName}Attributes>,`); stringBuilder.printLine(`COMMANDS: Readonly<${clusterName}Commands>,`); @@ -109,20 +108,20 @@ async function main(): Promise { // Close CLUSTER stringBuilder.decreaseIndent(); - stringBuilder.printLine("};"); + stringBuilder.printLine('};'); // Emit a name->class lookup map used by `ZCLNodeEndpoint.clusters` for // typed access to known cluster classes. Keys are optional because an // endpoint may not implement every cluster; an unknown cluster name // (e.g. manufacturer-specific) falls through the intersection with // `Record>` in the template. - stringBuilder.printLine("type ClustersByName = {"); + stringBuilder.printLine('type ClustersByName = {'); stringBuilder.increaseIndent(); for (const { name, className } of clusterClassByName) { stringBuilder.printLine(`${JSON.stringify(name)}?: ${className};`); } stringBuilder.decreaseIndent(); - stringBuilder.printLine("};"); + stringBuilder.printLine('};'); const template = await fs.readFile(templatePath, 'utf8'); const templateHeader = "declare module 'zigbee-clusters' {"; @@ -133,19 +132,22 @@ async function main(): Promise { // Write the result to index.d.ts await fs.writeFile(filePath, stringBuilder.toString()); - console.log("Done!"); + console.log('Done!'); } - -async function formatCluster(stringBuilder: StringBuilder, className: string, classDefinition: typeof Cluster): Promise { +async function formatCluster( + stringBuilder: StringBuilder, + className: string, + classDefinition: typeof Cluster, +): Promise { stringBuilder.startLine(); stringBuilder.print(`type ${className}Attributes = `); if (Object.keys(classDefinition.ATTRIBUTES).length === 0) { - stringBuilder.print("Record;"); + stringBuilder.print('Record;'); stringBuilder.endLine(); } else { // Open attributes - stringBuilder.print("{"); + stringBuilder.print('{'); stringBuilder.endLine(); stringBuilder.increaseIndent(); for (const attribute in classDefinition.ATTRIBUTES) { @@ -160,11 +162,11 @@ async function formatCluster(stringBuilder: StringBuilder, className: string, cl stringBuilder.startLine(); stringBuilder.print(`type ${className}Commands = `); if (Object.keys(classDefinition.COMMANDS).length === 0) { - stringBuilder.print("Record;"); + stringBuilder.print('Record;'); stringBuilder.endLine(); } else { // Open commands - stringBuilder.print("{"); + stringBuilder.print('{'); stringBuilder.endLine(); stringBuilder.increaseIndent(); for (const command in classDefinition.COMMANDS) { @@ -177,7 +179,9 @@ async function formatCluster(stringBuilder: StringBuilder, className: string, cl } // Open class - stringBuilder.printLine(`class ${className} extends Cluster {`); + stringBuilder.printLine( + `class ${className} extends Cluster {`, + ); stringBuilder.increaseIndent(); for (const command in classDefinition.COMMANDS) { @@ -190,46 +194,58 @@ async function formatCluster(stringBuilder: StringBuilder, className: string, cl stringBuilder.printLine('}'); } - -function formatAttribute(stringBuilder: StringBuilder, className: string, name: string, definition: types.AttributeDefinition): void { +function formatAttribute( + stringBuilder: StringBuilder, + className: string, + name: string, + definition: types.AttributeDefinition, +): void { stringBuilder.startLine(); - stringBuilder.print(`${name}: { id: 0x${definition.id.toString(16).padStart(2, "0")}`); + stringBuilder.print(`${name}: { id: 0x${definition.id.toString(16).padStart(2, '0')}`); stringBuilder.print(', type: ZCLDataType<'); formatZCLDataTypeGeneric(stringBuilder, className, name, definition.type); - stringBuilder.print("> },"); + stringBuilder.print('> },'); stringBuilder.endLine(); } - -function formatCommand(stringBuilder: StringBuilder, className: string, name: string, definition: types.CommandDefinition): void { +function formatCommand( + stringBuilder: StringBuilder, + className: string, + name: string, + definition: types.CommandDefinition, +): void { stringBuilder.startLine(); - stringBuilder.print(`${name}: { id: 0x${definition.id.toString(16).padStart(2, "0")}`); - stringBuilder.print(`, direction: ${JSON.stringify(definition.direction ?? "DIRECTION_SERVER_TO_CLIENT")}`); + stringBuilder.print(`${name}: { id: 0x${definition.id.toString(16).padStart(2, '0')}`); + stringBuilder.print( + `, direction: ${JSON.stringify(definition.direction ?? 'DIRECTION_SERVER_TO_CLIENT')}`, + ); if (definition.frameControl !== undefined) { stringBuilder.print(`, frameControl: ${JSON.stringify(definition.frameControl)}`); } if (definition.encodeMissingFieldsBehavior !== undefined) { - stringBuilder.print(`, encodeMissingFieldsBehavior: ${JSON.stringify(definition.encodeMissingFieldsBehavior)}`); + stringBuilder.print( + `, encodeMissingFieldsBehavior: ${JSON.stringify(definition.encodeMissingFieldsBehavior)}`, + ); } if (definition.global !== undefined) { stringBuilder.print(`, global: ${definition.global}`); } if (definition.args !== undefined) { - stringBuilder.print(", args: "); + stringBuilder.print(', args: '); if (Object.keys(definition.args).length === 0) { - throw new Error(`Empty args definition for ${className} command ${name}`) + throw new Error(`Empty args definition for ${className} command ${name}`); } else { // Open args - stringBuilder.print("{"); + stringBuilder.print('{'); stringBuilder.endLine(); stringBuilder.increaseIndent(2); for (const [key, arg] of Object.entries(definition.args)) { stringBuilder.startLine(); stringBuilder.print(`${key}: ZCLDataType<`); formatZCLDataTypeGeneric(stringBuilder, className, name, arg); - stringBuilder.print(">,"); + stringBuilder.print('>,'); stringBuilder.endLine(); } // Close args @@ -241,15 +257,19 @@ function formatCommand(stringBuilder: StringBuilder, className: string, name: st } } else { // Space before closing bracket of attribute - stringBuilder.print(" "); + stringBuilder.print(' '); } stringBuilder.print('},'); stringBuilder.endLine(); } - -function formatCommandMethod(stringBuilder: StringBuilder, className: string, name: string, definition: types.CommandDefinition): void { +function formatCommandMethod( + stringBuilder: StringBuilder, + className: string, + name: string, + definition: types.CommandDefinition, +): void { // The runtime `Cluster.addCluster` installs a sendable method for every // command regardless of direction (see lib/Cluster.js around the // `Object.defineProperty(proto, cmdName, ...)` loop). Emit the sendable @@ -264,12 +284,17 @@ function formatCommandMethod(stringBuilder: StringBuilder, className: string, na } } -function emitSendableCommandMethod(stringBuilder: StringBuilder, className: string, name: string, definition: types.CommandDefinition): void { +function emitSendableCommandMethod( + stringBuilder: StringBuilder, + className: string, + name: string, + definition: types.CommandDefinition, +): void { stringBuilder.startLine(); stringBuilder.print(name); // Open method - stringBuilder.print("("); + stringBuilder.print('('); stringBuilder.endLine(); stringBuilder.increaseIndent(); @@ -292,7 +317,6 @@ function emitSendableCommandMethod(stringBuilder: StringBuilder, className: stri stringBuilder.decreaseIndent(); stringBuilder.printLine('},'); - // Opts stringBuilder.printLine('opts?: {'); stringBuilder.increaseIndent(); @@ -305,17 +329,22 @@ function emitSendableCommandMethod(stringBuilder: StringBuilder, className: stri closeCommandMethod(stringBuilder, className, name, definition); } -function emitCommandHandlerMethod(stringBuilder: StringBuilder, className: string, name: string, definition: types.CommandDefinition): void { +function emitCommandHandlerMethod( + stringBuilder: StringBuilder, + className: string, + name: string, + definition: types.CommandDefinition, +): void { stringBuilder.startLine(); - stringBuilder.print("on", name.charAt(0).toUpperCase(), name.slice(1)); + stringBuilder.print('on', name.charAt(0).toUpperCase(), name.slice(1)); // Open method - stringBuilder.print("("); + stringBuilder.print('('); stringBuilder.endLine(); stringBuilder.increaseIndent(); if (definition.args === undefined) { - stringBuilder.printLine('args: undefined,') + stringBuilder.printLine('args: undefined,'); } else { // Open args stringBuilder.printLine('args: {'); @@ -334,49 +363,58 @@ function emitCommandHandlerMethod(stringBuilder: StringBuilder, className: strin stringBuilder.printLine('},'); } - stringBuilder.printLine("meta: object,") - stringBuilder.printLine("frame: object,") - stringBuilder.printLine("rawFrame: Buffer,") + stringBuilder.printLine('meta: object,'); + stringBuilder.printLine('frame: object,'); + stringBuilder.printLine('rawFrame: Buffer,'); closeCommandMethod(stringBuilder, className, name, definition); } -function closeCommandMethod(stringBuilder: StringBuilder, className: string, name: string, definition: types.CommandDefinition): void { +function closeCommandMethod( + stringBuilder: StringBuilder, + className: string, + name: string, + definition: types.CommandDefinition, +): void { // Close method stringBuilder.decreaseIndent(); stringBuilder.startLine(); - stringBuilder.print("): Promise<"); + stringBuilder.print('): Promise<'); if (definition.response === undefined) { - stringBuilder.print("void"); + stringBuilder.print('void'); } else { // Open return object - stringBuilder.print("{") - stringBuilder.endLine() - stringBuilder.increaseIndent() + stringBuilder.print('{'); + stringBuilder.endLine(); + stringBuilder.increaseIndent(); for (let argName in definition.response.args) { const argType = definition.response.args[argName]; stringBuilder.startLine(); stringBuilder.print(argName); if (definition.response.encodeMissingFieldsBehavior === 'skip') { - stringBuilder.print("?") + stringBuilder.print('?'); } - stringBuilder.print(": ") + stringBuilder.print(': '); formatZCLDataTypeGeneric(stringBuilder, className, name, argType); - stringBuilder.print(",") + stringBuilder.print(','); stringBuilder.endLine(); } // Close return object stringBuilder.decreaseIndent(); stringBuilder.startLine(); - stringBuilder.print("}") + stringBuilder.print('}'); } - stringBuilder.print(">;") + stringBuilder.print('>;'); stringBuilder.endLine(); } - -function formatZCLDataTypeGeneric(stringBuilder: StringBuilder, className: string, command: string, definition: DataType): void { +function formatZCLDataTypeGeneric( + stringBuilder: StringBuilder, + className: string, + command: string, + definition: DataType, +): void { const typeName = definition.shortName as keyof typeof DataTypes; const typeArgs: Array = definition.args; @@ -385,21 +423,26 @@ function formatZCLDataTypeGeneric(stringBuilder: StringBuilder, className: strin stringBuilder.print('unknown'); } else if (typeName.startsWith('enum')) { if (definition === enum8Status) { - stringBuilder.print('types.ZCLEnum8Status') + stringBuilder.print('types.ZCLEnum8Status'); } else { formatEnumDataType(stringBuilder, className, command, typeName, typeArgs); } } else if (typeName.startsWith('map')) { formatMapDataType(stringBuilder, className, command, typeName, typeArgs); - } else if (typeName.startsWith("_Array")) { + } else if (typeName.startsWith('_Array')) { formatArrayDataType(stringBuilder, className, command, typeName, typeArgs); } else { stringBuilder.print(zclDataTypeToValueType(typeName)); } } - -function formatEnumDataType(stringBuilder: StringBuilder, className: string, field: string, typeName: string, typeArgs: Array): void { +function formatEnumDataType( + stringBuilder: StringBuilder, + className: string, + field: string, + typeName: string, + typeArgs: Array, +): void { const typeArg = typeArgs[0]; if (typeof typeArg !== 'object' || Array.isArray(typeArg) || typeArg === null) { throw new Error(`Invalid ${typeName} arg for ${className} ${field}`); @@ -409,12 +452,17 @@ function formatEnumDataType(stringBuilder: StringBuilder, className: string, fie if (entries.length === 0) { stringBuilder.print('unknown'); } else { - stringBuilder.print(entries.map(arg => JSON.stringify(arg)).join(" | ")); + stringBuilder.print(entries.map((arg) => JSON.stringify(arg)).join(' | ')); } } - -function formatMapDataType(stringBuilder: StringBuilder, className: string, field: string, typeName: string, typeArgs: Array): void { +function formatMapDataType( + stringBuilder: StringBuilder, + className: string, + field: string, + typeName: string, + typeArgs: Array, +): void { if (typeof typeArgs !== 'object' || !Array.isArray(typeArgs)) { throw new Error(`Invalid ${typeName} arg for ${className} ${field}`); } @@ -427,87 +475,92 @@ function formatMapDataType(stringBuilder: StringBuilder, className: string, fiel stringBuilder.print('Bitmap'); } else { stringBuilder.print('Bitmap<'); - stringBuilder.print(typeArgs.map(arg => JSON.stringify(arg)).join(" | ")); - stringBuilder.print(">"); + stringBuilder.print(typeArgs.map((arg) => JSON.stringify(arg)).join(' | ')); + stringBuilder.print('>'); } } -function formatArrayDataType(stringBuilder: StringBuilder, className: string, field: string, typeName: string, typeArgs: Array>): void { - stringBuilder.print('Array<') - formatZCLDataTypeGeneric(stringBuilder, className, field, typeArgs[0]) - stringBuilder.print('>') +function formatArrayDataType( + stringBuilder: StringBuilder, + className: string, + field: string, + typeName: string, + typeArgs: Array>, +): void { + stringBuilder.print('Array<'); + formatZCLDataTypeGeneric(stringBuilder, className, field, typeArgs[0]); + stringBuilder.print('>'); } - function zclDataTypeToValueType(type: keyof typeof DataTypes): string { switch (type) { - case "noData": - return "null"; - case "data8": - case "data16": - case "data24": - case "data32": - case "data40": - case "data48": - case "data56": - return "Buffer"; - case "bool": - return "boolean"; - case "map8": - case "map16": - case "map24": - case "map32": - case "map40": - case "map48": - case "map56": - case "map64": - throw new Error("Complex type"); - case "uint8": - case "uint16": - case "uint24": - case "uint32": - case "uint40": - case "uint48": - case "int8": - case "int16": - case "int24": - case "int32": - case "int40": - case "int48": - case "UTC": - return "number"; - case "enum8": - case "enum16": - case "enum32": - throw new Error("Complex type"); - case "single": - case "double": - return "number"; - case "octstr": - return "Buffer" - case "string": - case "EUI48": - case "EUI64": - case "key128": - return "string"; + case 'noData': + return 'null'; + case 'data8': + case 'data16': + case 'data24': + case 'data32': + case 'data40': + case 'data48': + case 'data56': + return 'Buffer'; + case 'bool': + return 'boolean'; + case 'map8': + case 'map16': + case 'map24': + case 'map32': + case 'map40': + case 'map48': + case 'map56': + case 'map64': + throw new Error('Complex type'); + case 'uint8': + case 'uint16': + case 'uint24': + case 'uint32': + case 'uint40': + case 'uint48': + case 'int8': + case 'int16': + case 'int24': + case 'int32': + case 'int40': + case 'int48': + case 'UTC': + return 'number'; + case 'enum8': + case 'enum16': + case 'enum32': + throw new Error('Complex type'); + case 'single': + case 'double': + return 'number'; + case 'octstr': + return 'Buffer'; + case 'string': + case 'EUI48': + case 'EUI64': + case 'key128': + return 'string'; } // Internal types switch (type as string) { - case "_map4": - throw new Error("Complex type"); - case "_uint4": - return "number"; - case "_enum4": - throw new Error("Complex type"); - case "_buffer": - case "_buffer8": - case "_buffer16": - return "Buffer"; - case "_Array0": - case "_Array8": - throw new Error("Complex type"); - case "_FixedString": - return "string"; + case '_map4': + throw new Error('Complex type'); + case '_uint4': + return 'number'; + case '_enum4': + throw new Error('Complex type'); + case '_buffer': + case '_buffer8': + case '_buffer16': + return 'Buffer'; + case '_Array0': + case '_Array8': + throw new Error('Complex type'); + case '_FixedString': + return 'string'; } throw new Error(`Unknown ZCL type ${type}`); } diff --git a/scripts/template.d.ts.txt b/scripts/template.d.ts.txt index f9dfde1c..624890db 100644 --- a/scripts/template.d.ts.txt +++ b/scripts/template.d.ts.txt @@ -54,12 +54,14 @@ declare module 'zigbee-clusters' { } /** - * Minimum shape an Endpoint needs from its owner. Endpoint only ever calls `sendFrame`, so a - * plain object is enough - a device serving bound clusters does not need a full ZCLNode, which - * models one remote peer and bakes that peer's address into its own `sendFrame`. + * Minimum shape an Endpoint needs from its owner. Endpoint only needs `sendFrame`, so a plain + * object is enough - a device serving bound clusters does not need a full ZCLNode, which + * models one remote peer and bakes that peer's address into its own `sendFrame`. Without + * `nextSeqNr` the Endpoint keeps its own transaction sequence number counter. */ type EndpointInput = { sendFrame(endpointId: number, clusterId: number, frame: Buffer): Promise; + nextSeqNr?(): number; }; class Endpoint extends EventEmitter { @@ -274,7 +276,7 @@ declare module 'zigbee-clusters' { static removeCluster(clusterIdOrName: string | number): void; static getCluster(clusterIdOrName: string | number): Cluster; - on>(eventName: `attr.${Event}`, listener: (value: types.AttributesFromDefinition[Event]) => void): this; + on>(eventName: `attr.${Event}`, listener: (value: types.AttributesFromDefinition[Event], meta: types.AttributeReportMeta) => void): this; on = unknown[]>(eventName: string, listener: (...args: Values) => void): this; } @@ -649,6 +651,14 @@ declare module 'zigbee-clusters' { } } + type AttributeReportMeta = { + /** + * ZCL transaction sequence number of the report frame. It wraps at 256 and some devices + * reuse a fixed value, so only treat equal values as a duplicate within a short time window. + */ + transactionSequenceNumber: number; + }; + type ReadReportingConfigurationResponse = { status: ZCLEnum8Status, direction: 'reported'|'received'; diff --git a/test/attributeReport.js b/test/attributeReport.js new file mode 100644 index 00000000..79a86e77 --- /dev/null +++ b/test/attributeReport.js @@ -0,0 +1,36 @@ +'use strict'; + +const { describe, it } = require('node:test'); +const assert = require('node:assert'); +const OnOffCluster = require('../lib/clusters/onOff'); +const { createMockNode } = require('./util'); +const { ZCLStandardHeader } = require('../lib/zclFrames'); + +describe('Attribute report', function () { + it('should emit the transaction sequence number with the attribute value', function (t, done) { + const node = createMockNode({ + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], + }); + + node.endpoints[1].clusters.onOff.on('attr.onOff', (value, meta) => { + assert.strictEqual(value, true); + // Only whitelisted fields, not the stack's frame meta + assert.deepStrictEqual(meta, { transactionSequenceNumber: 42 }); + done(); + }); + + const frame = new ZCLStandardHeader(); + frame.cmdId = 0x0a; // reportAttributes + frame.trxSequenceNumber = 42; + frame.frameControl.directionToClient = true; + // attributeId 0x0000 (onOff), dataType 0x10 (bool), value true + frame.data = Buffer.from([0x00, 0x00, 0x10, 0x01]); + + node.handleFrame(1, OnOffCluster.ID, frame.toBuffer(), { dstEndpoint: 1, linkQuality: 200 }); + }); +}); diff --git a/test/boundClusterAttributeStatus.js b/test/boundClusterAttributeStatus.js index 82992aaf..e02703d1 100644 --- a/test/boundClusterAttributeStatus.js +++ b/test/boundClusterAttributeStatus.js @@ -1,7 +1,7 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const BasicCluster = require('../lib/clusters/basic'); @@ -22,10 +22,10 @@ function readStatuses(response) { return BasicCluster.attributeArrayStatusDataType.fromBuffer(response.attributes, 0); } -describe('BoundCluster attribute status codes', function() { - describe('readAttributes', function() { - it('reports UNSUPPORTED_ATTRIBUTE for an id the cluster does not define', async function() { - const bound = bind(new class extends BoundCluster {}()); +describe('BoundCluster attribute status codes', function () { + describe('readAttributes', function () { + it('reports UNSUPPORTED_ATTRIBUTE for an id the cluster does not define', async function () { + const bound = bind(new (class extends BoundCluster {})()); const records = readStatuses(await bound.readAttributes({ attributes: [UNREGISTERED_ID] })); assert.equal(records.length, 1); @@ -35,49 +35,49 @@ describe('BoundCluster attribute status codes', function() { assert.equal(records[0].status, 'UNSUPPORTED_ATTRIBUTE'); }); - it('reports UNSUPPORTED_ATTRIBUTE for a defined but unimplemented attribute', async function() { - const bound = bind(new class extends BoundCluster {}()); + it('reports UNSUPPORTED_ATTRIBUTE for a defined but unimplemented attribute', async function () { + const bound = bind(new (class extends BoundCluster {})()); const records = readStatuses(await bound.readAttributes({ attributes: [MODEL_ID] })); assert.equal(records[0].status, 'UNSUPPORTED_ATTRIBUTE'); }); - it('still reports FAILURE when a getter throws', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - throw new Error('sensor offline'); - } - - }()); + it('still reports FAILURE when a getter throws', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + throw new Error('sensor offline'); + } + })(), + ); const records = readStatuses(await bound.readAttributes({ attributes: [MODEL_ID] })); // The attribute exists, so this is a genuine failure and must not be masked as unsupported. assert.equal(records[0].status, 'FAILURE'); }); - it('reports FAILURE when the value cannot be serialized', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - // A string too long for the one-octet length prefix of a ZCL character string. - return 'x'.repeat(300); - } - - }()); + it('reports FAILURE when the value cannot be serialized', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + // A string too long for the one-octet length prefix of a ZCL character string. + return 'x'.repeat(300); + } + })(), + ); const records = readStatuses(await bound.readAttributes({ attributes: [MODEL_ID] })); assert.equal(records[0].status, 'FAILURE'); }); - it('reports UNSUPPORTED_ATTRIBUTE for a write-only attribute, not 0x8f', async function() { - const bound = bind(new class extends BoundCluster { - - set modelId(value) { - this._modelId = value; - } - - }()); + it('reports UNSUPPORTED_ATTRIBUTE for a write-only attribute, not 0x8f', async function () { + const bound = bind( + new (class extends BoundCluster { + set modelId(value) { + this._modelId = value; + } + })(), + ); const records = readStatuses(await bound.readAttributes({ attributes: [MODEL_ID] })); // ZCL R8 deprecates WRITE_ONLY and reassigns 0x8f to NOT_AUTHORIZED ("a request has been @@ -87,14 +87,14 @@ describe('BoundCluster attribute status codes', function() { assert.equal(records[0].status, 'UNSUPPORTED_ATTRIBUTE'); }); - it('honours a ZCLError thrown by a getter instead of flattening it to FAILURE', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - throw new ZCLError('NOT_AUTHORIZED'); - } - - }()); + it('honours a ZCLError thrown by a getter instead of flattening it to FAILURE', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + throw new ZCLError('NOT_AUTHORIZED'); + } + })(), + ); const records = readStatuses(await bound.readAttributes({ attributes: [MODEL_ID] })); // The per-attribute status is data on the error, so an implementation can pick its own rather @@ -102,28 +102,28 @@ describe('BoundCluster attribute status codes', function() { assert.equal(records[0].status, 'NOT_AUTHORIZED'); }); - it('still reports SUCCESS with a value for an implemented attribute', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - return 'Homey'; - } - - }()); + it('still reports SUCCESS with a value for an implemented attribute', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + return 'Homey'; + } + })(), + ); const records = readStatuses(await bound.readAttributes({ attributes: [MODEL_ID] })); assert.equal(records[0].status, 'SUCCESS'); assert.equal(records[0].value, 'Homey'); }); - it('reports a per-attribute status, not one status for the whole request', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - return 'Homey'; - } - - }()); + it('reports a per-attribute status, not one status for the whole request', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + return 'Homey'; + } + })(), + ); const records = readStatuses( await bound.readAttributes({ attributes: [MODEL_ID, UNREGISTERED_ID] }), ); @@ -134,7 +134,7 @@ describe('BoundCluster attribute status codes', function() { }); }); - describe('writeAttributes', function() { + describe('writeAttributes', function () { /** Build the wire payload writeAttributes expects. */ function writeBuffer(records) { const buf = Buffer.alloc(255); @@ -142,8 +142,8 @@ describe('BoundCluster attribute status codes', function() { return buf.slice(0, len); } - it('reports UNSUPPORTED_ATTRIBUTE for an attribute this device does not implement', async function() { - const bound = bind(new class extends BoundCluster {}()); + it('reports UNSUPPORTED_ATTRIBUTE for an attribute this device does not implement', async function () { + const bound = bind(new (class extends BoundCluster {})()); const { attributes } = await bound.writeAttributes({ attributes: writeBuffer([{ id: MODEL_ID, value: 'Homey' }]), }); @@ -151,14 +151,14 @@ describe('BoundCluster attribute status codes', function() { assert.equal(attributes[0].status, 'UNSUPPORTED_ATTRIBUTE'); }); - it('reports READ_ONLY for an attribute exposed with a getter but no setter', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - return 'Homey'; - } - - }()); + it('reports READ_ONLY for an attribute exposed with a getter but no setter', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + return 'Homey'; + } + })(), + ); const { attributes } = await bound.writeAttributes({ attributes: writeBuffer([{ id: MODEL_ID, value: 'Other' }]), }); @@ -167,18 +167,18 @@ describe('BoundCluster attribute status codes', function() { assert.equal(attributes[0].status, 'READ_ONLY'); }); - it('honours a ZCLError thrown by a setter', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - return this._modelId; - } - - set modelId(value) { - throw new ZCLError('INVALID_VALUE'); - } - - }()); + it('honours a ZCLError thrown by a setter', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + return this._modelId; + } + + set modelId(value) { + throw new ZCLError('INVALID_VALUE'); + } + })(), + ); const { attributes } = await bound.writeAttributes({ attributes: writeBuffer([{ id: MODEL_ID, value: 'Other' }]), }); @@ -186,18 +186,18 @@ describe('BoundCluster attribute status codes', function() { assert.equal(attributes[0].status, 'INVALID_VALUE'); }); - it('still reports SUCCESS for a writable attribute', async function() { - const bound = bind(new class extends BoundCluster { - - get modelId() { - return this._modelId; - } - - set modelId(value) { - this._modelId = value; - } - - }()); + it('still reports SUCCESS for a writable attribute', async function () { + const bound = bind( + new (class extends BoundCluster { + get modelId() { + return this._modelId; + } + + set modelId(value) { + this._modelId = value; + } + })(), + ); const { attributes } = await bound.writeAttributes({ attributes: writeBuffer([{ id: MODEL_ID, value: 'Other' }]), }); diff --git a/test/colorControl.js b/test/colorControl.js index 1c192fbb..c84caa4c 100644 --- a/test/colorControl.js +++ b/test/colorControl.js @@ -1,63 +1,66 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); +const { describe, it, afterEach, mock } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const ColorControlCluster = require('../lib/clusters/colorControl'); const Endpoint = require('../lib/Endpoint'); const { createMockNode } = require('./util'); -const sandbox = sinon.createSandbox(); - // Sends colorLoopSet on a fresh node and returns the parsed outgoing frame, so tests can assert // the payload bytes against the ZCL spec instead of round-tripping through our own definition async function sendColorLoopSet(args) { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [ColorControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [ColorControlCluster.ID], + }, + ], }); - node.endpoints[1].bind('colorControl', new (class extends BoundCluster { - - async colorLoopSet() { - // Accept the command so no error response is generated - } - - })()); + node.endpoints[1].bind( + 'colorControl', + new (class extends BoundCluster { + async colorLoopSet() { + // Accept the command so no error response is generated + } + })(), + ); - const sendFrameSpy = sandbox.spy(node, 'sendFrame'); + const sendFrameSpy = mock.method(node, 'sendFrame'); await node.endpoints[1].clusters.colorControl.colorLoopSet(args); - return Endpoint.parseFrame(sendFrameSpy.getCall(0).args[2]); + return Endpoint.parseFrame(sendFrameSpy.mock.calls[0].arguments[2]); } -describe('Color Control', function() { - afterEach(function() { - sandbox.restore(); +describe('Color Control', function () { + afterEach(function () { + mock.restoreAll(); }); - it('should receive moveToColor', async function() { + it('should receive moveToColor', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [ColorControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [ColorControlCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('colorControl', new (class extends BoundCluster { - - async moveToColor(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'colorControl', + new (class extends BoundCluster { + async moveToColor(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.colorControl.moveToColor({ colorX: 0x5000, @@ -70,23 +73,26 @@ describe('Color Control', function() { assert.strictEqual(receivedData.transitionTime, 20); }); - it('should receive moveToColorTemperature', async function() { + it('should receive moveToColorTemperature', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [ColorControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [ColorControlCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('colorControl', new (class extends BoundCluster { - - async moveToColorTemperature(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'colorControl', + new (class extends BoundCluster { + async moveToColorTemperature(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.colorControl.moveToColorTemperature({ colorTemperature: 370, @@ -97,23 +103,26 @@ describe('Color Control', function() { assert.strictEqual(receivedData.transitionTime, 15); }); - it('should receive moveToHueAndSaturation', async function() { + it('should receive moveToHueAndSaturation', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [ColorControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [ColorControlCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('colorControl', new (class extends BoundCluster { - - async moveToHueAndSaturation(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'colorControl', + new (class extends BoundCluster { + async moveToHueAndSaturation(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.colorControl.moveToHueAndSaturation({ hue: 180, @@ -126,23 +135,26 @@ describe('Color Control', function() { assert.strictEqual(receivedData.transitionTime, 10); }); - it('should receive colorLoopSet', async function() { + it('should receive colorLoopSet', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [ColorControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [ColorControlCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('colorControl', new (class extends BoundCluster { - - async colorLoopSet(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'colorControl', + new (class extends BoundCluster { + async colorLoopSet(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.colorControl.colorLoopSet({ updateFlags: ['updateAction', 'updateDirection', 'updateTime', 'updateStartHue'], @@ -153,7 +165,10 @@ describe('Color Control', function() { }); assert.deepStrictEqual(receivedData.updateFlags.getBits(), [ - 'updateAction', 'updateDirection', 'updateTime', 'updateStartHue', + 'updateAction', + 'updateDirection', + 'updateTime', + 'updateStartHue', ]); assert.strictEqual(receivedData.action, 'activateFromColorLoopStartEnhancedHue'); assert.strictEqual(receivedData.direction, 'incrementHue'); @@ -165,7 +180,7 @@ describe('Color Control', function() { // that definition is wrong on the wire. These bytes come from the spec, not from our types: // ZCL r8 Figure 5-17 (payload layout), Figure 5-18 (updateFlags bits), Table 5.25 (action // values), Table 5.26 (direction values), Table 5.13 (command id). - it('should encode colorLoopSet as specified by the ZCL', async function() { + it('should encode colorLoopSet as specified by the ZCL', async function () { const frame = await sendColorLoopSet({ updateFlags: ['updateAction', 'updateStartHue'], // Bits 0 and 3, so 0x09 action: 'activateFromEnhancedCurrentHue', // 0x02 @@ -179,7 +194,7 @@ describe('Color Control', function() { }); // Setting every flag at once cannot tell the bit positions apart, so pin each one separately - it('should encode each colorLoopSet update flag on its own bit', async function() { + it('should encode each colorLoopSet update flag on its own bit', async function () { const flagBits = [ ['updateAction', 0x01], ['updateDirection', 0x02], @@ -188,7 +203,6 @@ describe('Color Control', function() { ]; for (const [flag, expectedByte] of flagBits) { - // eslint-disable-next-line no-await-in-loop const frame = await sendColorLoopSet({ updateFlags: [flag], action: 'deactivate', diff --git a/test/defaultResponse.js b/test/defaultResponse.js new file mode 100644 index 00000000..ea8474ee --- /dev/null +++ b/test/defaultResponse.js @@ -0,0 +1,66 @@ +'use strict'; + +const { describe, it } = require('node:test'); +const assert = require('node:assert'); + +const { Endpoint, BoundCluster } = require('..'); +const DoorLockCluster = require('../lib/clusters/doorLock'); + +// Door Lock setWeekDaySchedule is cluster-specific command 0x0B, same id as global Default Response +const SET_WEEK_DAY_SCHEDULE_REQUEST = Buffer.from([ + 0x01, 0x05, 0x0b, 0x01, 0x02, 0x00, 0x02, 0x08, 0x00, 0x17, 0x00, +]); + +function createEndpoint() { + const sentFrames = []; + const endpoint = new Endpoint( + { + sendFrame: async (_endpointId, _clusterId, frame) => { + sentFrames.push(frame.toString('hex')); + }, + }, + { endpointId: 1, inputClusters: [DoorLockCluster.ID], outputClusters: [] }, + ); + return { endpoint, sentFrames }; +} + +describe('Default Response', function () { + it('sends the cluster-specific response to a cluster-specific command 0x0B', async function () { + const { endpoint, sentFrames } = createEndpoint(); + endpoint.bind( + 'doorLock', + new (class extends BoundCluster { + async setWeekDaySchedule() { + return { status: 0 }; + } + })(), + ); + + await endpoint.handleFrame(DoorLockCluster.ID, SET_WEEK_DAY_SCHEDULE_REQUEST); + + assert.deepEqual(sentFrames, ['19050b00']); + }); + + it('sends an error Default Response to an unhandled cluster-specific command 0x0B', async function () { + const { endpoint, sentFrames } = createEndpoint(); + endpoint.bind('doorLock', new BoundCluster()); + + await endpoint.handleFrame(DoorLockCluster.ID, SET_WEEK_DAY_SCHEDULE_REQUEST); + // The error response is sent without awaiting, let it flush + await new Promise(setImmediate); + + // Default Response (0x0B) for command 0x0B with any error status; the exact status is not + // what this test is about + assert.equal(sentFrames.length, 1); + assert.match(sentFrames[0], /^18050b0b(?!00)[0-9a-f]{2}$/); + }); + + it('does not respond to a global Default Response', async function () { + const { endpoint, sentFrames } = createEndpoint(); + + await endpoint.handleFrame(DoorLockCluster.ID, Buffer.from([0x08, 0x05, 0x0b, 0x00, 0x00])); + await new Promise(setImmediate); + + assert.deepEqual(sentFrames, []); + }); +}); diff --git a/test/doorLock.js b/test/doorLock.js index 4c9c9ee5..842233c2 100644 --- a/test/doorLock.js +++ b/test/doorLock.js @@ -1,30 +1,33 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const DoorLockCluster = require('../lib/clusters/doorLock'); const { createMockNode } = require('./util'); const { ZCLStandardHeader } = require('../lib/zclFrames'); -describe('Door Lock', function() { - it('should receive lockDoor', async function() { +describe('Door Lock', function () { + it('should receive lockDoor', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [DoorLockCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [DoorLockCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('doorLock', new (class extends BoundCluster { - - async lockDoor(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'doorLock', + new (class extends BoundCluster { + async lockDoor(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.doorLock.lockDoor({ pinCode: Buffer.from([0x31, 0x32, 0x33, 0x34]), @@ -33,48 +36,54 @@ describe('Door Lock', function() { assert.deepStrictEqual(receivedData.pinCode, Buffer.from([0x31, 0x32, 0x33, 0x34])); }); - it('should receive lockDoor without arguments', async function() { + it('should receive lockDoor without arguments', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [DoorLockCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [DoorLockCluster.ID], + }, + ], }); let called = false; - node.endpoints[1].bind('doorLock', new (class extends BoundCluster { - - async lockDoor(data) { - called = true; - // pinCode should be empty buffer when not provided - assert.deepStrictEqual(data.pinCode, Buffer.from([])); - } - - })()); + node.endpoints[1].bind( + 'doorLock', + new (class extends BoundCluster { + async lockDoor(data) { + called = true; + // pinCode should be empty buffer when not provided + assert.deepStrictEqual(data.pinCode, Buffer.from([])); + } + })(), + ); // Call without any arguments - should not throw await node.endpoints[1].clusters.doorLock.lockDoor(); assert.strictEqual(called, true); }); - it('should receive unlockDoor', async function() { + it('should receive unlockDoor', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [DoorLockCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [DoorLockCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('doorLock', new (class extends BoundCluster { - - async unlockDoor(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'doorLock', + new (class extends BoundCluster { + async unlockDoor(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.doorLock.unlockDoor({ pinCode: Buffer.from([0x30, 0x30, 0x30, 0x30]), @@ -83,23 +92,26 @@ describe('Door Lock', function() { assert.deepStrictEqual(receivedData.pinCode, Buffer.from([0x30, 0x30, 0x30, 0x30])); }); - it('should receive setPINCode', async function() { + it('should receive setPINCode', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [DoorLockCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [DoorLockCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('doorLock', new (class extends BoundCluster { - - async setPINCode(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'doorLock', + new (class extends BoundCluster { + async setPINCode(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.doorLock.setPINCode({ userId: 1, @@ -116,16 +128,18 @@ describe('Door Lock', function() { // Server-to-client notifications require manual frame construction // since they are sent BY the device TO the controller - it('should receive operationEventNotification', function(done) { + it('should receive operationEventNotification', function (t, done) { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [DoorLockCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [DoorLockCluster.ID], + }, + ], }); - node.endpoints[1].clusters.doorLock.onOperationEventNotification = data => { + node.endpoints[1].clusters.doorLock.onOperationEventNotification = (data) => { assert.strictEqual(data.operationEventSource, 1); // Keypad assert.strictEqual(data.operationEventCode, 2); // Unlock assert.strictEqual(data.userId, 3); @@ -140,32 +154,31 @@ describe('Door Lock', function() { frame.frameControl.directionToClient = true; frame.frameControl.clusterSpecific = true; frame.data = Buffer.from([ - 0x01, 0x02, 0x03, 0x00, - 0x04, 0x31, 0x32, 0x33, 0x34, - 0x78, 0x56, 0x34, 0x12, - 0x00, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x31, 0x32, 0x33, 0x34, 0x78, 0x56, 0x34, 0x12, 0x00, ]); node.handleFrame(1, DoorLockCluster.ID, frame.toBuffer(), {}); }); - it('should receive programmingEventNotification', function(done) { + it('should receive programmingEventNotification', function (t, done) { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [DoorLockCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [DoorLockCluster.ID], + }, + ], }); - node.endpoints[1].clusters.doorLock.onProgrammingEventNotification = data => { + node.endpoints[1].clusters.doorLock.onProgrammingEventNotification = (data) => { assert.strictEqual(data.programEventSource, 2); // RF assert.strictEqual(data.programEventCode, 3); // PIN added assert.strictEqual(data.userId, 7); assert.deepStrictEqual(data.pin, Buffer.from([0x35, 0x36, 0x37, 0x38])); assert.strictEqual(data.userType, 'unrestricted'); assert.strictEqual(data.userStatus, 'occupiedEnabled'); - assert.strictEqual(data.zigBeeLocalTime, 0xAABBCCDD); + assert.strictEqual(data.zigBeeLocalTime, 0xaabbccdd); assert.deepStrictEqual(data.data, Buffer.from([])); done(); }; @@ -175,10 +188,7 @@ describe('Door Lock', function() { frame.frameControl.directionToClient = true; frame.frameControl.clusterSpecific = true; frame.data = Buffer.from([ - 0x02, 0x03, 0x07, 0x00, - 0x04, 0x35, 0x36, 0x37, 0x38, - 0x00, 0x01, - 0xDD, 0xCC, 0xBB, 0xAA, + 0x02, 0x03, 0x07, 0x00, 0x04, 0x35, 0x36, 0x37, 0x38, 0x00, 0x01, 0xdd, 0xcc, 0xbb, 0xaa, 0x00, ]); diff --git a/test/endpointStandalone.js b/test/endpointStandalone.js index eb8f0b9c..ae3d6fe8 100644 --- a/test/endpointStandalone.js +++ b/test/endpointStandalone.js @@ -1,6 +1,7 @@ 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const { Endpoint, BoundCluster } = require('..'); @@ -8,19 +9,17 @@ const BASIC_CLUSTER_ID = 0x0000; const MODEL_ID = 0x0005; class Basic extends BoundCluster { - get modelId() { return 'Homey Bridge'; } - } -describe('Endpoint standalone', function() { - it('serves bound clusters with nothing but a sendFrame owner', async function() { +describe('Endpoint standalone', function () { + it('serves bound clusters with nothing but a sendFrame owner', async function () { // The whole point of the export: a device answering incoming commands is not a peer, so it // should not have to construct a ZCLNode - which models one remote node and bakes that node's - // address into its own sendFrame. Endpoint touches its owner in exactly one place (sendFrame), - // so a plain object is enough. If that ever stops being true, this fails. + // address into its own sendFrame. Endpoint only needs sendFrame from its owner (nextSeqNr is + // optional), so a plain object is enough. If that ever stops being true, this fails. let sent; const endpoint = new Endpoint( { @@ -37,4 +36,14 @@ describe('Endpoint standalone', function() { assert.equal(sent.toString('hex'), '180701050000420c486f6d657920427269646765'); }); + + it('allocates transaction sequence numbers without a node counter', function () { + const endpoint = new Endpoint( + { sendFrame: async () => {} }, + { endpointId: 1, inputClusters: [BASIC_CLUSTER_ID], outputClusters: [] }, + ); + const first = endpoint.clusters.basic.nextSeqNr(); + + assert.equal(endpoint.clusters.basic.nextSeqNr(), (first + 1) % 256); + }); }); diff --git a/test/iasZone.js b/test/iasZone.js index c78d1f16..4fad1823 100644 --- a/test/iasZone.js +++ b/test/iasZone.js @@ -1,24 +1,26 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const IASZoneCluster = require('../lib/clusters/iasZone'); const { createMockNode, MOCK_DEVICES } = require('./util'); const { ZCLStandardHeader } = require('../lib/zclFrames'); -describe('IAS Zone', function() { +describe('IAS Zone', function () { // Server-to-client notification - requires manual frame - it('should receive onZoneEnrollRequest', function(done) { + it('should receive onZoneEnrollRequest', function (t, done) { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [IASZoneCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [IASZoneCluster.ID], + }, + ], }); - node.endpoints[1].clusters.iasZone.onZoneEnrollRequest = data => { + node.endpoints[1].clusters.iasZone.onZoneEnrollRequest = (data) => { assert.strictEqual(data.zoneType, 'keypad'); assert.strictEqual(data.manufacturerCode, 4117); done(); @@ -34,23 +36,26 @@ describe('IAS Zone', function() { }); // Client-to-server command - can use loopback - it('should send zoneEnrollResponse', async function() { + it('should send zoneEnrollResponse', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [IASZoneCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [IASZoneCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('iasZone', new (class extends BoundCluster { - - async zoneEnrollResponse(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'iasZone', + new (class extends BoundCluster { + async zoneEnrollResponse(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.iasZone.zoneEnrollResponse({ enrollResponseCode: 'success', @@ -62,16 +67,18 @@ describe('IAS Zone', function() { }); // Server-to-client notification - requires manual frame - it('should receive zoneStatusChangeNotification', function(done) { + it('should receive zoneStatusChangeNotification', function (t, done) { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [IASZoneCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [IASZoneCluster.ID], + }, + ], }); - node.endpoints[1].clusters.iasZone.onZoneStatusChangeNotification = data => { + node.endpoints[1].clusters.iasZone.onZoneStatusChangeNotification = (data) => { assert.strictEqual(data.zoneStatus.supervisionReports, true); assert.strictEqual(data.extendedStatus, 0); assert.strictEqual(data.zoneId, 10); @@ -83,27 +90,27 @@ describe('IAS Zone', function() { frame.cmdId = IASZoneCluster.COMMANDS.zoneStatusChangeNotification.id; frame.frameControl.directionToClient = true; frame.frameControl.clusterSpecific = true; - frame.data = Buffer.from([0x10, 0x00, 0x00, 0x0A, 0x6C, 0x00]); + frame.data = Buffer.from([0x10, 0x00, 0x00, 0x0a, 0x6c, 0x00]); node.handleFrame(1, IASZoneCluster.ID, frame.toBuffer(), {}); }); - describe('Mock Device Factory', function() { - it('should create a motion sensor with correct zone type', function() { + describe('Mock Device Factory', function () { + it('should create a motion sensor with correct zone type', function () { const sensor = MOCK_DEVICES.motionSensor(); const boundCluster = sensor.endpoints[1].bindings.iasZone; - assert.strictEqual(boundCluster.zoneType, 0x000D, 'Should be motion sensor type'); + assert.strictEqual(boundCluster.zoneType, 0x000d, 'Should be motion sensor type'); assert.strictEqual(boundCluster.zoneState, 1, 'Should be enrolled'); }); - it('should create a contact sensor with correct zone type', function() { + it('should create a contact sensor with correct zone type', function () { const sensor = MOCK_DEVICES.contactSensor(); const boundCluster = sensor.endpoints[1].bindings.iasZone; assert.strictEqual(boundCluster.zoneType, 0x0015, 'Should be contact switch type'); assert.strictEqual(boundCluster.zoneState, 1, 'Should be enrolled'); }); - it('should allow attribute overrides', function() { + it('should allow attribute overrides', function () { const sensor = MOCK_DEVICES.motionSensor({ iasZone: { zoneStatus: 0x0001 }, // Alarm1 active }); @@ -111,7 +118,7 @@ describe('IAS Zone', function() { assert.strictEqual(boundCluster.zoneStatus, 0x0001, 'Should have alarm1 bit set'); }); - it('should create temp/humidity sensor with measurement values', function() { + it('should create temp/humidity sensor with measurement values', function () { const sensor = MOCK_DEVICES.tempHumiditySensor(); const tempCluster = sensor.endpoints[1].bindings.temperatureMeasurement; const humCluster = sensor.endpoints[1].bindings.relativeHumidity; diff --git a/test/levelControl.js b/test/levelControl.js index 42728603..a1f6aded 100644 --- a/test/levelControl.js +++ b/test/levelControl.js @@ -1,29 +1,32 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const LevelControlCluster = require('../lib/clusters/levelControl'); const { createMockNode } = require('./util'); -describe('Level Control', function() { - it('should receive moveToLevel', async function() { +describe('Level Control', function () { + it('should receive moveToLevel', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [LevelControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [LevelControlCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('levelControl', new (class extends BoundCluster { - - async moveToLevel(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'levelControl', + new (class extends BoundCluster { + async moveToLevel(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.levelControl.moveToLevel({ level: 128, @@ -34,23 +37,26 @@ describe('Level Control', function() { assert.strictEqual(receivedData.transitionTime, 10); }); - it('should receive step', async function() { + it('should receive step', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [LevelControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [LevelControlCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('levelControl', new (class extends BoundCluster { - - async step(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'levelControl', + new (class extends BoundCluster { + async step(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.levelControl.step({ mode: 'up', @@ -63,23 +69,26 @@ describe('Level Control', function() { assert.strictEqual(receivedData.transitionTime, 5); }); - it('should receive stop', async function() { + it('should receive stop', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [LevelControlCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [LevelControlCluster.ID], + }, + ], }); let called = false; - node.endpoints[1].bind('levelControl', new (class extends BoundCluster { - - async stop() { - called = true; - } - - })()); + node.endpoints[1].bind( + 'levelControl', + new (class extends BoundCluster { + async stop() { + called = true; + } + })(), + ); await node.endpoints[1].clusters.levelControl.stop(); assert.strictEqual(called, true); diff --git a/test/manual/xiaomiHacks.js b/test/manual/xiaomiHacks.js index 2dc0dff3..90ef1a82 100644 --- a/test/manual/xiaomiHacks.js +++ b/test/manual/xiaomiHacks.js @@ -24,63 +24,70 @@ const attributes = { }; // custom data type parser with dynamic length with minimal 3 bytes, and no declared ZCL id. -const XiaomiLifelineDataRecord = new ZCLDataType(NaN, 'XiaomiLifelineDataRecord', -3, function(buf, v, i) { - throw new Error('generating xiaomi structs is not implemented'); -}, function(buf, i, returnLength) { - i = i || 0; - const startByte = i; - const res = {}; - res.id = ZCLDataTypes.uint8.fromBuffer(buf, i); - i += ZCLDataTypes.uint8.length; - - const dataTypeId = ZCLDataTypes.uint8.fromBuffer(buf, i); - i += ZCLDataTypes.uint8.length; - - // eslint-disable-next-line no-mixed-operators - const DataType = attributes[res.id] && attributes[res.id].type - // eslint-disable-next-line no-mixed-operators - || Object.values(ZCLDataTypes).find(type => type && type.id === dataTypeId); - if (!DataType) throw new TypeError(`Invalid Type for Attribute: ${res.id}`); - - // eslint-disable-next-line no-mixed-operators - res.name = attributes[res.id] && attributes[res.id].name || `unknown_attr_${res.id}`; - - const entry = DataType.fromBuffer(buf, i, true); - if (DataType.length > 0) { - i += DataType.length; - res.value = entry; - } else { - res.value = entry.result; - i += entry.length; - } - if (returnLength) { - return { result: res, length: i - startByte }; - } - return res; -}); - -const XiaomiLifelineDataRecordArray = new ZCLDataType(NaN, 'XiaomiLifelineDataRecordArray', -1, function(buf, v, i) { - throw new Error('not_supported'); -}, function(buf, i, returnLength) { - // eslint-disable-next-line prefer-const - let { result, length } = ZCLDataTypes.buffer8.fromBuffer(buf, i, true); - result = ZCLDataTypes.Array0(XiaomiLifelineDataRecord).fromBuffer(result, 0); - result = result.reduce((r, { name, value }) => Object.assign(r, { [name]: value }), {}); - if (returnLength) { - return { result, length }; - } - return result; -}); +const XiaomiLifelineDataRecord = new ZCLDataType( + NaN, + 'XiaomiLifelineDataRecord', + -3, + function (_buf, _v, _i) { + throw new Error('generating xiaomi structs is not implemented'); + }, + function (buf, i, returnLength) { + i = i || 0; + const startByte = i; + const res = {}; + res.id = ZCLDataTypes.uint8.fromBuffer(buf, i); + i += ZCLDataTypes.uint8.length; + + const dataTypeId = ZCLDataTypes.uint8.fromBuffer(buf, i); + i += ZCLDataTypes.uint8.length; + + const DataType = + (attributes[res.id] && attributes[res.id].type) || + Object.values(ZCLDataTypes).find((type) => type && type.id === dataTypeId); + if (!DataType) throw new TypeError(`Invalid Type for Attribute: ${res.id}`); + + res.name = (attributes[res.id] && attributes[res.id].name) || `unknown_attr_${res.id}`; + + const entry = DataType.fromBuffer(buf, i, true); + if (DataType.length > 0) { + i += DataType.length; + res.value = entry; + } else { + res.value = entry.result; + i += entry.length; + } + if (returnLength) { + return { result: res, length: i - startByte }; + } + return res; + }, +); + +const XiaomiLifelineDataRecordArray = new ZCLDataType( + NaN, + 'XiaomiLifelineDataRecordArray', + -1, + function (_buf, _v, _i) { + throw new Error('not_supported'); + }, + function (buf, i, returnLength) { + let { result, length } = ZCLDataTypes.buffer8.fromBuffer(buf, i, true); + result = ZCLDataTypes.Array0(XiaomiLifelineDataRecord).fromBuffer(result, 0); + result = result.reduce((r, { name, value }) => Object.assign(r, { [name]: value }), {}); + if (returnLength) { + return { result, length }; + } + return result; + }, +); class XiaomiHackedBasicCluster extends BasicCluster { - static get ATTRIBUTES() { return { ...super.ATTRIBUTES, - xiaomiLifeline: { id: 0xFF01, type: XiaomiLifelineDataRecordArray }, + xiaomiLifeline: { id: 0xff01, type: XiaomiLifelineDataRecordArray }, }; } - } // Replace basic cluster with our patched version diff --git a/test/onOff.js b/test/onOff.js index 8241c5b2..ba8bd77d 100644 --- a/test/onOff.js +++ b/test/onOff.js @@ -1,95 +1,107 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const OnOffCluster = require('../lib/clusters/onOff'); const { createMockNode } = require('./util'); -describe('On/Off', function() { - it('should receive setOn', async function() { +describe('On/Off', function () { + it('should receive setOn', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); let called = false; - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - called = true; - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + called = true; + } + })(), + ); await node.endpoints[1].clusters.onOff.setOn(); assert.strictEqual(called, true); }); - it('should receive setOff', async function() { + it('should receive setOff', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); let called = false; - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOff() { - called = true; - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOff() { + called = true; + } + })(), + ); await node.endpoints[1].clusters.onOff.setOff(); assert.strictEqual(called, true); }); - it('should receive toggle', async function() { + it('should receive toggle', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); let called = false; - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async toggle() { - called = true; - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async toggle() { + called = true; + } + })(), + ); await node.endpoints[1].clusters.onOff.toggle(); assert.strictEqual(called, true); }); - it('should receive onWithTimedOff', async function() { + it('should receive onWithTimedOff', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); let receivedData = null; - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async onWithTimedOff(data) { - receivedData = data; - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async onWithTimedOff(data) { + receivedData = data; + } + })(), + ); await node.endpoints[1].clusters.onOff.onWithTimedOff({ onOffControl: 0x01, diff --git a/test/ota.js b/test/ota.js index 0ed5d777..cb96e97a 100644 --- a/test/ota.js +++ b/test/ota.js @@ -1,7 +1,7 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const Node = require('../lib/Node'); const OTACluster = require('../lib/clusters/ota'); @@ -26,32 +26,35 @@ function createCapturingNode() { capturedFrames.push(buffer); return node.handleFrame(endpointId, clusterId, buffer, {}); }, - endpointDescriptors: [{ - endpointId: 1, - inputClusters: [OTACluster.ID], - outputClusters: [], - }], + endpointDescriptors: [ + { + endpointId: 1, + inputClusters: [OTACluster.ID], + outputClusters: [], + }, + ], }; node = new Node(mockNode); return { node, capturedFrames }; } -describe('OTA', function() { +describe('OTA', function () { // --- queryNextImageRequest: encodeMissingFieldsBehavior on the request --- - it('should NOT encode hardwareVersion when omitted from queryNextImageRequest', async function() { + it('should NOT encode hardwareVersion when omitted from queryNextImageRequest', async function () { const { node, capturedFrames } = createCapturingNode(); let receivedData = null; - node.endpoints[1].bind('ota', new (class extends BoundCluster { - - async queryNextImageRequest(data) { - receivedData = data; - return { status: 'NO_IMAGE_AVAILABLE' }; - } - - })()); + node.endpoints[1].bind( + 'ota', + new (class extends BoundCluster { + async queryNextImageRequest(data) { + receivedData = data; + return { status: 'NO_IMAGE_AVAILABLE' }; + } + })(), + ); await node.endpoints[1].clusters.ota.queryNextImageRequest({ fieldControl: 0, @@ -61,7 +64,7 @@ describe('OTA', function() { // hardwareVersion intentionally omitted }); - const requestFrame = capturedFrames.find(buf => buf[2] === CMD_QUERY_NEXT_IMAGE_REQUEST); + const requestFrame = capturedFrames.find((buf) => buf[2] === CMD_QUERY_NEXT_IMAGE_REQUEST); assert.ok(requestFrame, 'request frame not captured'); // fieldControl(1) + manufacturerCode(2) + imageType(2) + fileVersion(4) = 9 bytes @@ -80,16 +83,17 @@ describe('OTA', function() { assert.strictEqual(receivedData.hardwareVersion, 0); }); - it('should encode hardwareVersion when provided in queryNextImageRequest', async function() { + it('should encode hardwareVersion when provided in queryNextImageRequest', async function () { const { node, capturedFrames } = createCapturingNode(); - node.endpoints[1].bind('ota', new (class extends BoundCluster { - - async queryNextImageRequest() { - return { status: 'NO_IMAGE_AVAILABLE' }; - } - - })()); + node.endpoints[1].bind( + 'ota', + new (class extends BoundCluster { + async queryNextImageRequest() { + return { status: 'NO_IMAGE_AVAILABLE' }; + } + })(), + ); await node.endpoints[1].clusters.ota.queryNextImageRequest({ fieldControl: ['hardwareVersionPresent'], @@ -99,7 +103,7 @@ describe('OTA', function() { hardwareVersion: 0x0002, }); - const requestFrame = capturedFrames.find(buf => buf[2] === CMD_QUERY_NEXT_IMAGE_REQUEST); + const requestFrame = capturedFrames.find((buf) => buf[2] === CMD_QUERY_NEXT_IMAGE_REQUEST); assert.ok(requestFrame, 'request frame not captured'); // fieldControl(1) + manufacturerCode(2) + imageType(2) + fileVersion(4) @@ -117,22 +121,23 @@ describe('OTA', function() { // --- queryNextImageResponse: encodeMissingFieldsBehavior on the response --- - it('should encode all fields in queryNextImageResponse when status is SUCCESS', async function() { + it('should encode all fields in queryNextImageResponse when status is SUCCESS', async function () { const { node, capturedFrames } = createCapturingNode(); - node.endpoints[1].bind('ota', new (class extends BoundCluster { - - async queryNextImageRequest() { - return { - status: 'SUCCESS', - manufacturerCode: 0x1234, - imageType: 0x0001, - fileVersion: 0x00000020, - imageSize: 0x00010000, - }; - } - - })()); + node.endpoints[1].bind( + 'ota', + new (class extends BoundCluster { + async queryNextImageRequest() { + return { + status: 'SUCCESS', + manufacturerCode: 0x1234, + imageType: 0x0001, + fileVersion: 0x00000020, + imageSize: 0x00010000, + }; + } + })(), + ); const response = await node.endpoints[1].clusters.ota.queryNextImageRequest({ fieldControl: 0, @@ -141,7 +146,7 @@ describe('OTA', function() { fileVersion: 0x00000010, }); - const responseFrame = capturedFrames.find(buf => buf[2] === CMD_QUERY_NEXT_IMAGE_RESPONSE); + const responseFrame = capturedFrames.find((buf) => buf[2] === CMD_QUERY_NEXT_IMAGE_RESPONSE); assert.ok(responseFrame, 'response frame not captured'); // status(1) + manufacturerCode(2) + imageType(2) + fileVersion(4) + imageSize(4) = 13 bytes @@ -159,42 +164,42 @@ describe('OTA', function() { assert.strictEqual(response.imageSize, 0x00010000); }); - it('should encode only the status byte in queryNextImageResponse when status is NO_IMAGE_AVAILABLE', - async function() { - const { node, capturedFrames } = createCapturingNode(); - - node.endpoints[1].bind('ota', new (class extends BoundCluster { + it('should encode only the status byte in queryNextImageResponse when status is NO_IMAGE_AVAILABLE', async function () { + const { node, capturedFrames } = createCapturingNode(); + node.endpoints[1].bind( + 'ota', + new (class extends BoundCluster { async queryNextImageRequest() { return { status: 'NO_IMAGE_AVAILABLE' }; } + })(), + ); - })()); - - const response = await node.endpoints[1].clusters.ota.queryNextImageRequest({ - fieldControl: 0, - manufacturerCode: 0x1234, - imageType: 0x0001, - fileVersion: 0x00000010, - }); - - const responseFrame = capturedFrames.find(buf => buf[2] === CMD_QUERY_NEXT_IMAGE_RESPONSE); - assert.ok(responseFrame, 'response frame not captured'); - - // Only status(1) — all other fields must be absent - const payload = responseFrame.slice(ZCL_HEADER_SIZE); - assert.strictEqual( - payload.length, - 1, - `payload must be 1 byte (status only), got ${payload.length}`, - ); - assert.strictEqual(payload[0], 0x98, 'status byte must be NO_IMAGE_AVAILABLE (0x98)'); - - assert.strictEqual(response.status, 'NO_IMAGE_AVAILABLE'); - // Absent fields decode as 0 (decoder reads from exhausted buffer) - assert.strictEqual(response.manufacturerCode, 0); - assert.strictEqual(response.imageType, 0); - assert.strictEqual(response.fileVersion, 0); - assert.strictEqual(response.imageSize, 0); + const response = await node.endpoints[1].clusters.ota.queryNextImageRequest({ + fieldControl: 0, + manufacturerCode: 0x1234, + imageType: 0x0001, + fileVersion: 0x00000010, }); + + const responseFrame = capturedFrames.find((buf) => buf[2] === CMD_QUERY_NEXT_IMAGE_RESPONSE); + assert.ok(responseFrame, 'response frame not captured'); + + // Only status(1) — all other fields must be absent + const payload = responseFrame.slice(ZCL_HEADER_SIZE); + assert.strictEqual( + payload.length, + 1, + `payload must be 1 byte (status only), got ${payload.length}`, + ); + assert.strictEqual(payload[0], 0x98, 'status byte must be NO_IMAGE_AVAILABLE (0x98)'); + + assert.strictEqual(response.status, 'NO_IMAGE_AVAILABLE'); + // Absent fields decode as 0 (decoder reads from exhausted buffer) + assert.strictEqual(response.manufacturerCode, 0); + assert.strictEqual(response.imageType, 0); + assert.strictEqual(response.fileVersion, 0); + assert.strictEqual(response.imageSize, 0); + }); }); diff --git a/test/testClusterResponseTimeout.js b/test/testClusterResponseTimeout.js index bfa4e503..add10987 100644 --- a/test/testClusterResponseTimeout.js +++ b/test/testClusterResponseTimeout.js @@ -1,20 +1,21 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); +const { describe, it, beforeEach, afterEach, mock } = require('node:test'); +const assert = require('node:assert'); +const Cluster = require('../lib/Cluster'); const Node = require('../lib/Node'); +const { ZCLDataTypes } = require('../lib/zclTypes'); const BoundCluster = require('../lib/BoundCluster'); const OnOffCluster = require('../lib/clusters/onOff'); +const AlarmsCluster = require('../lib/clusters/alarms'); +const IasZoneCluster = require('../lib/clusters/iasZone'); -const sandbox = sinon.createSandbox(); - -describe('Cluster Response Timeout', function() { +describe('Cluster Response Timeout', function () { let receivingNode; let sendingNode; - beforeEach(function() { + beforeEach(function () { sendingNode = new Node({ // Forward frames to receiving node sendFrame: (...args) => { @@ -42,60 +43,71 @@ describe('Cluster Response Timeout', function() { }); }); - afterEach(function() { - sandbox.restore(); + afterEach(function () { + mock.restoreAll(); + mock.timers.reset(); }); - it('should only start timeout after frame is sent', async function() { + it('should only start timeout after frame is sent', async function () { + mock.timers.enable({ apis: ['setTimeout'] }); const originalSendFrame = sendingNode.endpoints[1].sendFrame.bind(sendingNode.endpoints[1]); - sandbox.stub(sendingNode.endpoints[1], 'sendFrame').callsFake(async (...args) => { + mock.method(sendingNode.endpoints[1], 'sendFrame', async (...args) => { // Delay sendFrame by 150ms (longer than timeout) - await new Promise(resolve => setTimeout(resolve, 150)); + await new Promise((resolve) => setTimeout(resolve, 150)); return originalSendFrame(...args); }); - receivingNode.endpoints[1].bind('onOff', new class extends BoundCluster { - - toggle() { - // Respond immediately - } - - }()); + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() { + // Respond immediately + } + })(), + ); // Start the command with 100ms timeout, if timeout starts immediately it will fire before // sendFrame completes and cause the command to fail - await sendingNode.endpoints[1].clusters.onOff.toggle(undefined, { timeout: 100 }); + const toggled = sendingNode.endpoints[1].clusters.onOff.toggle(undefined, { timeout: 100 }); + // Let the stubbed sendFrame reach its fake timer before advancing past the 100ms timeout. + await Promise.resolve(); + mock.timers.tick(150); + await toggled; }); - it('should clear timeout when response is received', async function() { - const clearTimeoutSpy = sandbox.spy(global, 'clearTimeout'); + it('should clear timeout when response is received', async function () { + const clearTimeoutSpy = mock.method(global, 'clearTimeout'); - receivingNode.endpoints[1].bind('onOff', new class extends BoundCluster { - - async toggle() { - // Respond after sendFrame resolved - return new Promise(resolve => setImmediate(resolve)); - } - - }()); + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async toggle() { + // Respond after sendFrame resolved + return new Promise((resolve) => setImmediate(resolve)); + } + })(), + ); await sendingNode.endpoints[1].clusters.onOff.toggle(undefined, { timeout: 5000 }); // Should have called clearTimeout to prevent timeout firing - assert(clearTimeoutSpy.called, 'clearTimeout should be called when response received'); + assert( + clearTimeoutSpy.mock.callCount() > 0, + 'clearTimeout should be called when response received', + ); }); - it('should not wait for response when waitForResponse is false', async function() { - const sendingNodeSendFrameSpy = sandbox.spy(sendingNode, 'sendFrame'); - - receivingNode.endpoints[1].bind('onOff', new class extends BoundCluster { + it('should not wait for response when waitForResponse is false', async function () { + const sendingNodeSendFrameSpy = mock.method(sendingNode, 'sendFrame'); - toggle() { - - // Respond with default response - } - - }()); + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() { + // Respond with default response + } + })(), + ); // Send command without waiting for response const result = await sendingNode.endpoints[1].clusters.onOff.toggle({ waitForResponse: false }); @@ -104,6 +116,259 @@ describe('Cluster Response Timeout', function() { assert.strictEqual(result, undefined); // Only one frame should be sent (the command itself) - assert.strictEqual(sendingNodeSendFrameSpy.callCount, 1); + assert.strictEqual(sendingNodeSendFrameSpy.mock.callCount(), 1); + }); + + it('should not resolve with a device-initiated frame that reuses the pending TSN', async function () { + const reportedValues = []; + sendingNode.endpoints[1].clusters.onOff.on('attr.onOff', (value) => reportedValues.push(value)); + + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async toggle(args, meta, frame) { + // Device sends an attribute report numbered from its own counter, colliding with the TSN + await sendingNode.handleFrame( + 1, + OnOffCluster.ID, + Buffer.from([0x18, frame.trxSequenceNumber, 0x0a, 0x00, 0x00, 0x10, 0x01]), + ); + } + })(), + ); + + const result = await sendingNode.endpoints[1].clusters.onOff.toggle(); + + assert.deepStrictEqual(reportedValues, [true]); + assert.strictEqual(result, undefined); + }); + + it('should resolve getAlarm with a Get Alarm Response alone', async function () { + const pair = [AlarmsCluster.ID]; + const sender = new Node({ + sendFrame: (...args) => receiver.handleFrame(...args), + endpointDescriptors: [{ endpointId: 1, inputClusters: pair }], + }); + const receiver = new Node({ + sendFrame: (...args) => sender.handleFrame(...args), + endpointDescriptors: [{ endpointId: 1, inputClusters: pair }], + }); + receiver.endpoints[1].bind( + 'alarms', + new (class extends BoundCluster { + getAlarm() { + return { + status: 'SUCCESS', + alarmCode: 2, + clusterId: 6, + timeStamp: 1234, + }; + } + })(), + ); + + const { alarms } = sender.endpoints[1].clusters; + const response = await alarms.getAlarm(undefined, { timeout: 1000 }); + + assert.strictEqual(response.alarmCode, 2); + assert.strictEqual(response.timeStamp, 1234); + }); + + it('should resolve a command without declared response on a cluster-specific reply', async function () { + class TuyaLikeCluster extends Cluster { + static get ID() { + return 0xef00; + } + + static get NAME() { + return 'tuyaLike'; + } + + static get COMMANDS() { + return { + datapoint: { id: 0x00, args: { value: ZCLDataTypes.uint8 } }, + dataResponse: { + id: 0x01, + direction: Cluster.DIRECTION_SERVER_TO_CLIENT, + args: { value: ZCLDataTypes.uint8 }, + }, + }; + } + } + Cluster.addCluster(TuyaLikeCluster); + + try { + const pair = [TuyaLikeCluster.ID]; + const sender = new Node({ + sendFrame: (...args) => receiver.handleFrame(...args), + endpointDescriptors: [{ endpointId: 1, inputClusters: pair }], + }); + const receiver = new Node({ + sendFrame: (...args) => sender.handleFrame(...args), + endpointDescriptors: [{ endpointId: 1, inputClusters: pair }], + }); + receiver.endpoints[1].bind( + 'tuyaLike', + new (class extends BoundCluster { + // Reply like a Tuya MCU: its own command with the request's TSN, no Default Response + async datapoint({ value }, meta, frame) { + await sender.handleFrame( + 1, + TuyaLikeCluster.ID, + Buffer.from([0x19, frame.trxSequenceNumber, 0x01, value]), + ); + } + })(), + ); + + const { tuyaLike } = sender.endpoints[1].clusters; + const response = await tuyaLike.datapoint( + { value: 7 }, + { disableDefaultResponse: true, timeout: 1000 }, + ); + + assert.strictEqual(response.value, 7); + } finally { + Cluster.removeCluster(TuyaLikeCluster.ID); + } + }); + + it('should treat a declared response without id as the command id', async function () { + class EchoCluster extends Cluster { + static get ID() { + return 0xfc01; + } + + static get NAME() { + return 'echo'; + } + + static get COMMANDS() { + return { + ping: { + id: 0x05, + args: { value: ZCLDataTypes.uint8 }, + response: { args: { value: ZCLDataTypes.uint8 } }, + }, + notify: { + id: 0x06, + direction: Cluster.DIRECTION_SERVER_TO_CLIENT, + args: { value: ZCLDataTypes.uint8 }, + }, + }; + } + } + Cluster.addCluster(EchoCluster); + + try { + const pair = [EchoCluster.ID]; + const sender = new Node({ + sendFrame: (...args) => receiver.handleFrame(...args), + endpointDescriptors: [{ endpointId: 1, inputClusters: pair }], + }); + const receiver = new Node({ + sendFrame: (...args) => sender.handleFrame(...args), + endpointDescriptors: [{ endpointId: 1, inputClusters: pair }], + }); + receiver.endpoints[1].bind( + 'echo', + new (class extends BoundCluster { + // An unrelated device command reuses the TSN first, then the real response (id 0x05) + async ping({ value }, meta, frame) { + await sender.handleFrame( + 1, + EchoCluster.ID, + Buffer.from([0x19, frame.trxSequenceNumber, 0x06, 99]), + ); + return { value }; + } + })(), + ); + + const { echo } = sender.endpoints[1].clusters; + const response = await echo.ping({ value: 7 }, { timeout: 1000 }); + + assert.strictEqual(response.value, 7); + } finally { + Cluster.removeCluster(EchoCluster.ID); + } + }); + + describe('pending response matching', function () { + // Node pair where the receiving side first sends `colliding(tsn)` with the request's TSN, + // then its real reply + function createCollidingPair(clusterId, colliding) { + const descriptors = [{ endpointId: 1, inputClusters: [clusterId] }]; + const sender = new Node({ + sendFrame: (...args) => receiver.handleFrame(...args), + endpointDescriptors: descriptors, + }); + const receiver = new Node({ + sendFrame: async (endpointId, frameClusterId, frame) => { + await sender.handleFrame(endpointId, frameClusterId, colliding(frame[1])); + await sender.handleFrame(endpointId, frameClusterId, frame); + }, + endpointDescriptors: descriptors, + }); + return { sender, receiver }; + } + + it('should not resolve a global command on a cluster-specific frame with its response id', async function () { + // IAS Zone Enroll Request is cluster-specific 0x01, the same id as Read Attributes Response + const { sender, receiver } = createCollidingPair(IasZoneCluster.ID, (tsn) => + Buffer.from([0x19, tsn, 0x01, 0x0d, 0x00, 0x00, 0x00]), + ); + receiver.endpoints[1].bind( + 'iasZone', + new (class extends BoundCluster { + get zoneState() { + return 'enrolled'; + } + })(), + ); + + const { iasZone } = sender.endpoints[1].clusters; + const result = await iasZone.readAttributes(['zoneState'], { timeout: 1000 }); + + assert.deepStrictEqual(result, { zoneState: 'enrolled' }); + }); + + it('should not resolve on a Default Response for another command', async function () { + // Default Response with FAILURE for cmdId 0x01 (on), while toggle (0x02) is pending + const { sender, receiver } = createCollidingPair(OnOffCluster.ID, (tsn) => + Buffer.from([0x18, tsn, 0x0b, 0x01, 0x01]), + ); + receiver.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() {} + })(), + ); + + await sender.endpoints[1].clusters.onOff.toggle(undefined, { timeout: 1000 }); + }); + }); + + it('should resolve when the response arrives before sendFrame rejects', async function () { + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() {} + })(), + ); + sendingNode.sendFrame = async (endpointId, clusterId, frame) => { + await receivingNode.handleFrame(endpointId, clusterId, frame); + throw new Error('device not responding'); + }; + + await sendingNode.endpoints[1].clusters.onOff.toggle(); + }); + + it('should reject when sendFrame rejects without a response', async function () { + sendingNode.sendFrame = async () => { + throw new Error('device not responding'); + }; + + await assert.rejects(sendingNode.endpoints[1].clusters.onOff.toggle(), /device not responding/); }); }); diff --git a/test/testConfigureReportingRecordsStruct.js b/test/testConfigureReportingRecordsStruct.js index 016110b1..9c0d5192 100644 --- a/test/testConfigureReportingRecordsStruct.js +++ b/test/testConfigureReportingRecordsStruct.js @@ -1,10 +1,9 @@ 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); -const { - ZCLConfigureReportingRecords, -} = require('../lib/zclFrames'); +const { ZCLConfigureReportingRecords } = require('../lib/zclFrames'); const CONFIGURE_REPORTING_RECORDS_MOCK = [ { @@ -80,8 +79,8 @@ const CONFIGURE_REPORTING_RECORDS_WITH_STATUS_BUFFER_MOCK = Buffer.from( 'hex', ); -describe('command configure reporting', function() { - it('should parse multiple records to buffer', function() { +describe('command configure reporting', function () { + it('should parse multiple records to buffer', function () { // Create type instance const ZCLConfigureReportingRecordsType = ZCLConfigureReportingRecords(); @@ -95,13 +94,15 @@ describe('command configure reporting', function() { assert(buf.equals(CONFIGURE_REPORTING_RECORDS_BUFFER_MOCK)); }); - it('should parse buffer to multiple records', function() { + it('should parse buffer to multiple records', function () { // Create type instance const ZCLConfigureReportingRecordsType = ZCLConfigureReportingRecords(); // Allocate buffer to be filled with configure reporting records - const parsedRecords = ZCLConfigureReportingRecordsType - .fromBuffer(CONFIGURE_REPORTING_RECORDS_BUFFER_MOCK, 0); + const parsedRecords = ZCLConfigureReportingRecordsType.fromBuffer( + CONFIGURE_REPORTING_RECORDS_BUFFER_MOCK, + 0, + ); // Compare the parsed records against the initial records `configureReportingRecordsBuffer` for (let i = 0; i < CONFIGURE_REPORTING_RECORDS_MOCK.length; i++) { @@ -110,8 +111,8 @@ describe('command configure reporting', function() { }); }); -describe('command read configure reporting', function() { - it('should parse multiple records to buffer', function() { +describe('command read configure reporting', function () { + it('should parse multiple records to buffer', function () { // Create type instance const ZCLConfigureReportingRecordsWithStatusType = ZCLConfigureReportingRecords({ withStatus: true, @@ -129,15 +130,17 @@ describe('command read configure reporting', function() { assert(buf.equals(CONFIGURE_REPORTING_RECORDS_WITH_STATUS_BUFFER_MOCK)); }); - it('should parse buffer to multiple records', function() { + it('should parse buffer to multiple records', function () { // Create type instance const ZCLConfigureReportingRecordsWithStatusType = ZCLConfigureReportingRecords({ withStatus: true, }); // Allocate buffer to be filled with configure reporting records - const parsedRecords = ZCLConfigureReportingRecordsWithStatusType - .fromBuffer(CONFIGURE_REPORTING_RECORDS_WITH_STATUS_BUFFER_MOCK, 0); + const parsedRecords = ZCLConfigureReportingRecordsWithStatusType.fromBuffer( + CONFIGURE_REPORTING_RECORDS_WITH_STATUS_BUFFER_MOCK, + 0, + ); // Compare the parsed records against the initial records `configureReportingRecordsBuffer` for (let i = 0; i < CONFIGURE_REPORTING_RECORDS_WITH_STATUS_MOCK.length; i++) { diff --git a/test/testMfgSpecificCommands.js b/test/testMfgSpecificCommands.js index 5c3a96e6..8bf9f29e 100644 --- a/test/testMfgSpecificCommands.js +++ b/test/testMfgSpecificCommands.js @@ -1,7 +1,7 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const Cluster = require('../lib/Cluster'); const { ZCLDataTypes } = require('../lib/zclTypes'); const BoundCluster = require('../lib/BoundCluster'); @@ -11,7 +11,6 @@ const MANUFACTURER_ID_1 = 0x1234; const MANUFACTURER_ID_2 = 0x4321; class IkeaSceneCluster extends SceneCluster { - static get ATTRIBUTES() { return { sceneCount: { @@ -41,7 +40,7 @@ class IkeaSceneCluster extends SceneCluster { ...super.COMMANDS, ikeaSceneStep: { id: 0x07, - manufacturerId: 0x117C, + manufacturerId: 0x117c, args: { mode: ZCLDataTypes.enum8({ up: 0, @@ -53,7 +52,7 @@ class IkeaSceneCluster extends SceneCluster { }, ikeaSceneMove: { id: 0x08, - manufacturerId: 0x117C, + manufacturerId: 0x117c, args: { mode: ZCLDataTypes.enum8({ up: 0, @@ -64,14 +63,13 @@ class IkeaSceneCluster extends SceneCluster { }, ikeaSceneMoveStop: { id: 0x09, - manufacturerId: 0x117C, + manufacturerId: 0x117c, args: { duration: ZCLDataTypes.uint16, }, }, }; } - } Cluster.addCluster(IkeaSceneCluster); @@ -79,14 +77,15 @@ const { createMockNode } = require('./util'); const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [SceneCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [SceneCluster.ID], + }, + ], }); class IkeaBoundCluster extends BoundCluster { - constructor({ onReadAttributes, onWriteAttributes, @@ -107,11 +106,10 @@ class IkeaBoundCluster extends BoundCluster { if (onIkeaSceneMove) this.ikeaSceneMove = onIkeaSceneMove; if (onIkeaSceneMoveStop) this.ikeaSceneMoveStop = onIkeaSceneMoveStop; } - } -describe('manufacturer specific commands', function() { - it('should execute custom commands', function(done) { +describe('manufacturer specific commands', function () { + it('should execute custom commands', function (t, done) { let commandsExecuted = 0; const ikeaSceneStepCommand = { mode: 'up', @@ -125,147 +123,182 @@ describe('manufacturer specific commands', function() { const ikeaSceneMoveStop = { duration: 1000, }; - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onIkeaSceneStep: payload => { - commandsExecuted++; - assert.deepStrictEqual({ ...payload }, ikeaSceneStepCommand); - if (commandsExecuted === 3) done(); - }, - onIkeaSceneMove: payload => { - commandsExecuted++; - assert.deepStrictEqual({ ...payload }, ikeaSceneMoveCommand); - if (commandsExecuted === 3) done(); - }, - onIkeaSceneMoveStop: payload => { - commandsExecuted++; - assert.deepStrictEqual({ ...payload }, ikeaSceneMoveStop); - if (commandsExecuted === 3) done(); - }, - })); + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onIkeaSceneStep: (payload) => { + commandsExecuted++; + assert.deepStrictEqual({ ...payload }, ikeaSceneStepCommand); + if (commandsExecuted === 3) done(); + }, + onIkeaSceneMove: (payload) => { + commandsExecuted++; + assert.deepStrictEqual({ ...payload }, ikeaSceneMoveCommand); + if (commandsExecuted === 3) done(); + }, + onIkeaSceneMoveStop: (payload) => { + commandsExecuted++; + assert.deepStrictEqual({ ...payload }, ikeaSceneMoveStop); + if (commandsExecuted === 3) done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].ikeaSceneStep(ikeaSceneStepCommand); node.endpoints[1].clusters['scenes'].ikeaSceneMove(ikeaSceneMoveCommand); node.endpoints[1].clusters['scenes'].ikeaSceneMoveStop(ikeaSceneMoveStop); }); - describe('global commands', function() { - describe('readAttributes', function() { - it('should set correct manufacturerId', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onReadAttributes: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); - done(); - }, - })); + describe('global commands', function () { + describe('readAttributes', function () { + it('should set correct manufacturerId', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onReadAttributes: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].readAttributes(['sceneCount']); }); - it('should throw when different manufacturerIds are found', function(done) { - node.endpoints[1].clusters['scenes'].readAttributes(['sceneCount', 'currentScene']) - .catch(err => { + it('should throw when different manufacturerIds are found', function (t, done) { + node.endpoints[1].clusters['scenes'] + .readAttributes(['sceneCount', 'currentScene']) + .catch((err) => { assert(err instanceof Error); done(); }); }); - it('should set correct manufacturerId for multiple attributes', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onReadAttributes: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); - done(); - }, - })); + it('should set correct manufacturerId for multiple attributes', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onReadAttributes: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].readAttributes(['currentScene', 'currentGroup']); }); - it('should not set manufacturerId when zcl attribute is present', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onReadAttributes: (payload, meta, rawPayload) => { - assert.strictEqual(undefined, rawPayload.manufacturerId); - done(); - }, - })); + it('should not set manufacturerId when zcl attribute is present', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onReadAttributes: (payload, meta, rawPayload) => { + assert.strictEqual(undefined, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].readAttributes(['sceneValid']); }); }); - describe('writeAttributes', function() { - it('should set correct manufacturerId', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onWriteAttributes: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); - done(); - }, - })); + describe('writeAttributes', function () { + it('should set correct manufacturerId', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onWriteAttributes: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].writeAttributes({ sceneCount: 1 }); }); - it('should throw when different manufacturerIds are found', function(done) { - node.endpoints[1].clusters['scenes'].writeAttributes({ sceneCount: 1, currentScene: 2 }) - .catch(err => { + it('should throw when different manufacturerIds are found', function (t, done) { + node.endpoints[1].clusters['scenes'] + .writeAttributes({ sceneCount: 1, currentScene: 2 }) + .catch((err) => { assert(err instanceof Error); done(); }); }); - it('should set correct manufacturerId for multiple attributes', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onWriteAttributes: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); - done(); - }, - })); + it('should set correct manufacturerId for multiple attributes', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onWriteAttributes: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].writeAttributes({ currentScene: 1, currentGroup: 2 }); }); - it('should not set manufacturerId when zcl attribute is present', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onWriteAttributes: (payload, meta, rawPayload) => { - assert.strictEqual(undefined, rawPayload.manufacturerId); - done(); - }, - })); + it('should not set manufacturerId when zcl attribute is present', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onWriteAttributes: (payload, meta, rawPayload) => { + assert.strictEqual(undefined, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].writeAttributes({ sceneValid: true }); }); }); - describe('configureReporting', function() { - it('should set correct manufacturerId', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onConfigureReporting: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); - done(); - }, - })); - node.endpoints[1].clusters['scenes'].configureReporting({ sceneCount: { minInterval: 0, maxInterval: 300, minChange: 1 } }); - }); - it('should throw when different manufacturerIds are found', function(done) { + describe('configureReporting', function () { + it('should set correct manufacturerId', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onConfigureReporting: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].configureReporting({ sceneCount: { minInterval: 0, maxInterval: 300, minChange: 1 }, - currentScene: { minInterval: 0, maxInterval: 300, minChange: 1 }, - }) - .catch(err => { + }); + }); + it('should throw when different manufacturerIds are found', function (t, done) { + node.endpoints[1].clusters['scenes'] + .configureReporting({ + sceneCount: { minInterval: 0, maxInterval: 300, minChange: 1 }, + currentScene: { minInterval: 0, maxInterval: 300, minChange: 1 }, + }) + .catch((err) => { assert(err instanceof Error); done(); }); }); - it('should set correct manufacturerId for multiple attributes', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onConfigureReporting: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); - done(); - }, - })); + it('should set correct manufacturerId for multiple attributes', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onConfigureReporting: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].configureReporting({ currentScene: { minInterval: 0, maxInterval: 300, minChange: 1 }, currentGroup: { minInterval: 0, maxInterval: 300, minChange: 1 }, }); }); - it('should not set manufacturerId when zcl attribute is present', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onConfigureReporting: (payload, meta, rawPayload) => { - assert.strictEqual(undefined, rawPayload.manufacturerId); - done(); - }, - })); + it('should not set manufacturerId when zcl attribute is present', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onConfigureReporting: (payload, meta, rawPayload) => { + assert.strictEqual(undefined, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].configureReporting({ sceneValid: { minInterval: 0, maxInterval: 300, minChange: 1 }, @@ -274,41 +307,57 @@ describe('manufacturer specific commands', function() { }); }); - describe('readReportingConfiguration', function() { - it('should set correct manufacturerId', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onReadReportingConfiguration: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); - done(); - }, - })); + describe('readReportingConfiguration', function () { + it('should set correct manufacturerId', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onReadReportingConfiguration: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_1, rawPayload.manufacturerId); + done(); + }, + }), + ); node.endpoints[1].clusters['scenes'].readReportingConfiguration(['sceneCount']); }); - it('should throw when different manufacturerIds are found', function(done) { - node.endpoints[1].clusters['scenes'].readReportingConfiguration(['sceneCount', 'currentScene']) - .catch(err => { + it('should throw when different manufacturerIds are found', function (t, done) { + node.endpoints[1].clusters['scenes'] + .readReportingConfiguration(['sceneCount', 'currentScene']) + .catch((err) => { assert(err instanceof Error); done(); }); }); - it('should set correct manufacturerId for multiple attributes', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onReadReportingConfiguration: (payload, meta, rawPayload) => { - assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); - done(); - }, - })); - node.endpoints[1].clusters['scenes'].readReportingConfiguration(['currentGroup', 'currentScene']); + it('should set correct manufacturerId for multiple attributes', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onReadReportingConfiguration: (payload, meta, rawPayload) => { + assert.strictEqual(MANUFACTURER_ID_2, rawPayload.manufacturerId); + done(); + }, + }), + ); + node.endpoints[1].clusters['scenes'].readReportingConfiguration([ + 'currentGroup', + 'currentScene', + ]); }); - it('should not set manufacturerId when zcl attribute is present', function(done) { - node.endpoints[1].bind('scenes', new IkeaBoundCluster({ - onReadReportingConfiguration: (payload, meta, rawPayload) => { - assert.strictEqual(undefined, rawPayload.manufacturerId); - done(); - }, - })); + it('should not set manufacturerId when zcl attribute is present', function (t, done) { + node.endpoints[1].bind( + 'scenes', + new IkeaBoundCluster({ + onReadReportingConfiguration: (payload, meta, rawPayload) => { + assert.strictEqual(undefined, rawPayload.manufacturerId); + done(); + }, + }), + ); - node.endpoints[1].clusters['scenes'].readReportingConfiguration(['currentGroup', 'sceneValid']); + node.endpoints[1].clusters['scenes'].readReportingConfiguration([ + 'currentGroup', + 'sceneValid', + ]); }); }); }); diff --git a/test/testNode.js b/test/testNode.js index 15d78a32..d0a9738a 100644 --- a/test/testNode.js +++ b/test/testNode.js @@ -1,8 +1,7 @@ -// eslint-disable-next-line max-classes-per-file,lines-around-directive 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); +const { describe, it, before, afterEach, mock } = require('node:test'); +const assert = require('node:assert'); const { createMockNode, createConnectedNodePair } = require('./util'); let { debug } = require('./util'); @@ -15,33 +14,37 @@ const OnOffCluster = require('../lib/clusters/onOff'); debug = debug.extend('test-node'); -const sandbox = sinon.createSandbox(); - -describe('Node', function() { +describe('Node', function () { let mockNode; let receivingNode; let sendingNode; - before(function() { + before(function () { mockNode = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [BasicCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [BasicCluster.ID], + }, + ], }); [sendingNode, receivingNode] = createConnectedNodePair( { - endpoints: [{ - endpointId: 1, - inputClusters: [BasicCluster.ID, OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [BasicCluster.ID, OnOffCluster.ID], + }, + ], }, { - endpoints: [{ - endpointId: 1, - inputClusters: [BasicCluster.ID, OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [BasicCluster.ID, OnOffCluster.ID], + }, + ], }, ); // Override log id for sending node @@ -53,10 +56,10 @@ describe('Node', function() { receivingNode.getLogId = receivingNodeLog; receivingNode.endpoints[1].getLogId = receivingNodeLog; }); - afterEach(function() { - sandbox.restore(); + afterEach(function () { + mock.restoreAll(); }); - it('should fail for unbound cluster', async function() { + it('should fail for unbound cluster', async function () { try { await mockNode.endpoints[1].clusters['basic'].configureReporting({ zclVersion: { @@ -64,43 +67,45 @@ describe('Node', function() { maxInterval: 4321, }, }); - } catch (e) { + } catch { return; } - throw new Error('didn\'t throw'); + throw new Error("didn't throw"); }); - it('should fail for unimplemented command', async function() { + it('should fail for unimplemented command', async function () { mockNode.endpoints[1].bind('basic', new BoundCluster()); try { await mockNode.endpoints[1].clusters['basic'].factoryReset(); - } catch (e) { + } catch { return; } - throw new Error('didn\'t throw'); + throw new Error("didn't throw"); }); - it('should invoke command', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - async factoryReset() { - debug('factory reset'); - } - - }()); + it('should invoke command', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + async factoryReset() { + debug('factory reset'); + } + })(), + ); await mockNode.endpoints[1].clusters['basic'].factoryReset(); }); - it('should configure reporting', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - async configureReporting({ reports }) { - assert.equal(reports.length, 1, 'exactly 1 report'); - } - - }()); + it('should configure reporting', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + async configureReporting({ reports }) { + assert.equal(reports.length, 1, 'exactly 1 report'); + } + })(), + ); await mockNode.endpoints[1].clusters['basic'].configureReporting({ zclVersion: { @@ -110,25 +115,32 @@ describe('Node', function() { }); }); - it('should read attributes', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - constructor() { - super(); - this.dateCode = '1234'; - } - - get modelId() { - return 'test'; - } - - get manufacturerName() { - return 'Athom'; - } - - }()); + it('should read attributes', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + constructor() { + super(); + this.dateCode = '1234'; + } + + get modelId() { + return 'test'; + } + + get manufacturerName() { + return 'Athom'; + } + })(), + ); - const res = await mockNode.endpoints[1].clusters['basic'].readAttributes(['modelId', 'manufacturerName', 'clusterRevision', 'zclVersion', 'dateCode']); + const res = await mockNode.endpoints[1].clusters['basic'].readAttributes([ + 'modelId', + 'manufacturerName', + 'clusterRevision', + 'zclVersion', + 'dateCode', + ]); assert.equal(res.modelId, 'test', 'modelId should be test'); assert.equal(res.manufacturerName, 'Athom', 'manufacturerName should be test'); assert.equal(res.clusterRevision, 1, 'clusterRevision should be test'); @@ -136,242 +148,300 @@ describe('Node', function() { assert.equal(res.dateCode, '1234', 'dateCode should not be present'); }); - it('should read attributes by numeric ID', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - get modelId() { - return 'numericTest'; - } - - }()); + it('should read attributes by numeric ID', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'numericTest'; + } + })(), + ); // modelId has attribute ID 5 const res = await mockNode.endpoints[1].clusters['basic'].readAttributes([5]); assert.equal(res[5], 'numericTest', 'numeric ID 5 should return modelId value'); }); - it('should read attributes with mixed strings and numeric IDs', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - get modelId() { - return 'mixedTest'; - } - - get manufacturerName() { - return 'Athom'; - } - - }()); + it('should read attributes with mixed strings and numeric IDs', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'mixedTest'; + } + + get manufacturerName() { + return 'Athom'; + } + })(), + ); // manufacturerName by name, modelId (ID 5) by numeric ID - const res = await mockNode.endpoints[1].clusters['basic'].readAttributes(['manufacturerName', 5]); + const res = await mockNode.endpoints[1].clusters['basic'].readAttributes([ + 'manufacturerName', + 5, + ]); assert.equal(res.manufacturerName, 'Athom', 'manufacturerName should resolve by name'); assert.equal(res[5], 'mixedTest', 'numeric ID 5 should return modelId value'); }); - it('should return both name and numeric key when same attribute requested both ways', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - get modelId() { - return 'both'; - } - - }()); + it('should return both name and numeric key when same attribute requested both ways', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'both'; + } + })(), + ); const res = await mockNode.endpoints[1].clusters['basic'].readAttributes(['modelId', 5]); assert.equal(res.modelId, 'both', 'modelId key should exist'); assert.equal(res[5], 'both', 'numeric key 5 should also exist'); }); - it('should read an unregistered attribute by numeric ID', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster {}()); + it('should read an unregistered attribute by numeric ID', async function () { + mockNode.endpoints[1].bind('basic', new (class extends BoundCluster {})()); // 0x1234 is not registered in the basic cluster, expect no error and empty/missing result const res = await mockNode.endpoints[1].clusters['basic'].readAttributes([0x1234]); assert.equal(res[0x1234], undefined, 'unregistered attribute should not have a value'); }); - it('should throw for invalid numeric attribute IDs', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster {}()); + it('should throw for invalid numeric attribute IDs', async function () { + mockNode.endpoints[1].bind('basic', new (class extends BoundCluster {})()); - await assert.rejects( - () => mockNode.endpoints[1].clusters['basic'].readAttributes([-1]), - { name: 'TypeError' }, - ); - await assert.rejects( - () => mockNode.endpoints[1].clusters['basic'].readAttributes([0x10000]), - { name: 'TypeError' }, - ); - await assert.rejects( - () => mockNode.endpoints[1].clusters['basic'].readAttributes([1.5]), - { name: 'TypeError' }, - ); - await assert.rejects( - () => mockNode.endpoints[1].clusters['basic'].readAttributes([NaN]), - { name: 'TypeError' }, - ); + await assert.rejects(() => mockNode.endpoints[1].clusters['basic'].readAttributes([-1]), { + name: 'TypeError', + }); + await assert.rejects(() => mockNode.endpoints[1].clusters['basic'].readAttributes([0x10000]), { + name: 'TypeError', + }); + await assert.rejects(() => mockNode.endpoints[1].clusters['basic'].readAttributes([1.5]), { + name: 'TypeError', + }); + await assert.rejects(() => mockNode.endpoints[1].clusters['basic'].readAttributes([NaN]), { + name: 'TypeError', + }); }); - it('should respond with read attribute response when disableDefaultResponse is true', async function() { - receivingNode.endpoints[1].bind('basic', new class extends BoundCluster { - - get modelId() { - return 'test'; - } - - }()); + it('should respond with read attribute response when disableDefaultResponse is true', async function () { + receivingNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'test'; + } + })(), + ); - const readAttributesResponse = await sendingNode.endpoints[1].clusters['basic'].readAttributes(['modelId'], { disableDefaultResponse: true }); + const readAttributesResponse = await sendingNode.endpoints[1].clusters['basic'].readAttributes( + ['modelId'], + { disableDefaultResponse: true }, + ); assert.equal(readAttributesResponse.modelId, 'test'); }); - it('should not respond with a default response when disableDefaultResponse is true', async function() { - receivingNode.endpoints[1].bind('basic', new class extends BoundCluster { - - get modelId() { - return 'test'; - } - - }()); + it('should not respond with a default response when disableDefaultResponse is true', async function () { + receivingNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'test'; + } + })(), + ); - const sendingNodeSendFrameSpy = sandbox.spy(sendingNode, 'sendFrame'); - const receivingNodeSendFrameSpy = sandbox.spy(receivingNode, 'sendFrame'); + const sendingNodeSendFrameSpy = mock.method(sendingNode, 'sendFrame'); + const receivingNodeSendFrameSpy = mock.method(receivingNode, 'sendFrame'); - await sendingNode.endpoints[1].clusters['basic'].readAttributes(['modelId'], { disableDefaultResponse: true }); + await sendingNode.endpoints[1].clusters['basic'].readAttributes(['modelId'], { + disableDefaultResponse: true, + }); // 1 frame sent by sending node, the read attributes command - assert.equal(sendingNodeSendFrameSpy.callCount, 1); + assert.equal(sendingNodeSendFrameSpy.mock.callCount(), 1); // 1 frame sent by receiving node, the read attributes response - assert.equal(receivingNodeSendFrameSpy.callCount, 1); + assert.equal(receivingNodeSendFrameSpy.mock.callCount(), 1); // Parse the received frame - const frame = Endpoint.parseFrame(receivingNodeSendFrameSpy.getCall(0).args[2]); + const frame = Endpoint.parseFrame(receivingNodeSendFrameSpy.mock.calls[0].arguments[2]); // 0x01 is read attributes response assert.equal(frame.cmdId, 1); }); - it('should not respond to a default response frame', async function() { - receivingNode.endpoints[1].bind('onOff', new class extends BoundCluster { - - toggle() { - debug('toggled'); - } - - }()); + it('should not respond to a default response frame', async function () { + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() { + debug('toggled'); + } + })(), + ); - const sendingNodeSendFrameSpy = sandbox.spy(sendingNode, 'sendFrame'); - const receivingNodeSendFrameSpy = sandbox.spy(receivingNode, 'sendFrame'); + const sendingNodeSendFrameSpy = mock.method(sendingNode, 'sendFrame'); + const receivingNodeSendFrameSpy = mock.method(receivingNode, 'sendFrame'); await sendingNode.endpoints[1].clusters['onOff'].toggle(); // 1 frame sent by sending node, the toggle command - assert.equal(sendingNodeSendFrameSpy.callCount, 1); + assert.equal(sendingNodeSendFrameSpy.mock.callCount(), 1); // 1 frame sent by receiving node, the toggle command default response - assert.equal(receivingNodeSendFrameSpy.callCount, 1); + assert.equal(receivingNodeSendFrameSpy.mock.callCount(), 1); // Parse the received frame - const frame = Endpoint.parseFrame(receivingNodeSendFrameSpy.getCall(0).args[2]); + const frame = Endpoint.parseFrame(receivingNodeSendFrameSpy.mock.calls[0].arguments[2]); // 0x01 is read attributes response assert.equal(frame.cmdId, 11); }); - it('should respond with default response error when frame could not be handled', async function() { - receivingNode.endpoints[1].bind('onOff', new class extends BoundCluster {}()); + it('should respond with default response error when frame could not be handled', async function () { + receivingNode.endpoints[1].bind('onOff', new (class extends BoundCluster {})()); - const sendingNodeHandleFrameSpy = sandbox.spy(sendingNode, 'handleFrame'); + const sendingNodeHandleFrameSpy = mock.method(sendingNode, 'handleFrame'); - // Execute toggle and expect a failure as the command is not implemented - await assert.rejects(sendingNode.endpoints[1].clusters['onOff'].toggle(), { message: 'FAILURE' }); + // Execute toggle and expect UNSUP_COMMAND as the command is not implemented (ZCL R8 2.5.12.2) + await assert.rejects(sendingNode.endpoints[1].clusters['onOff'].toggle(), { + message: 'UNSUP_CLUSTER_COMMAND', + }); // 1 frame received by sending node, the default response error - assert.equal(sendingNodeHandleFrameSpy.callCount, 1); + assert.equal(sendingNodeHandleFrameSpy.mock.callCount(), 1); // Parse the received frame - const frame = Endpoint.parseFrame(sendingNodeHandleFrameSpy.getCall(0).args[2]); - assert.equal(frame.cmdId, 0x0B); - assert.equal(frame.data[1], 0x01); // Error status + const frame = Endpoint.parseFrame(sendingNodeHandleFrameSpy.mock.calls[0].arguments[2]); + assert.equal(frame.cmdId, 0x0b); + assert.equal(frame.data[1], 0x81); // UNSUP_COMMAND }); - it('should not respond to a group cast frame', async function() { - const toggledSpy = sandbox.spy(); - receivingNode.endpoints[1].bind('onOff', new class extends BoundCluster { - - toggle() { - toggledSpy(); - } - - }()); + it('should not respond to a group cast frame', async function () { + const toggledSpy = mock.fn(); + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() { + toggledSpy(); + } + })(), + ); - const receivingNodeSendFrameSpy = sandbox.spy(receivingNode, 'sendFrame'); + const receivingNodeSendFrameSpy = mock.method(receivingNode, 'sendFrame'); // Send toggle command to onOff cluster with group id await receivingNode.handleFrame(1, 6, Buffer.from([0x01, 0x01, 0x02]), { groupId: 0x01 }); - assert.equal(toggledSpy.callCount, 1); + assert.equal(toggledSpy.mock.callCount(), 1); // 0 frames sent by receiving node, no response to group commands - assert.equal(receivingNodeSendFrameSpy.callCount, 0); + assert.equal(receivingNodeSendFrameSpy.mock.callCount(), 0); }); - it('should write attributes', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { + it('should not send a default response to a broadcast frame', async function () { + const toggledSpy = mock.fn(); + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() { + toggledSpy(); + } + })(), + ); - get modelId() { - return 'test'; - } + const receivingNodeSendFrameSpy = mock.method(receivingNode, 'sendFrame'); - get manufacturerName() { - return 'Athom'; - } + const meta = { broadcast: true, dstEndpoint: 1 }; + await receivingNode.handleFrame(1, 6, Buffer.from([0x01, 0x01, 0x02]), meta); + assert.equal(toggledSpy.mock.callCount(), 1); + assert.equal(receivingNodeSendFrameSpy.mock.callCount(), 0); + }); - set modelId(val) { - assert.equal(val, 'test1'); - } + it('should not send a default response error to a broadcast frame', async function () { + receivingNode.endpoints[1].bind('onOff', new (class extends BoundCluster {})()); - }()); + const receivingNodeSendFrameSpy = mock.method(receivingNode, 'sendFrame'); - await mockNode.endpoints[1].clusters['basic'].writeAttributes({ - modelId: 'test1', - }); + // toggle is not implemented, so this would otherwise get a default response error + await receivingNode.handleFrame(1, 6, Buffer.from([0x01, 0x01, 0x02]), { broadcast: true }); + assert.equal(receivingNodeSendFrameSpy.mock.callCount(), 0); }); - it('should discover attributes', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { + it('should send a default response to a unicast frame for the broadcast endpoint', async function () { + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() {} + })(), + ); - get modelId() { - return 'test'; - } + const receivingNodeSendFrameSpy = mock.method(receivingNode, 'sendFrame'); - get manufacturerName() { - return 'Athom'; - } + await receivingNode.handleFrame(1, 6, Buffer.from([0x01, 0x01, 0x02]), { dstEndpoint: 0xff }); + assert.equal(receivingNodeSendFrameSpy.mock.callCount(), 1); + }); - set modelId(val) { - assert.equal(val, 'test1'); - } + it('should write attributes', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'test'; + } + + get manufacturerName() { + return 'Athom'; + } + + set modelId(val) { + assert.equal(val, 'test1'); + } + })(), + ); + + await mockNode.endpoints[1].clusters['basic'].writeAttributes({ + modelId: 'test1', + }); + }); - }()); + it('should discover attributes', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + get modelId() { + return 'test'; + } + + get manufacturerName() { + return 'Athom'; + } + + set modelId(val) { + assert.equal(val, 'test1'); + } + })(), + ); const attrs = await mockNode.endpoints[1].clusters['basic'].discoverAttributes(); - ['modelId', 'manufacturerName'].forEach(a => { + ['modelId', 'manufacturerName'].forEach((a) => { assert(attrs.includes(a), `${a} is missing`); }); }); - it('should discover received commands', async function() { - mockNode.endpoints[1].bind('basic', new class extends BoundCluster { - - async factoryReset() { - debug('factory reset'); - } - - }()); + it('should discover received commands', async function () { + mockNode.endpoints[1].bind( + 'basic', + new (class extends BoundCluster { + async factoryReset() { + debug('factory reset'); + } + })(), + ); const cmds = await mockNode.endpoints[1].clusters['basic'].discoverCommandsReceived(); assert(cmds.includes('factoryReset')); }); - it('should support adding a Cluster with string attribute with 0x0000 ID', async function() { + it('should support adding a Cluster with string attribute with 0x0000 ID', async function () { class MyCluster extends Cluster { - static get ID() { return 0x1234; } @@ -381,7 +451,6 @@ describe('Node', function() { priceOption: { id: 0x0000, type: ZCLDataTypes.string }, }; } - } Cluster.addCluster(MyCluster); diff --git a/test/testTrxSequenceNumber.js b/test/testTrxSequenceNumber.js new file mode 100644 index 00000000..0fc29ca7 --- /dev/null +++ b/test/testTrxSequenceNumber.js @@ -0,0 +1,67 @@ +'use strict'; + +const { describe, it, beforeEach, afterEach, mock } = require('node:test'); +const assert = require('node:assert'); + +const Node = require('../lib/Node'); +const BoundCluster = require('../lib/BoundCluster'); +const BasicCluster = require('../lib/clusters/basic'); +const OnOffCluster = require('../lib/clusters/onOff'); + +describe('Transaction sequence number', function () { + let receivingNode; + let sendingNode; + let sentTrxSequenceNumbers; + + beforeEach(function () { + sentTrxSequenceNumbers = []; + sendingNode = new Node({ + sendFrame: (endpointId, clusterId, frame) => { + sentTrxSequenceNumbers.push(frame[1]); + receivingNode.handleFrame(endpointId, clusterId, frame); + }, + endpointDescriptors: [ + { endpointId: 1, inputClusters: [OnOffCluster.ID] }, + { endpointId: 2, inputClusters: [BasicCluster.ID] }, + ], + }); + + receivingNode = new Node({ + sendFrame: (...args) => { + sendingNode.handleFrame(...args); + }, + endpointDescriptors: [ + { endpointId: 1, inputClusters: [OnOffCluster.ID] }, + { endpointId: 2, inputClusters: [BasicCluster.ID] }, + ], + }); + receivingNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + toggle() {} + })(), + ); + }); + + afterEach(function () { + mock.restoreAll(); + }); + + it('should share one counter across endpoints and clusters', async function () { + await sendingNode.endpoints[1].clusters.onOff.toggle(); + const { basic } = sendingNode.endpoints[2].clusters; + await basic.factoryReset(undefined, { waitForResponse: false }); + await sendingNode.endpoints[1].clusters.onOff.toggle(); + + const [first] = sentTrxSequenceNumbers; + assert.deepStrictEqual(sentTrxSequenceNumbers, [first, (first + 1) % 256, (first + 2) % 256]); + }); + + it('should start at a random value and wrap around', function () { + mock.method(Math, 'random', () => 0.999); + const node = new Node({ sendFrame: () => {}, endpointDescriptors: [] }); + + assert.strictEqual(node.nextSeqNr(), 0); + assert.strictEqual(node.nextSeqNr(), 1); + }); +}); diff --git a/test/testZCLError.js b/test/testZCLError.js index c4a7b15d..42a36a13 100644 --- a/test/testZCLError.js +++ b/test/testZCLError.js @@ -1,11 +1,11 @@ -/* eslint-disable max-classes-per-file */ - 'use strict'; -const assert = require('assert'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); const BoundCluster = require('../lib/BoundCluster'); const Node = require('../lib/Node'); const OnOffCluster = require('../lib/clusters/onOff'); +const LevelControlCluster = require('../lib/clusters/levelControl'); const { ZCLStandardHeader } = require('../lib/zclFrames'); const { ZCLError } = require('../lib/util'); const { createMockNode } = require('./util'); @@ -38,171 +38,248 @@ function createSpyNodePair() { return { controllerNode, deviceNode, capturedFrames }; } -describe('ZCLError handling', function() { - it('should return ZCLError status code in Default Response when BoundCluster throws ZCLError', async function() { +function makeToClientFrame(cmdId) { + const header = new ZCLStandardHeader(); + header.frameControl.clusterSpecific = true; + header.frameControl.directionToClient = true; + header.trxSequenceNumber = 1; + header.cmdId = cmdId; + header.data = Buffer.alloc(0); + return header.toBuffer(); +} + +describe('ZCLError handling', function () { + it('should return ZCLError status code in Default Response when BoundCluster throws ZCLError', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - throw new ZCLError('NOT_AUTHORIZED'); - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + throw new ZCLError('NOT_AUTHORIZED'); + } + })(), + ); await assert.rejects( () => node.endpoints[1].clusters.onOff.setOn(), - err => { + (err) => { assert.strictEqual(err.message, 'NOT_AUTHORIZED'); return true; }, ); }); - it('should return FAILURE status in Default Response when BoundCluster throws a generic Error', async function() { + it('should return FAILURE status in Default Response when BoundCluster throws a generic Error', async function () { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - throw new Error('something went wrong'); - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + throw new Error('something went wrong'); + } + })(), + ); await assert.rejects( () => node.endpoints[1].clusters.onOff.setOn(), - err => { + (err) => { assert.strictEqual(err.message, 'FAILURE'); return true; }, ); }); - it('should encode ZCLError status code in Default Response frame bytes', async function() { + it('should encode ZCLError status code in Default Response frame bytes', async function () { // NOT_AUTHORIZED = 0x7e per ZCL spec const NOT_AUTHORIZED_STATUS_BYTE = 0x7e; const SET_ON_CMD_ID = OnOffCluster.COMMANDS.setOn.id; - const DEFAULT_RESPONSE_CMD_ID = 0x0B; + const DEFAULT_RESPONSE_CMD_ID = 0x0b; const { controllerNode, deviceNode, capturedFrames } = createSpyNodePair(); - deviceNode.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - throw new ZCLError('NOT_AUTHORIZED'); - } - - })()); + deviceNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + throw new ZCLError('NOT_AUTHORIZED'); + } + })(), + ); await assert.rejects(() => controllerNode.endpoints[1].clusters.onOff.setOn()); // capturedFrames only contains frames sent from the device back to the controller. // Find the Default Response frame among the captured device → controller frames. const defaultResponseFrame = capturedFrames - .map(f => ZCLStandardHeader.fromBuffer(f.data)) - .find(frame => frame.cmdId === DEFAULT_RESPONSE_CMD_ID); + .map((f) => ZCLStandardHeader.fromBuffer(f.data)) + .find((frame) => frame.cmdId === DEFAULT_RESPONSE_CMD_ID); assert.ok(defaultResponseFrame, 'Default Response frame was sent'); - assert.strictEqual(defaultResponseFrame.data[0], SET_ON_CMD_ID, - 'Default Response should reference the received setOn command ID'); - assert.strictEqual(defaultResponseFrame.data[1], NOT_AUTHORIZED_STATUS_BYTE, - 'Default Response should encode NOT_AUTHORIZED (0x7e) as the status byte'); + assert.strictEqual( + defaultResponseFrame.data[0], + SET_ON_CMD_ID, + 'Default Response should reference the received setOn command ID', + ); + assert.strictEqual( + defaultResponseFrame.data[1], + NOT_AUTHORIZED_STATUS_BYTE, + 'Default Response should encode NOT_AUTHORIZED (0x7e) as the status byte', + ); }); - it('should encode FAILURE (0x01) in Default Response frame bytes when a generic Error is thrown', async function() { + it('should encode FAILURE (0x01) in Default Response frame bytes when a generic Error is thrown', async function () { const FAILURE_STATUS_BYTE = 0x01; const SET_ON_CMD_ID = OnOffCluster.COMMANDS.setOn.id; - const DEFAULT_RESPONSE_CMD_ID = 0x0B; + const DEFAULT_RESPONSE_CMD_ID = 0x0b; const { controllerNode, deviceNode, capturedFrames } = createSpyNodePair(); - deviceNode.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - throw new Error('something went wrong'); - } - - })()); + deviceNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + throw new Error('something went wrong'); + } + })(), + ); await assert.rejects(() => controllerNode.endpoints[1].clusters.onOff.setOn()); const defaultResponseFrame = capturedFrames - .map(f => ZCLStandardHeader.fromBuffer(f.data)) - .find(frame => frame.cmdId === DEFAULT_RESPONSE_CMD_ID); + .map((f) => ZCLStandardHeader.fromBuffer(f.data)) + .find((frame) => frame.cmdId === DEFAULT_RESPONSE_CMD_ID); assert.ok(defaultResponseFrame, 'Default Response frame was sent'); - assert.strictEqual(defaultResponseFrame.data[0], SET_ON_CMD_ID, - 'Default Response should reference the received setOn command ID'); - assert.strictEqual(defaultResponseFrame.data[1], FAILURE_STATUS_BYTE, - 'Default Response should encode FAILURE (0x01) as the status byte'); + assert.strictEqual( + defaultResponseFrame.data[0], + SET_ON_CMD_ID, + 'Default Response should reference the received setOn command ID', + ); + assert.strictEqual( + defaultResponseFrame.data[1], + FAILURE_STATUS_BYTE, + 'Default Response should encode FAILURE (0x01) as the status byte', + ); }); - it('should send SUCCESS status byte when ZCLError("SUCCESS") is thrown', async function() { + it('should send SUCCESS status byte when ZCLError("SUCCESS") is thrown', async function () { const SUCCESS_STATUS_BYTE = 0x00; const SET_ON_CMD_ID = OnOffCluster.COMMANDS.setOn.id; - const DEFAULT_RESPONSE_CMD_ID = 0x0B; + const DEFAULT_RESPONSE_CMD_ID = 0x0b; const { controllerNode, deviceNode, capturedFrames } = createSpyNodePair(); - deviceNode.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - throw new ZCLError('SUCCESS'); - } - - })()); + deviceNode.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + throw new ZCLError('SUCCESS'); + } + })(), + ); // The controller should not reject — a SUCCESS default response resolves the command await controllerNode.endpoints[1].clusters.onOff.setOn(); const defaultResponseFrame = capturedFrames - .map(f => ZCLStandardHeader.fromBuffer(f.data)) - .find(frame => frame.cmdId === DEFAULT_RESPONSE_CMD_ID); + .map((f) => ZCLStandardHeader.fromBuffer(f.data)) + .find((frame) => frame.cmdId === DEFAULT_RESPONSE_CMD_ID); assert.ok(defaultResponseFrame, 'Default Response frame was sent'); - assert.strictEqual(defaultResponseFrame.data[0], SET_ON_CMD_ID, - 'Default Response should reference the received setOn command ID'); - assert.strictEqual(defaultResponseFrame.data[1], SUCCESS_STATUS_BYTE, - 'Default Response should encode SUCCESS (0x00) as the status byte'); + assert.strictEqual( + defaultResponseFrame.data[0], + SET_ON_CMD_ID, + 'Default Response should reference the received setOn command ID', + ); + assert.strictEqual( + defaultResponseFrame.data[1], + SUCCESS_STATUS_BYTE, + 'Default Response should encode SUCCESS (0x00) as the status byte', + ); + }); + + // ZCL R8 2.5.12.2 + it('should send UNSUP_COMMAND (0x81) for a command the BoundCluster does not implement', async function () { + const { controllerNode, deviceNode, capturedFrames } = createSpyNodePair(); + deviceNode.endpoints[1].bind('onOff', new BoundCluster()); + + await assert.rejects(() => controllerNode.endpoints[1].clusters.onOff.setOn(), { + message: 'UNSUP_CLUSTER_COMMAND', + }); + + const defaultResponseFrame = ZCLStandardHeader.fromBuffer(capturedFrames[0].data); + assert.strictEqual(defaultResponseFrame.cmdId, 0x0b); + assert.strictEqual(defaultResponseFrame.data[1], 0x81); }); - it('should propagate different ZCLError status codes', async function() { + it('should send UNSUP_COMMAND (0x81) for an unknown command id on a client cluster', async function () { + const { deviceNode, capturedFrames } = createSpyNodePair(); + await deviceNode.handleFrame(1, OnOffCluster.ID, makeToClientFrame(0x7f), {}); + assert.strictEqual(ZCLStandardHeader.fromBuffer(capturedFrames[0].data).data[1], 0x81); + }); + + it('should send UNSUPPORTED_CLUSTER (0xc3) for a server-to-client frame on a cluster the endpoint lacks', async function () { + const { deviceNode, capturedFrames } = createSpyNodePair(); + await deviceNode.handleFrame(1, LevelControlCluster.ID, makeToClientFrame(0x00), {}); + assert.strictEqual(ZCLStandardHeader.fromBuffer(capturedFrames[0].data).data[1], 0xc3); + }); + + it('should send UNSUPPORTED_CLUSTER (0xc3) when the endpoint has no binding for the cluster', async function () { + const { controllerNode, capturedFrames } = createSpyNodePair(); + + await assert.rejects(() => controllerNode.endpoints[1].clusters.onOff.setOn(), { + message: 'UNSUPPORTED_CLUSTER', + }); + + const defaultResponseFrame = ZCLStandardHeader.fromBuffer(capturedFrames[0].data); + assert.strictEqual(defaultResponseFrame.cmdId, 0x0b); + assert.strictEqual(defaultResponseFrame.data[1], 0xc3); + }); + + it('should propagate different ZCLError status codes', async function () { const statuses = ['NOT_AUTHORIZED', 'INVALID_VALUE', 'INSUFFICIENT_SPACE']; for (const status of statuses) { const node = createMockNode({ loopback: true, - endpoints: [{ - endpointId: 1, - inputClusters: [OnOffCluster.ID], - }], + endpoints: [ + { + endpointId: 1, + inputClusters: [OnOffCluster.ID], + }, + ], }); - node.endpoints[1].bind('onOff', new (class extends BoundCluster { - - async setOn() { - throw new ZCLError(status); - } - - })()); + node.endpoints[1].bind( + 'onOff', + new (class extends BoundCluster { + async setOn() { + throw new ZCLError(status); + } + })(), + ); - // eslint-disable-next-line no-await-in-loop await assert.rejects( () => node.endpoints[1].clusters.onOff.setOn(), - err => { + (err) => { assert.strictEqual(err.message, status); return true; }, diff --git a/test/util/mockNode.js b/test/util/mockNode.js index a303794e..59e5f47c 100644 --- a/test/util/mockNode.js +++ b/test/util/mockNode.js @@ -21,17 +21,15 @@ const ElectricalMeasurementCluster = require('../../lib/clusters/electricalMeasu */ function createBoundClusterWithAttributes(attributes) { const ClusterClass = class extends BoundCluster { - constructor() { super(); // Store mutable attributes this._attributes = { ...attributes }; } - }; // Define getters/setters for each attribute - Object.keys(attributes).forEach(attrName => { + Object.keys(attributes).forEach((attrName) => { Object.defineProperty(ClusterClass.prototype, attrName, { get() { return this._attributes[attrName]; @@ -78,7 +76,7 @@ function createBoundClusterWithAttributes(attributes) { * @returns {Node} Configured mock Node */ function createMockNode(config) { - const endpointDescriptors = config.endpoints.map(ep => ({ + const endpointDescriptors = config.endpoints.map((ep) => ({ endpointId: ep.endpointId, inputClusters: ep.inputClusters || [], outputClusters: ep.outputClusters || [], @@ -87,16 +85,14 @@ function createMockNode(config) { // Create node reference first so sendFrame can reference it let node; const mockNode = { - sendFrame: config.loopback - ? (...args) => node.handleFrame(...args) - : () => Promise.resolve(), + sendFrame: config.loopback ? (...args) => node.handleFrame(...args) : () => Promise.resolve(), endpointDescriptors, }; node = new Node(mockNode); // Bind clusters with preset attribute values - config.endpoints.forEach(ep => { + config.endpoints.forEach((ep) => { if (!ep.clusters) return; Object.entries(ep.clusters).forEach(([clusterName, attributes]) => { @@ -116,13 +112,13 @@ function createMockNode(config) { * @returns {[Node, Node]} Tuple of connected nodes */ function createConnectedNodePair(config1, config2) { - const endpointDescriptors1 = config1.endpoints.map(ep => ({ + const endpointDescriptors1 = config1.endpoints.map((ep) => ({ endpointId: ep.endpointId, inputClusters: ep.inputClusters || [], outputClusters: ep.outputClusters || [], })); - const endpointDescriptors2 = config2.endpoints.map(ep => ({ + const endpointDescriptors2 = config2.endpoints.map((ep) => ({ endpointId: ep.endpointId, inputClusters: ep.inputClusters || [], outputClusters: ep.outputClusters || [], @@ -145,7 +141,7 @@ function createConnectedNodePair(config1, config2) { node2 = new Node(mockNode2); // Bind clusters for node1 - config1.endpoints.forEach(ep => { + config1.endpoints.forEach((ep) => { if (!ep.clusters) return; Object.entries(ep.clusters).forEach(([clusterName, attributes]) => { const boundCluster = createBoundClusterWithAttributes(attributes); @@ -154,7 +150,7 @@ function createConnectedNodePair(config1, config2) { }); // Bind clusters for node2 - config2.endpoints.forEach(ep => { + config2.endpoints.forEach((ep) => { if (!ep.clusters) return; Object.entries(ep.clusters).forEach(([clusterName, attributes]) => { const boundCluster = createBoundClusterWithAttributes(attributes); @@ -172,140 +168,152 @@ const MOCK_DEVICES = { /** * IAS Zone Motion Sensor */ - motionSensor: (overrides = {}) => createMockNode({ - endpoints: [{ - endpointId: 1, - inputClusters: [BasicCluster.ID, PowerConfigurationCluster.ID, IASZoneCluster.ID], - clusters: { - basic: { - zclVersion: 3, - manufacturerName: 'MockDevice', - modelId: 'MockMotionSensor', - ...overrides.basic, - }, - powerConfiguration: { - batteryPercentageRemaining: 200, // 100% - ...overrides.powerConfiguration, + motionSensor: (overrides = {}) => + createMockNode({ + endpoints: [ + { + endpointId: 1, + inputClusters: [BasicCluster.ID, PowerConfigurationCluster.ID, IASZoneCluster.ID], + clusters: { + basic: { + zclVersion: 3, + manufacturerName: 'MockDevice', + modelId: 'MockMotionSensor', + ...overrides.basic, + }, + powerConfiguration: { + batteryPercentageRemaining: 200, // 100% + ...overrides.powerConfiguration, + }, + iasZone: { + zoneState: 1, // Enrolled + zoneType: 0x000d, // Motion sensor + zoneStatus: 0, + iasCIEAddress: '0x0000000000000000', + zoneId: 1, + ...overrides.iasZone, + }, + }, }, - iasZone: { - zoneState: 1, // Enrolled - zoneType: 0x000D, // Motion sensor - zoneStatus: 0, - iasCIEAddress: '0x0000000000000000', - zoneId: 1, - ...overrides.iasZone, - }, - }, - }], - }), + ], + }), /** * IAS Zone Contact Sensor (door/window) */ - contactSensor: (overrides = {}) => createMockNode({ - endpoints: [{ - endpointId: 1, - inputClusters: [BasicCluster.ID, PowerConfigurationCluster.ID, IASZoneCluster.ID], - clusters: { - basic: { - zclVersion: 3, - manufacturerName: 'MockDevice', - modelId: 'MockContactSensor', - ...overrides.basic, + contactSensor: (overrides = {}) => + createMockNode({ + endpoints: [ + { + endpointId: 1, + inputClusters: [BasicCluster.ID, PowerConfigurationCluster.ID, IASZoneCluster.ID], + clusters: { + basic: { + zclVersion: 3, + manufacturerName: 'MockDevice', + modelId: 'MockContactSensor', + ...overrides.basic, + }, + powerConfiguration: { + batteryPercentageRemaining: 200, + ...overrides.powerConfiguration, + }, + iasZone: { + zoneState: 1, + zoneType: 0x0015, // Contact switch + zoneStatus: 0, + iasCIEAddress: '0x0000000000000000', + zoneId: 1, + ...overrides.iasZone, + }, + }, }, - powerConfiguration: { - batteryPercentageRemaining: 200, - ...overrides.powerConfiguration, - }, - iasZone: { - zoneState: 1, - zoneType: 0x0015, // Contact switch - zoneStatus: 0, - iasCIEAddress: '0x0000000000000000', - zoneId: 1, - ...overrides.iasZone, - }, - }, - }], - }), + ], + }), /** * Temperature + Humidity Sensor */ - tempHumiditySensor: (overrides = {}) => createMockNode({ - endpoints: [{ - endpointId: 1, - inputClusters: [ - BasicCluster.ID, - PowerConfigurationCluster.ID, - TemperatureMeasurementCluster.ID, - RelativeHumidityCluster.ID, - ], - clusters: { - basic: { - zclVersion: 3, - manufacturerName: 'MockDevice', - modelId: 'MockTempHumidity', - ...overrides.basic, + tempHumiditySensor: (overrides = {}) => + createMockNode({ + endpoints: [ + { + endpointId: 1, + inputClusters: [ + BasicCluster.ID, + PowerConfigurationCluster.ID, + TemperatureMeasurementCluster.ID, + RelativeHumidityCluster.ID, + ], + clusters: { + basic: { + zclVersion: 3, + manufacturerName: 'MockDevice', + modelId: 'MockTempHumidity', + ...overrides.basic, + }, + powerConfiguration: { + batteryPercentageRemaining: 200, + ...overrides.powerConfiguration, + }, + temperatureMeasurement: { + measuredValue: 2150, // 21.50°C + minMeasuredValue: -4000, + maxMeasuredValue: 8500, + ...overrides.temperatureMeasurement, + }, + relativeHumidity: { + measuredValue: 6500, // 65.00% + minMeasuredValue: 0, + maxMeasuredValue: 10000, + ...overrides.relativeHumidity, + }, + }, }, - powerConfiguration: { - batteryPercentageRemaining: 200, - ...overrides.powerConfiguration, - }, - temperatureMeasurement: { - measuredValue: 2150, // 21.50°C - minMeasuredValue: -4000, - maxMeasuredValue: 8500, - ...overrides.temperatureMeasurement, - }, - relativeHumidity: { - measuredValue: 6500, // 65.00% - minMeasuredValue: 0, - maxMeasuredValue: 10000, - ...overrides.relativeHumidity, - }, - }, - }], - }), + ], + }), /** * Smart Plug with Power Metering */ - smartPlug: (overrides = {}) => createMockNode({ - endpoints: [{ - endpointId: 1, - inputClusters: [ - BasicCluster.ID, - OnOffCluster.ID, - MeteringCluster.ID, - ElectricalMeasurementCluster.ID, - ], - clusters: { - basic: { - zclVersion: 3, - manufacturerName: 'MockDevice', - modelId: 'MockSmartPlug', - ...overrides.basic, + smartPlug: (overrides = {}) => + createMockNode({ + endpoints: [ + { + endpointId: 1, + inputClusters: [ + BasicCluster.ID, + OnOffCluster.ID, + MeteringCluster.ID, + ElectricalMeasurementCluster.ID, + ], + clusters: { + basic: { + zclVersion: 3, + manufacturerName: 'MockDevice', + modelId: 'MockSmartPlug', + ...overrides.basic, + }, + onOff: { + onOff: false, + ...overrides.onOff, + }, + metering: { + currentSummationDelivered: 12345678, + multiplier: 1, + divisor: 1000, + ...overrides.metering, + }, + electricalMeasurement: { + activePower: 1500, // 150.0W + rmsVoltage: 2300, // 230.0V + rmsCurrent: 652, // 0.652A + ...overrides.electricalMeasurement, + }, + }, }, - onOff: { - onOff: false, - ...overrides.onOff, - }, - metering: { - currentSummationDelivered: 12345678, - multiplier: 1, - divisor: 1000, - ...overrides.metering, - }, - electricalMeasurement: { - activePower: 1500, // 150.0W - rmsVoltage: 2300, // 230.0V - rmsCurrent: 652, // 0.652A - ...overrides.electricalMeasurement, - }, - }, - }], - }), + ], + }), }; module.exports = { diff --git a/tsconfig.json b/tsconfig.json index 82403b49..a7c74bd0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,6 @@ "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "declaration": false, - "skipLibCheck": false, + "skipLibCheck": false } }