diff --git a/.commitlintrc.json b/.commitlintrc.json new file mode 100644 index 000000000..477b0d1f9 --- /dev/null +++ b/.commitlintrc.json @@ -0,0 +1,30 @@ +{ + "extends": [ + "@commitlint/config-conventional" + ], + "rules": { + "type-enum": [ + 2, + "always", + [ + "build", + "ci", + "deps", + "docs", + "feat", + "fix", + "perf", + "refactor", + "release", + "revert", + "style", + "test" + ] + ], + "body-max-line-length": [2, "always", 160], + "subject-case": [ + 2, "always", + ["sentence-case", "start-case", "pascal-case"] + ] + } +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..b432804f7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# see http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = tab + +[*.{css,html,js,cjs,mjs,jsx,ts,tsx,less,txt,json,yml,md}] +trim_trailing_whitespace = true +end_of_line = lf +indent_size = 4 +insert_final_newline = true + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..04dbec591 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,12 @@ +# /node_modules/* and /bower_components/* ignored by default + +# Exclude coverage folder +coverage/ + +# Exclude test files +test/tmp/ +test/projects/ +test/fixtures/ + +# Exclude generated code +/lib/ diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 000000000..e8269a6d4 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,54 @@ +/* eslint-env node */ +module.exports = { + env: { + node: true, + es2022: true + }, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:ava/recommended"], + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint", "ava"], + rules: { + "indent": [ + "error", + "tab" + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double", + {"allowTemplateLiterals": true} + ], + "semi": [ + "error", + "always" + ], + "max-len": [ + "error", + { + "code": 120, + "ignoreUrls": true, + "ignoreRegExpLiterals": true + } + ], + "no-implicit-coercion": [ + 2, + {"allow": ["!!"]} + ], + "no-console": "error", + // ava/assertion-arguments reports concatenated strings in a assertion message as an issue + // See: https://github.com/avajs/eslint-plugin-ava/issues/332 + "ava/assertion-arguments": 0, + "no-unused-vars": "off", // Turn off default rule to customize typescript variant + "@typescript-eslint/no-unused-vars": [ + "error", { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ] + }, + root: true, +}; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..6313b56c5 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 000000000..20bdd6fc0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,54 @@ +--- +name: Bug Report +about: Report an issue with a package part of UI5 linter +title: '' +labels: bug, needs triage +assignees: '' + +--- + + + +## Expected Behavior + +{...} + +## Current Behavior + +{...} + +## Steps to Reproduce the Issue + + +1. {...} +2. {...} +3. {...} + +## Context + +- UI5 linter package and version +- Node.js Version: **`unknown`** +- npm Version: `unknown` +- OS/Platform: `unknown` +- Browser *(if relevant)*: `unknown` +- Other information regarding your environment *(optional)*: `nothing` + +## Log Output / Stack Trace + + + +``` +{...} +``` diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..0086358db --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: true diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 000000000..8e329cfe4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,29 @@ +--- +name: Feature Request +about: Request a new feature to be added to a package part of UI5 linter +title: '' +labels: enhancement +assignees: '' + +--- + + + +## Is your feature request related to a problem? Please describe. + +A clear and concise description of the problem, e.g. "I'm always frustrated when {...}" + +## Describe the solution you'd like + +A clear and concise description of what you want to happen. + +## Describe alternatives you've considered + +A clear and concise description of any alternative solutions or features you've considered. + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..986162f98 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +**Thank you for your contribution!** 🙌 + +To get it merged faster, kindly review the checklist below: + +## Pull Request Checklist +- [ ] Reviewed the [Contributing Guidelines](https://github.com/SAP/ui5-linter/blob/main/CONTRIBUTING.md#-contributing-code) + + Especially the [How to Contribute](https://github.com/SAP/ui5-linter/blob/main/CONTRIBUTING.md#how-to-contribute) section +- [ ] [No merge commits](https://github.com/SAP/ui5-linter/blob/main/docs/Guidelines.md#no-merge-commits) +- [ ] [Correct commit message style](https://github.com/SAP/ui5-linter/blob/main/docs/Guidelines.md#commit-message-style) diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..8773de2cd --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "ci(github-actions)" +- package-ecosystem: npm + directory: "/" + schedule: + interval: weekly + day: sunday + time: "10:00" + timezone: Etc/UCT + reviewers: + - "SAP/ui5-foundation" + versioning-strategy: increase + commit-message: + prefix: "deps" + prefix-development: "build(deps-dev)" diff --git a/.github/in-solidarity.yml b/.github/in-solidarity.yml new file mode 100644 index 000000000..4ce829a6b --- /dev/null +++ b/.github/in-solidarity.yml @@ -0,0 +1 @@ +_extends: ietf/terminology diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..cf1c037a3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: CI +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test: + name: General checks, tests and coverage reporting + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 21.4.0 + uses: actions/setup-node@v4.0.2 + with: + node-version: 21.4.0 + + - name: Install dependencies + run: npm ci + + - name: Perfrom Licenses check + run: npm run check-licenses + + - name: Perform dependency check + run: npm run depcheck + + - name: Perform checks and tests + run: npm test + env: + NODE_OPTIONS: "" diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 000000000..7641ccb6c --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,18 @@ +name: Commit Message Linting + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: wagoid/commitlint-github-action@v5 diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 000000000..0dffcefeb --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,26 @@ +name: Dependabot auto-merge +on: + pull_request: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Enable auto-merge for Dependabot PRs + if: ${{contains(fromJSON('["version-update:semver-minor", "version-update:semver-patch"]'), steps.metadata.outputs.update-type)}} + run: gh pr review --approve "$PR_URL" && gh pr merge --auto --rebase "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 000000000..572757d37 --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,18 @@ +name: Issue/Pull Request Handling +on: + schedule: + - cron: '00 20 * * *' + +jobs: + stale: + name: Flag and close stale issues + runs-on: ubuntu-22.04 + steps: + - uses: actions/stale@v9 + with: + stale-issue-message: 'This issue has been automatically marked as stale because it has been open for 60 days with no activity. It will be closed in 10 days if no further activity occurs.' + stale-issue-label: 'stale' + stale-pr-label: 'stale' + days-before-stale: 60 + days-before-close: 10 + only-labels: 'information required' diff --git a/.github/workflows/reuse-compliance.yml b/.github/workflows/reuse-compliance.yml new file mode 100644 index 000000000..f09064c3f --- /dev/null +++ b/.github/workflows/reuse-compliance.yml @@ -0,0 +1,18 @@ +name: REUSE + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + compliance-check: + name: Compliance Check + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Execute REUSE Compliance Check + uses: fsfe/reuse-action@v3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..eb7dcdd93 --- /dev/null +++ b/.gitignore @@ -0,0 +1,111 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# build / generate output +dist + +# Gatsby files +.cache/ + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +.DS_Store + +# IDEs +.vscode/ +*.~vsdx +.idea/ +*.sublime-workspace + +# Generated code +/lib/ + +# Temporary files +/tmp/ \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 000000000..90289817c --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1 @@ +npm run hooks:pre-push diff --git a/.husky/skip.js b/.husky/skip.js new file mode 100755 index 000000000..f67431759 --- /dev/null +++ b/.husky/skip.js @@ -0,0 +1,5 @@ +if (process.env.CI) { + process.exit(0); +} else { + process.exit(1); +} diff --git a/.licensee.json b/.licensee.json new file mode 100644 index 000000000..7e9810438 --- /dev/null +++ b/.licensee.json @@ -0,0 +1,17 @@ +{ + "licenses": { + "spdx": [ + "CC-BY-3.0", + "CC-BY-4.0", + "BSD" + ], + "blueOak": "bronze" + }, + "packages": { + "@sapui5/types": "^1.120.4", + "callsite": "1.0.0", + "yesno": "0.4.0", + "deep-freeze-strict": "1.1.1" + }, + "corrections": true +} diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..a8ad72ed4 --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +# Enforce public npm registry +registry=https://registry.npmjs.org/ +lockfile-version=3 \ No newline at end of file diff --git a/.nycrc b/.nycrc new file mode 100644 index 000000000..6f6c37453 --- /dev/null +++ b/.nycrc @@ -0,0 +1,18 @@ +{ + "extends": "@istanbuljs/nyc-config-typescript", + "reporter": ["lcov", "text", "text-summary"], + "include": ["src/**"], + "check-coverage": true, + "statements": 80, + "branches": 75, + "functions": 75, + "lines": 80, + "watermarks": { + "statements": [70, 90], + "branches": [70, 90], + "functions": [70, 90], + "lines": [70, 90] + }, + "cache": true, + "all": true +} diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 000000000..0680e6196 --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,29 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: ui5-linter +Upstream-Contact: SAP OpenUI5 +Source: https://github.com/SAP/ui5-linter +Disclaimer: The code in this project may include calls to APIs (“API Calls”) of + SAP or third-party products or services developed outside of this project + (“External Products”). + “APIs” means application programming interfaces, as well as their respective + specifications and implementing code that allows software to communicate with + other software. + API Calls to External Products are not licensed under the open source license + that governs this project. The use of such API Calls and related External + Products are subject to applicable additional agreements with the relevant + provider of the External Products. In no event shall the open source license + that governs this project grant any rights in or to any External Products,or + alter, expand or supersede any terms of the applicable additional agreements. + If you have a valid license agreement with SAP for the use of a particular SAP + External Product, then you may make use of any API Calls included in this + project’s code for that SAP External Product, subject to the terms of such + license agreement. If you do not have a valid license agreement for the use of + a particular SAP External Product, then you may only make use of any API Calls + in this project for that SAP External Product for your internal, non-productive + and non-commercial test and evaluation of such API Calls. Nothing herein grants + you any rights to use or access any SAP External Product, or provide any third + parties the right to use of access any SAP External Product, through API Calls. + +Files: * +Copyright: 2024 SAP SE or an SAP affiliate company and UI5 linter contributors +License: Apache-2.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..07e0a2ead --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,123 @@ +# Contributing to UI5 linter + +## Content + +1. [📝 **Reporting Issues**](#-reporting-issues) +2. [🤩 **Feature Requests**](#-feature-requests) +3. [🔍 **Analyzing Issues**](#-analyzing-issues) +4. [💻 **Contributing Code**](#-contributing-code) + +### ⚡️ Quick Links for Maintainers + +- [All Open Pull Requests](https://github.com/SAP/ui5-linter/pulls) +- [All Open Issues](https://github.com/SAP/ui5-linter/issues) + +## 📝 Reporting Issues + +### Seeking Help / Not a Bug + + +### How to Report an Issue + +1. **Only UI5 linter issues** + * Please do not report: + * Issues caused by dependencies. + * Issues caused by the use of non-public/internal methods. Only the public methods listed in the API documentation may be used. + * Something you do not get to work properly, see [Not a Bug / Questions](#not-a-bug--questions). +2. **No duplicate**: You have searched the [issue tracker](https://github.com/SAP/ui5-linter/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) to make sure the bug has not already been reported. +3. **Good summary**: The summary should be specific to the issue. +4. **Current bug**: The bug can be reproduced in the most current version of the relevant module(s). +5. **Reproducible bug**: There are step-by-step instructions provided on how to reproduce the issue. +6. **Well-documented**: + * Precisely state the expected and the actual behavior. + * Give information about the environment in which the issue occurs (OS/Platform, Node.js version, etc.). + * Generally, give as much additional information as possible. +7. **Only one bug per report**: Open additional tickets for additional issues. +8. **Please report bugs in English.** + +We encourage you to follow the issue template that will be presented to you when creating a new issue. + +When you are ready, report your issue here: https://github.com/SAP/ui5-linter/issues/new + +### Reporting Security Issues + +If you find any bug that may be a security problem, please follow our instructions at [in our security policy](https://github.com/SAP/ui5-linter/security/policy) on how to report it. Please do not create GitHub issues for security-related doubts or problems. + +### Use of Labels + +GitHub offers labels to categorize issues. The labels can only be set and modified by committers. + +#### General issue categories: + +- **`bug`**: This issue is a bug in the code. +- **`documentation`**: This issue is about wrong documentation. +- **`enhancement`**: This is not a bug report, but an enhancement request. +- **`needs triage`**: This issue needs to be investigated and confirmed as a valid issue that is not a duplicate + +##### Status of an open issue: + +- **`information required`**: The author is required to provide information. +- **`good first issue`**: A newcomer may work on this. +- **`help wanted`**: Additional help in analyzing this issue is required. + +##### Status/resolution of a closed issue: + +- **`duplicate`**: The issue was already reported somewhere else. +- **`invalid`**: For any reason, this issue report will not be handled further. Possible reasons are lack of information, or that the issue does not apply anymore. +- **`wontfix`**: While acknowledged to be an issue, a fix cannot or will not be provided. + +### Issue Reporting Disclaimer + +We want to improve the quality of the UI5 linter and good bug reports are welcome! But our capacity is limited, so we cannot handle questions or consultation requests, and we cannot afford to ask for required details. + +Therefore, we reserve the right to close or to not process insufficient bug reports in favor of those which are clearly documented and easy to reproduce. Even though we would like to solve each well-documented issue, there is always the chance that it won't happen - please remember: The UI5 linter is Open Source and comes without warranty. + +Bug report analysis support is always very welcome! See [Analyze Issues](#-analyzing-issues). + +## 🤩 Feature Requests + +You can request most features by creating an issue in the UI5 linter repository: https://github.com/SAP/ui5-linter/issues/new + +For bigger features an RFC (Request for Comment) might be necessary. You should always clarify the need for an RFC with the project contributors upfront. You could do this either by opening an issue or in our [Slack channel](#seeking-help--not-a-bug). You can use [this template](rfcs/0000-template.md) for creating an RFC. + +## 🔍 Analyzing Issues + +Analyzing issue reports can be a lot of effort. Any help is welcome! 👍 + +Open the [Bug Triage Project Board](https://github.com/orgs/SAP/projects/XX) and look for open issues which require triage, additional work, or a bugfix. +Especially check for issues in the **`Needs Triage`** column, or for issues with the labels **`good first issue`**, **`help wanted`**, or **`information required`**. + +You may be able to add additional or missing information, such as a step-by-step guide on how to reproduce an issue or an analysis of the root cause. In case of the latter, you might even be able to [contribute](#-contributing-code) a bugfix. 🙌 + +## 💻 Contributing Code + +### General Remarks + +You are welcome to contribute code to UI5 linter in order to fix bugs or to implement new features. + +There are three important things to know: + +1. You must be aware of the Apache License (which describes contributions) and **agree to the Developer Certificate of Origin***. This is common practice in major Open Source projects. To make this process as simple as possible, we are using *[CLA assistant](https://cla-assistant.io/)* for individual contributions. CLA assistant is an open source tool that integrates with GitHub very well and enables a one-click experience for accepting the DCO. For company contributers, special rules apply. See the respective section below for details. +2. Follow our **[Development Conventions and Guidelines](docs/Guidelines.md)**. +3. **Not all proposed contributions can be accepted**. Some features may just fit a third-party add-on better. The code must match the overall direction of the UI5 linter and improve it. So there should be some "bang for the byte". For most bug fixes this is a given, but a major feature implementation first needs to be discussed with one of the committers. Possibly, one who touched the related code or module recently. The more effort you invest, the better you should clarify in advance whether the contribution will match the project's direction. The best way would be to just open an enhancement ticket in the issue tracker to discuss the feature you plan to implement (make it clear that you intend to contribute). We will then forward the proposal to the respective code owner. This avoids disappointment. + +### Developer Certificate of Origin (DCO) + +Due to legal reasons, contributors will be asked to accept a DCO before they submit the first pull request to this project. SAP uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/). +This happens in an automated fashion during the submission process: the CLA assistant tool will add a comment to the pull request. Click it to check the DCO, then accept it on the following screen. CLA assistant will save this decision for upcoming contributions. + +This DCO replaces the previously used CLA ("Contributor License Agreement") as well as the "Corporate Contributor License Agreement" with new terms which are well-known standards and hence easier to approve by legal departments. Contributors who had already accepted the CLA in the past may be asked once to accept the new DCO. + +### How to Contribute + +1. Make sure the change is welcome (see [General Remarks](#general-remarks)). + - Also check on the [UI5 linter Task Board](https://github.com/orgs/SAP/projects/XX) whether related tasks are already being worked on, blocked, or in discussion. +1. Create a branch by forking the relevant module repository and apply your change. +1. Commit and push your change on that branch. + - 👉 **Please follow our [Development Conventions and Guidelines](docs/Guidelines.md).** +1. Create a pull request in the relevant repository. +1. Follow the link posted by the CLA assistant to your pull request and accept it, as described above. +1. Wait for our code review and approval, possibly enhancing your change on request. + - Note that the UI5 developers have many duties. So, depending on the required effort for reviewing, testing, and clarification, this may take a while. +1. Once the change has been approved and merged, we will inform you in a comment. +1. Celebrate! 🎉 diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 000000000..137069b82 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 000000000..d36114e7d --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +![UI5 logo](./docs/images/UI5_logo_wide.png) + +# UI5 linter + +> A static code analysis tool for UI5 + + + +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md) + + + +## Description + +UI5 linter is a static code analysis tool for UI5 projects. +It checks JavaScript, XML, JSON, and other files in your project and reports findings. + +Currently, it identifies deprecated API usage, global variables, and more to prepare your project for [UI5 2.0](https://community.sap.com/t5/open-source-blogs/introducing-openui5-2-x/ba-p/13580633). + +## Requirements + +- [Node.js](https://nodejs.org/) Version v20.11.0, v21.2.0 or higher +- [npm](https://www.npmjs.com/) Version v10.0.0 or higher + +## Installation + +Install the CLI using the npm package manager: + +```sh +# Global +npm install --global @ui5/linter + +# In your project +npm install --save-dev @ui5/linter +``` + +## Usage + +Run the `ui5lint` command in your project root folder + +```sh +ui5lint + +## UI5Lint Report ## + +webapp/controller/App.controller.js + ui5-linter-no-deprecated-api (1) + 10:4 error Call to deprecated function 'attachTap' of class 'Button' + +webapp/manifest.json + ui5-linter-no-deprecated-api (1) + 81:17 error Use of deprecated model type 'sap.ui5/models/odata/type="sap.ui.model.odata.ODataModel"' + +webapp/test/unit/unitTests.qunit.js + ui5-linter-no-deprecated-api (2) + 6:1 error Call to deprecated function 'attachInit' of class 'Core' + 6:1 error Call to deprecated function 'getCore' (sap.ui.getCore) + ui5-linter-no-globals-js (1) + 6:1 error Access of global variable 'sap' (sap.ui.getCore) + +webapp/view/Main.view.xml + ui5-linter-no-deprecated-api (2) + 16:39 error Import of deprecated module 'sap/m/MessagePage' + 22:5 error Use of deprecated property 'blocked' of class 'Button' + +7 problems (7 errors, 0 warnings) + +Note: Use "ui5lint --details" to show more information about the findings +``` + +### Options + +#### `--details` + +Show more information about the findings and how to fix them. + +**Example:** +```sh +ui5lint --details +``` + +#### `--format` + +Choose the output format. Currently, `stylish` (default) and `json` are supported. + +**Example:** +```sh +ui5lint --format json +``` + +## Support, Feedback, Contributing + +This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/SAP/ui5-linter/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md). + +You can also chat with us in the [`#tooling`](https://openui5.slack.com/archives/C0A7QFN6B) channel of the [OpenUI5 Community Slack](https://ui5-slack-invite.cfapps.eu10.hana.ondemand.com/). For public Q&A, use the [`ui5-tooling` tag on Stack Overflow](https://stackoverflow.com/questions/tagged/ui5-tooling). + +## Security / Disclosure +If you find any bug that may be a security problem, please follow our instructions at [in our security policy](https://github.com/SAP/ui5-linter/security/policy) on how to report it. Please do not create GitHub issues for security-related doubts or problems. + +## Code of Conduct + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/SAP/ui5-linter?tab=coc-ov-file#readme) at all times. + +## Licensing + +Copyright 2024 SAP SE or an SAP affiliate company and contributors. Please see our [LICENSE](./LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/ui5-linter). diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 000000000..eb1589d17 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,10 @@ +### Support + +If you need help setting something up, or if you have questions regarding UI5 linter, please refrain from opening an issue on GitHub. + +Instead, please use one of the following platforms to seek help: + +* [StackOverflow](http://stackoverflow.com/questions/tagged/ui5-tooling) +* The [`#tooling`](https://openui5.slack.com/archives/C0A7QFN6B) channel of the [OpenUI5 Community Slack](https://ui5-slack-invite.cfapps.eu10.hana.ondemand.com). + +If you want to report an issue or request a new feature, please follow our [Contribution Guidelines](./CONTRIBUTING.md#-feature-requests). diff --git a/ava.config.js b/ava.config.js new file mode 100644 index 000000000..cca5314a8 --- /dev/null +++ b/ava.config.js @@ -0,0 +1,19 @@ +export default { + "extensions": { + "ts": "module" + }, + "files": [ + "test/lib/**/*.ts" + ], + "watcher": { + "ignoreChanges": [ + "test/tmp/**", + "lib/**" + ] + }, + "nodeArguments": [ + "--import=tsx/esm", + "--no-warnings=ExperimentalWarning" + ], + "workerThreads": false +}; diff --git a/bin/ui5lint.js b/bin/ui5lint.js new file mode 100755 index 000000000..e77976ebb --- /dev/null +++ b/bin/ui5lint.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +import initCli from "../lib/cli.js"; + +initCli(); diff --git a/docs/Guidelines.md b/docs/Guidelines.md new file mode 100644 index 000000000..b6a32ef95 --- /dev/null +++ b/docs/Guidelines.md @@ -0,0 +1,40 @@ +# Development Conventions and Guidelines + +## JavaScript Coding Guidelines + +We enforce code style rules using [ESLint](https://eslint.org). Execute `npm run lint` to check your code for style issues. +You may also find an ESLint integration for your favorite IDE [here](https://eslint.org/docs/user-guide/integrations). + +## Testing + +Unit testing is based on the [ava](https://github.com/avajs/ava) test-framework. You can run all tests using `npm test` (this is what our CI will do for all pull requests). + +During development, you might want to use `npm run unit` or `npm run unit-watch` (re-runs tests automatically after file changes) to quickly execute all unit tests and see whether your change just broke one of them. 😉 + +## Git Guidelines + +### No Merge Commits + +Please use [rebase instead of merge](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) to update a branch to the latest main. This helps keeping a clean commit history in the project. + +### Commit Message Style + +#### Commit Summary + +To be decided. + +#### Commit Body + +To be decided. + +#### Example + +To be decided. + +## Work on Release Branches + +To be decided. + +### Implementing Changes in Multiple Code Lines + +To be decided. diff --git a/docs/images/UI5_logo_wide.png b/docs/images/UI5_logo_wide.png new file mode 100644 index 000000000..6099c574d Binary files /dev/null and b/docs/images/UI5_logo_wide.png differ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json new file mode 100644 index 000000000..860dafec7 --- /dev/null +++ b/npm-shrinkwrap.json @@ -0,0 +1,13094 @@ +{ + "name": "@sap/ui5-linter", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@sap/ui5-linter", + "version": "0.0.1", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/trace-mapping": "^0.3.25", + "@sapui5/types": "1.120.9", + "@ui5/fs": "^3.0.5", + "@ui5/logger": "^3.0.0", + "@ui5/project": "^3.9.0", + "chalk": "^5.3.0", + "figures": "^6.1.0", + "he": "^1.2.0", + "json-source-map": "^0.6.1", + "sax-wasm": "^2.2.4", + "typescript": "5.3.x", + "yargs": "^17.7.2" + }, + "bin": { + "ui5lint": "bin/ui5lint.js" + }, + "devDependencies": { + "@commitlint/cli": "^19.0.3", + "@commitlint/config-conventional": "^19.0.3", + "@istanbuljs/esm-loader-hook": "^0.2.0", + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@types/he": "^1.2.3", + "@types/node": "^20.10.5", + "@types/sinon": "^17.0.3", + "@types/yargs": "^17.0.32", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", + "@ui5-language-assistant/semantic-model": "^3.3.1", + "@ui5-language-assistant/semantic-model-types": "^3.3.1", + "ava": "^6.1.2", + "depcheck": "^1.4.7", + "eslint": "^8.57.0", + "eslint-plugin-ava": "^14.0.0", + "esmock": "^2.6.4", + "husky": "^9.0.11", + "licensee": "^10.0.0", + "nyc": "^15.1.0", + "rimraf": "^5.0.5", + "sinon": "^17.0.1", + "tsx": "^4.7.1" + }, + "engines": { + "node": "^20.11.0 || >=21.2.0", + "npm": ">= 10" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==" + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/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==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/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==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/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==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", + "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.0", + "@babel/parser": "^7.24.0", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", + "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", + "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@blueoak/list": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@blueoak/list/-/list-9.0.0.tgz", + "integrity": "sha512-ExvaAZaZEIhaCePVpqW4ZoFgixhuylQiukSSqaRNfqUtqSWKnlUMZpZWOlugRpfRLuazPkcquDVhPkeodQI5FQ==", + "dev": true + }, + "node_modules/@commitlint/cli": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.0.3.tgz", + "integrity": "sha512-mGhh/aYPib4Vy4h+AGRloMY+CqkmtdeKPV9poMcZeImF5e3knQ5VYaSeAM0mEzps1dbKsHvABwaDpafLUuM96g==", + "dev": true, + "dependencies": { + "@commitlint/format": "^19.0.3", + "@commitlint/lint": "^19.0.3", + "@commitlint/load": "^19.0.3", + "@commitlint/read": "^19.0.3", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.0.3.tgz", + "integrity": "sha512-vh0L8XeLaEzTe8VCxSd0gAFvfTK0RFolrzw4o431bIuWJfi/yRCHJlsDwus7wW2eJaFFDR0VFXJyjGyDQhi4vA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", + "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "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/@commitlint/config-validator/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/@commitlint/ensure": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz", + "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", + "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.0.3.tgz", + "integrity": "sha512-QjjyGyoiVWzx1f5xOteKHNLFyhyweVifMgopozSgx1fGNrGV8+wp7k6n1t6StHdJ6maQJ+UUtO2TcEiBFRyR6Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.0.3.tgz", + "integrity": "sha512-MqDrxJaRSVSzCbPsV6iOKG/Lt52Y+PVwFVexqImmYYFhe51iVJjK2hRhOG2jUAGiUHk4jpdFr0cZPzcBkSzXDQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@commitlint/lint": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.0.3.tgz", + "integrity": "sha512-uHPyRqIn57iIplYa5xBr6oNu5aPXKGC4WLeuHfqQHclwIqbJ33g3yA5fIA+/NYnp5ZM2EFiujqHFaVUYj6HlKA==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^19.0.3", + "@commitlint/parse": "^19.0.3", + "@commitlint/rules": "^19.0.3", + "@commitlint/types": "^19.0.3" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.0.3.tgz", + "integrity": "sha512-18Tk/ZcDFRKIoKfEcl7kC+bYkEQ055iyKmGsYDoYWpKf6FUvBrP9bIWapuy/MB+kYiltmP9ITiUx6UXtqC9IRw==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/execute-rule": "^19.0.0", + "@commitlint/resolve-extends": "^19.0.3", + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0", + "cosmiconfig": "^8.3.6", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load/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/@commitlint/load/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", + "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", + "dev": true, + "dependencies": { + "jiti": "^1.19.1" + }, + "engines": { + "node": ">=v16" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=8.2", + "typescript": ">=4" + } + }, + "node_modules/@commitlint/load/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/@commitlint/message": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz", + "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz", + "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^19.0.3", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.0.3.tgz", + "integrity": "sha512-b5AflTyAXkUx5qKw4TkjjcOccXZHql3JqMi522knTQktq2AubKXFz60Sws+K4FsefwPws6fGz9mqiI/NvsvxFA==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^19.0.0", + "@commitlint/types": "^19.0.3", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.0.3.tgz", + "integrity": "sha512-18BKmta8OC8+Ub+Q3QGM9l27VjQaXobloVXOrMvu8CpEwJYv62vC/t7Ka5kJnsW0tU9q1eMqJFZ/nN9T/cOaIA==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^19.0.3", + "@commitlint/types": "^19.0.3", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz", + "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^19.0.3", + "@commitlint/message": "^19.0.0", + "@commitlint/to-lines": "^19.0.0", + "@commitlint/types": "^19.0.3", + "execa": "^8.0.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz", + "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==", + "dev": true, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz", + "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==", + "dev": true, + "dependencies": { + "find-up": "^7.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level/node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@commitlint/top-level/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/types": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", + "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", + "dev": true, + "dependencies": { + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/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/@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, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/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==" + }, + "node_modules/@isaacs/cliui/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==", + "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/@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "dev": true + }, + "node_modules/@istanbuljs/esm-loader-hook": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/esm-loader-hook/-/esm-loader-hook-0.2.0.tgz", + "integrity": "sha512-pw8o3zWCen4sgiNJq69Pcl1Og7Bx4WP3ho7py2FLqZ56Hnz812yN2WwdViCx9tn9U5EWtzF4aqHDRnD7vDs92g==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.7", + "@istanbuljs/load-nyc-config": "^1.1.0", + "@istanbuljs/schema": "^0.1.3", + "babel-plugin-istanbul": "^6.0.0", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=16.12.0" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/nyc-config-typescript": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", + "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "nyc": ">=15" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "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==", + "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==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "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==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz", + "integrity": "sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@mapbox/node-pre-gyp/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/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/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", + "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/arborist": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-6.5.1.tgz", + "integrity": "sha512-cdV8pGurLK0CifZRilMJbm2CZ3H4Snk8PAqOngj5qmgFLjEllMLvScSZ3XKfd+CK8fo/hrPHO9zazy9OYdvmUg==", + "dev": true, + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^5.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^4.0.0", + "@npmcli/query": "^3.1.0", + "@npmcli/run-script": "^6.0.0", + "bin-links": "^4.0.1", + "cacache": "^17.0.4", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.0", + "nopt": "^7.0.0", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^10.1.0", + "npm-pick-manifest": "^8.0.1", + "npm-registry-fetch": "^14.0.3", + "npmlog": "^7.0.1", + "pacote": "^15.0.8", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.2", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.1", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@npmcli/package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.1.0", + "glob": "^10.2.2", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@npmcli/run-script": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@sigstore/sign/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@sigstore/sign/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/@tufjs/models": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/@npmcli/arborist/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/@npmcli/arborist/node_modules/are-we-there-yet": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", + "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/gauge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.1.tgz", + "integrity": "sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@npmcli/arborist/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/arborist/node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/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/@npmcli/arborist/node_modules/node-gyp/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/@npmcli/arborist/node_modules/node-gyp/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/@npmcli/arborist/node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "dependencies": { + "ignore-walk": "^6.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/npm-pick-manifest": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", + "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/npm-registry-fetch": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/npm-registry-fetch/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/npmlog": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", + "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@npmcli/arborist/node_modules/pacote": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/pacote/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/read-package-json": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "dev": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/arborist/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@npmcli/arborist/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/arborist/node_modules/rimraf/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/@npmcli/arborist/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/arborist/node_modules/semver/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/arborist/node_modules/sigstore": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" + }, + "bin": { + "sigstore": "bin/sigstore.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/sigstore/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/arborist/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/@npmcli/arborist/node_modules/tuf-js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "dev": true, + "dependencies": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/tuf-js/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/arborist/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@npmcli/config": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-8.2.0.tgz", + "integrity": "sha512-YoEYZFg0hRSRP/Chmq+J4FvULFvji6SORUYWQc10FiJ+ReAnViXcDCENg6kM6dID04bAoKNUygrby798+gYBbQ==", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/config/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/config/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/config/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/fs/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@npmcli/git": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.4.tgz", + "integrity": "sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/git/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/semver/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/map-workspaces": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz", + "integrity": "sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg==", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-5.0.1.tgz", + "integrity": "sha512-qb8Q9wIIlEPj3WeA1Lba91R4ZboPL0uspzV0F9uwP+9AYMVB2zOoa7Pbk12g6D2NHAinSbHh6QYmGuRyHZ874Q==", + "dev": true, + "dependencies": { + "cacache": "^17.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^15.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@npmcli/run-script": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/sign/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/@tufjs/models": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/@npmcli/metavuln-calculator/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/@npmcli/metavuln-calculator/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/node-gyp/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/@npmcli/metavuln-calculator/node_modules/node-gyp/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/@npmcli/metavuln-calculator/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "dependencies": { + "ignore-walk": "^6.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npm-pick-manifest": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", + "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npm-registry-fetch": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npm-registry-fetch/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/pacote/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/read-package-json": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "dev": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/rimraf/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/@npmcli/metavuln-calculator/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/semver/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/sigstore": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" + }, + "bin": { + "sigstore": "bin/sigstore.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/sigstore/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/metavuln-calculator/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/@npmcli/metavuln-calculator/node_modules/tuf-js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "dev": true, + "dependencies": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/tuf-js/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@npmcli/move-file/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/move-file/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/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", + "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.0.tgz", + "integrity": "sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/package-json/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/package-json/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@npmcli/promise-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz", + "integrity": "sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/query": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-3.1.0.tgz", + "integrity": "sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", + "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@sapui5/types": { + "version": "1.120.9", + "resolved": "https://registry.npmjs.org/@sapui5/types/-/types-1.120.9.tgz", + "integrity": "sha512-3ZXAJQICE595BalqOKh87uMYeHvTFUx2pnUxRbS4pjQIUYgmGeu5b3v6Hn9SPK+KbEb/PPi3ByBR9K/ayJJ66w==", + "dependencies": { + "@types/jquery": "3.5.13", + "@types/offscreencanvas": "2019.6.4", + "@types/qunit": "2.5.4", + "@types/three": "0.125.3" + } + }, + "node_modules/@sigstore/bundle": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.2.0.tgz", + "integrity": "sha512-5VI58qgNs76RDrwXNhpmyN/jKpq9evV/7f1XrcqcAfvxDl5SeVY/I5Rmfe96ULAV7/FK5dge9RBKGBJPhL1WsQ==", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.0.0.tgz", + "integrity": "sha512-dW2qjbWLRKGu6MIDUTBuJwXCnR8zivcSpf5inUzk7y84zqy/dji0/uahppoIgMoKeR+6pUZucrwHfkQQtiG9Rw==", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.0.tgz", + "integrity": "sha512-zxiQ66JFOjVvP9hbhGj/F/qNdsZfkGb/dVXSanNRNuAzMlr4MC95voPUBX8//ZNnmv3uSYzdfR/JSkrgvZTGxA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.3.tgz", + "integrity": "sha512-LqlA+ffyN02yC7RKszCdMTS6bldZnIodiox+IkT8B2f8oRYXCB3LQ9roXeiEL21m64CVH1wyveYAORfD65WoSw==", + "dependencies": { + "@sigstore/bundle": "^2.2.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.0", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.1.tgz", + "integrity": "sha512-9Iv40z652td/QbV0o5n/x25H9w6IYRt2pIGbTX55yFDYlApDQn/6YZomjz6+KBx69rXHLzHcbtTS586mDdFD+Q==", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.0", + "tuf-js": "^2.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.1.0.tgz", + "integrity": "sha512-1fTqnqyTBWvV7cftUUFtDcHPdSox0N3Ub7C0lRyReYx4zZUlNTZjCV+HPy4Lre+r45dV7Qx5JLKvqqsgxuyYfg==", + "dependencies": { + "@sigstore/bundle": "^2.2.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.0.tgz", + "integrity": "sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/he": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/he/-/he-1.2.3.tgz", + "integrity": "sha512-q67/qwlxblDzEDvzHhVkwc1gzVWxaNxeyHUBF4xElrvjL11O+Ytze+1fGpBHlr/H9myiBUaUXNnNPmBHxxfAcA==", + "dev": true + }, + "node_modules/@types/jquery": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.13.tgz", + "integrity": "sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg==", + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/json-schema": { + "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 + }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==" + }, + "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==", + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==" + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + }, + "node_modules/@types/offscreencanvas": { + "version": "2019.6.4", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", + "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true + }, + "node_modules/@types/qunit": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@types/qunit/-/qunit-2.5.4.tgz", + "integrity": "sha512-VHi2lEd4/zp8OOouf43JXGJJ5ZxHvdLL1dU0Yakp6Iy73SjpuXl7yjwAwmh1qhTv8krDgHteSwaySr++uXX9YQ==" + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "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 + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==" + }, + "node_modules/@types/three": { + "version": "0.125.3", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.125.3.tgz", + "integrity": "sha512-tUPMzKooKDvMOhqcNVUPwkt+JNnF8ASgWSsrLgleVd0SjLj4boJhteSsF9f6YDjye0mmUjO+BDMWW83F97ehXA==" + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/utils/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ui5-language-assistant/semantic-model": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@ui5-language-assistant/semantic-model/-/semantic-model-3.3.1.tgz", + "integrity": "sha512-weexuascJ8ns7hlJWYIX3eQ0tnqZ2u7/1doKUWxGAGH+EulDCkspWk8dnO5vdOK9lgDgCMTgkSPEGK3xzapEEw==", + "dev": true, + "dependencies": { + "@ui5-language-assistant/semantic-model-types": "3.3.1", + "ajv": "6.12.3", + "deep-freeze-strict": "1.1.1", + "fs-extra": "9.0.1", + "lodash": "4.17.21" + } + }, + "node_modules/@ui5-language-assistant/semantic-model-types": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@ui5-language-assistant/semantic-model-types/-/semantic-model-types-3.3.1.tgz", + "integrity": "sha512-VbBnNcdqAyPFl4VK/X7S+cBxIOKp1/kEbhZ8LgGmgpUlCp8E8/5lMsbofUVUzWiUVYDUpUzvLVv6Ft5zkxHcXQ==", + "dev": true + }, + "node_modules/@ui5/builder": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@ui5/builder/-/builder-3.3.0.tgz", + "integrity": "sha512-gQ28Bj4WqF3b+8Mp4luxe2pGb+Adq2qpy1H9JZ8DTpIGcCEcJgJVCTRv6KdWZja6y5ZD89NWQAv0k0N50MV6Sw==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@ui5/fs": "^3.0.5", + "@ui5/logger": "^3.0.0", + "cheerio": "1.0.0-rc.12", + "escape-unicode": "^0.2.0", + "escope": "^4.0.0", + "espree": "^9.6.1", + "graceful-fs": "^4.2.11", + "jsdoc": "^4.0.2", + "less-openui5": "^0.11.6", + "pretty-data": "^0.40.0", + "rimraf": "^5.0.5", + "semver": "^7.5.4", + "terser": "^5.27.0", + "workerpool": "^6.5.1", + "xml2js": "^0.6.2" + }, + "engines": { + "node": "^16.18.0 || >=18.12.0", + "npm": ">= 8" + } + }, + "node_modules/@ui5/builder/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ui5/builder/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ui5/builder/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@ui5/fs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@ui5/fs/-/fs-3.0.5.tgz", + "integrity": "sha512-SpDoMvOGYeBR8xOTDb1cu0uxJNsC1FxrENsZiRMd6R2PfUAiR0fiWQHn4dVBspoLx+jFemAfLfTMv1DEn0m1qQ==", + "dependencies": { + "@ui5/logger": "^3.0.0", + "clone": "^2.1.2", + "escape-string-regexp": "^5.0.0", + "globby": "^13.2.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.5", + "minimatch": "^9.0.3", + "pretty-hrtime": "^1.0.3", + "random-int": "^3.0.0" + }, + "engines": { + "node": "^16.18.0 || >=18.12.0", + "npm": ">= 8" + } + }, + "node_modules/@ui5/fs/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ui5/fs/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ui5/logger": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ui5/logger/-/logger-3.0.0.tgz", + "integrity": "sha512-Np9pHhr+dnyL2gDFwIx6c6Xy0yhtpBIqUQM9An8uLX/wIcRjIjBSQ/r16o3YgS9roY59I/uj5ZEbIa1cdS3Dzg==", + "dependencies": { + "chalk": "^5.2.0", + "cli-progress": "^3.11.2", + "figures": "^5.0.0" + }, + "engines": { + "node": "^16.18.0 || >=18.12.0", + "npm": ">= 8" + } + }, + "node_modules/@ui5/logger/node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ui5/logger/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ui5/project": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@ui5/project/-/project-3.9.0.tgz", + "integrity": "sha512-pm7FzV8oCaZtLBuoH9bVVpAtRz0pwpAJhJKg731lUHGsMkGG5zaWkmUjajBlQR/+dZtWmTlkwxjpJttjUVi43A==", + "dependencies": { + "@npmcli/config": "^8.0.3", + "@ui5/builder": "^3.2.0", + "@ui5/fs": "^3.0.5", + "@ui5/logger": "^3.0.0", + "ajv": "^6.12.6", + "ajv-errors": "^1.0.1", + "chalk": "^5.3.0", + "escape-string-regexp": "^5.0.0", + "globby": "^13.2.2", + "graceful-fs": "^4.2.11", + "js-yaml": "^4.1.0", + "lockfile": "^1.0.4", + "make-fetch-happen": "^13.0.0", + "node-stream-zip": "^1.15.0", + "pacote": "^17.0.5", + "pretty-hrtime": "^1.0.3", + "read-pkg": "^8.1.0", + "read-pkg-up": "^10.1.0", + "resolve": "^1.22.8", + "rimraf": "^5.0.5", + "semver": "^7.5.4", + "xml2js": "^0.6.2", + "yesno": "^0.4.0" + }, + "engines": { + "node": "^16.18.0 || >=18.12.0", + "npm": ">= 8" + } + }, + "node_modules/@ui5/project/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@ui5/project/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==" + }, + "node_modules/@ui5/project/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ui5/project/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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@ui5/project/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ui5/project/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@ui5/project/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ui5/project/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vercel/nft": { + "version": "0.26.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz", + "integrity": "sha512-j4jCOOXke2t8cHZCIxu1dzKLHLcFmYzC3yqAK6MfZznOL1QIJKd0xcFsXK3zcqzU7ScsE2zWkiMMNHGMHgp+FA==", + "dev": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "acorn-import-attributes": "^1.9.2", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "nft": "out/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vercel/nft/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@vercel/nft/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vercel/nft/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/@vue/compiler-core": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz", + "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.23.9", + "@vue/shared": "3.4.21", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz", + "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.4.21", + "@vue/shared": "3.4.21" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz", + "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.23.9", + "@vue/compiler-core": "3.4.21", + "@vue/compiler-dom": "3.4.21", + "@vue/compiler-ssr": "3.4.21", + "@vue/shared": "3.4.21", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.7", + "postcss": "^8.4.35", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz", + "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.4.21", + "@vue/shared": "3.4.21" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz", + "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==", + "dev": true + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.2.tgz", + "integrity": "sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aggregate-error/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "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==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrgv": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", + "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/async-sema": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", + "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/ava": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ava/-/ava-6.1.2.tgz", + "integrity": "sha512-WcpxJ8yZ7mk9ABTinD0IAjcemovSeVGjuuwZx0JS9johREWFeLTl8UP6wd7l6nmnrWqkKZdwaD71a/ocH4qPKw==", + "dev": true, + "dependencies": { + "@vercel/nft": "^0.26.2", + "acorn": "^8.11.3", + "acorn-walk": "^8.3.2", + "ansi-styles": "^6.2.1", + "arrgv": "^1.0.2", + "arrify": "^3.0.0", + "callsites": "^4.1.0", + "cbor": "^9.0.1", + "chalk": "^5.3.0", + "chunkd": "^2.0.1", + "ci-info": "^4.0.0", + "ci-parallel-vars": "^1.0.1", + "cli-truncate": "^4.0.0", + "code-excerpt": "^4.0.0", + "common-path-prefix": "^3.0.0", + "concordance": "^5.0.4", + "currently-unhandled": "^0.4.1", + "debug": "^4.3.4", + "emittery": "^1.0.1", + "figures": "^6.0.1", + "globby": "^14.0.0", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "matcher": "^5.0.0", + "memoize": "^10.0.0", + "ms": "^2.1.3", + "p-map": "^7.0.1", + "package-config": "^5.0.0", + "picomatch": "^3.0.1", + "plur": "^5.1.0", + "pretty-ms": "^9.0.0", + "resolve-cwd": "^3.0.0", + "stack-utils": "^2.0.6", + "strip-ansi": "^7.1.0", + "supertap": "^3.0.1", + "temp-dir": "^3.0.0", + "write-file-atomic": "^5.0.1", + "yargs": "^17.7.2" + }, + "bin": { + "ava": "entrypoints/cli.mjs" + }, + "engines": { + "node": "^18.18 || ^20.8 || ^21" + }, + "peerDependencies": { + "@ava/typescript": "*" + }, + "peerDependenciesMeta": { + "@ava/typescript": { + "optional": true + } + } + }, + "node_modules/ava/node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ava/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ava/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bin-links": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-4.0.3.tgz", + "integrity": "sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA==", + "dev": true, + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "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==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/builtins/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/builtins/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/builtins/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/cacache": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", + "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/cacache/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/caching-transform/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.1.0.tgz", + "integrity": "sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chunkd": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", + "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", + "dev": true + }, + "node_modules/ci-info": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/ci-parallel-vars": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", + "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/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==" + }, + "node_modules/cliui/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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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==", + "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/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cmd-shim": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.2.tgz", + "integrity": "sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "dev": true, + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.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==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/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/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "dev": true + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concordance": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", + "dev": true, + "dependencies": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + }, + "engines": { + "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" + } + }, + "node_modules/concordance/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/concordance/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/concordance/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/correct-license-metadata": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/correct-license-metadata/-/correct-license-metadata-1.4.0.tgz", + "integrity": "sha512-nvbNpK/aYCbztZWGi9adIPqR+ZcQmZTWNT7eMYLvkaVGroN1nTHiVuuNPl7pK6ZNx1mvDztlRBJtfUdrVwKJ5A==", + "dev": true, + "dependencies": { + "spdx-expression-validate": "^2.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "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, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", + "dev": true, + "dependencies": { + "time-zone": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/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/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-freeze-strict": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-freeze-strict/-/deep-freeze-strict-1.1.1.tgz", + "integrity": "sha512-QemROZMM2IvhAcCFvahdX2Vbm4S/txeq5rFYU9fh4mQP79WTMW5c/HkQ2ICl1zuzcDZdPZ6zarDxQeQMsVYoNA==", + "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 + }, + "node_modules/default-require-extensions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depcheck": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz", + "integrity": "sha512-1lklS/bV5chOxwNKA/2XUUk/hPORp8zihZsXflr8x0kLwmcZ9Y9BsS6Hs3ssvA+2wUVbG0U2Ciqvm1SokNjPkA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@vue/compiler-sfc": "^3.3.4", + "callsite": "^1.0.0", + "camelcase": "^6.3.0", + "cosmiconfig": "^7.1.0", + "debug": "^4.3.4", + "deps-regex": "^0.2.0", + "findup-sync": "^5.0.0", + "ignore": "^5.2.4", + "is-core-module": "^2.12.0", + "js-yaml": "^3.14.1", + "json5": "^2.2.3", + "lodash": "^4.17.21", + "minimatch": "^7.4.6", + "multimatch": "^5.0.0", + "please-upgrade-node": "^3.2.0", + "readdirp": "^3.6.0", + "require-package-name": "^2.0.1", + "resolve": "^1.22.3", + "resolve-from": "^5.0.0", + "semver": "^7.5.4", + "yargs": "^16.2.0" + }, + "bin": { + "depcheck": "bin/depcheck.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/depcheck/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/depcheck/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/depcheck/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/depcheck/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/depcheck/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/depcheck/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/depcheck/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/depcheck/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/depcheck/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/depcheck/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/depcheck/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/depcheck/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/depcheck/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/depcheck/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/deps-regex": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.2.0.tgz", + "integrity": "sha512-PwuBojGMQAYbWkMXOY9Pd/NWCDNHVH12pnS7WHqZkTSeMESe4hwnKKRp0yR87g37113x4JPbo/oIvXY+s/f56Q==", + "dev": true + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/docopt": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", + "integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.698", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.698.tgz", + "integrity": "sha512-f9iZD1t3CLy1AS6vzM5EKGa6p9pRcOeEFXRFbaG2Ta+Oe7MkfRQ3fsvPYidzHe1h4i0JvIvpcY55C+B6BZNGtQ==", + "dev": true + }, + "node_modules/emittery": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.0.3.tgz", + "integrity": "sha512-tJdCJitoy2lrC2ldJcqN4vkqJ00lT+tOWNT1hBJjO/3FDMJa5TTIiYGCKGkn/WfCyOzUMObeohbVTj00fhiLiA==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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==" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/enhance-visitors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/enhance-visitors/-/enhance-visitors-1.0.0.tgz", + "integrity": "sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==", + "dev": true, + "dependencies": { + "lodash": "^4.13.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, + "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==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-unicode": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/escape-unicode/-/escape-unicode-0.2.0.tgz", + "integrity": "sha512-7jMQuKb8nm0h/9HYLfu4NCLFwoUsd5XO6OZ1z86PbKcMf8zDK1m7nFR0iA2CCShq4TSValaLIveE8T1UBxgALQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/escope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-4.0.0.tgz", + "integrity": "sha512-E36qlD/r6RJHVpPKArgMoMlNJzoRJFH8z/cAZlI9lbc45zB3+S7i9k6e/MNb+7bZQzNEa6r8WKN3BovpeIBwgA==", + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-ava": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-ava/-/eslint-plugin-ava-14.0.0.tgz", + "integrity": "sha512-XmKT6hppaipwwnLVwwvQliSU6AF1QMHiNoLD5JQfzhUhf0jY7CO0O624fQrE+Y/fTb9vbW8r77nKf7M/oHulxw==", + "dev": true, + "dependencies": { + "enhance-visitors": "^1.0.0", + "eslint-utils": "^3.0.0", + "espree": "^9.0.0", + "espurify": "^2.1.1", + "import-modules": "^2.1.0", + "micro-spelling-correcter": "^1.1.1", + "pkg-dir": "^5.0.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=14.17 <15 || >=16.4" + }, + "peerDependencies": { + "eslint": ">=8.26.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope/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/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/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/eslint/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/eslint/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/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/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/eslint/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/eslint/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/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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/eslint/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/eslint/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/eslint/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/eslint/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/eslint/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/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esmock": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/esmock/-/esmock-2.6.4.tgz", + "integrity": "sha512-w/MIHWZeFzlyW6tTUW/sj1aSAScU8IQapjz8oCxjx3J90fhhmO0QdPGBjPD3oQSLLtVCFcgkTvdh7dNigp9K5A==", + "dev": true, + "engines": { + "node": ">=14.16.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/espurify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", + "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==", + "dev": true + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/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/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "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==", + "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==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "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/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, + "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==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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==" + }, + "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 + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/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/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/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/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/gauge/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/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-directory/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/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/global-prefix/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/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "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==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "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/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", + "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", + "dev": true, + "engines": { + "node": ">=10 <11 || >=12 <13 || >=14" + } + }, + "node_modules/ignore-walk": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", + "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/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/import-meta-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", + "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, + "node_modules/irregular-plurals": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", + "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", + "dev": true, + "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": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, + "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==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, + "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-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/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/istanbul-lib-processinfo/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "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==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@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", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "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-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "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==" + }, + "node_modules/json-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/json-source-map/-/json-source-map-0.6.1.tgz", + "integrity": "sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg==" + }, + "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 + }, + "node_modules/json-stringify-nice": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/just-diff": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==", + "dev": true + }, + "node_modules/just-diff-apply": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", + "dev": true + }, + "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 + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/less-openui5": { + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/less-openui5/-/less-openui5-0.11.6.tgz", + "integrity": "sha512-sQmU+G2pJjFfzRI+XtXkk+T9G0s6UmWWUfOW0utPR46C9lfhNr4DH1lNJuImj64reXYi+vOwyNxPRkj0F3mofA==", + "dependencies": { + "@adobe/css-tools": "^4.0.2", + "clone": "^2.1.2", + "mime": "^1.6.0" + }, + "engines": { + "node": ">= 10", + "npm": ">= 5" + } + }, + "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, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/licensee": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/licensee/-/licensee-10.0.0.tgz", + "integrity": "sha512-gvn5JHCNuchGGjjIm6FsK4qSOTtHkbUfo8YKW61hhEIk3osEf3fKlCH9ma0j+HaVESrOt0YUOmsi/wusKSnneQ==", + "dev": true, + "dependencies": { + "@blueoak/list": "^9.0.0", + "@npmcli/arborist": "^6.1.2", + "correct-license-metadata": "^1.4.0", + "docopt": "^0.6.2", + "has": "^1.0.3", + "npm-license-corrections": "^1.6.2", + "semver": "^7.3.8", + "spdx-expression-parse": "^3.0.1", + "spdx-expression-validate": "^2.0.0", + "spdx-osi": "^3.0.0", + "spdx-whitelisted": "^1.0.0" + }, + "bin": { + "licensee": "licensee" + }, + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/licensee/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/licensee/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/licensee/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "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==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/load-json-file": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", + "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lockfile": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "dependencies": { + "signal-exit": "^3.0.2" + } + }, + "node_modules/lockfile/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true + }, + "node_modules/lodash.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 + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-fetch-happen": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", + "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "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==", + "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.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "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==" + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/matcher": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "dev": true, + "dependencies": { + "blueimp-md5": "^2.10.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/memoize": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.0.0.tgz", + "integrity": "sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/memoize?sponsor=1" + } + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micro-spelling-correcter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", + "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.0.tgz", + "integrity": "sha512-RBfQ+9X9DpXdEoK7Bu+KeEU6vFhumEIiXKWECPzRBmDserEq4uR2b/VCm0LwpMSosoq2k+Zuxj/GzOr0Fn6h/g==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "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/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/multimatch/node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/multimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/multimatch/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/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "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": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nise": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", + "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", + "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-package-data/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/npm-license-corrections": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/npm-license-corrections/-/npm-license-corrections-1.6.2.tgz", + "integrity": "sha512-U66tDCdutNSdzbbPu3IWpgUwcrekT3XW+5fPdRleQmW2kiDqCnurRJnI2kQswRYng1dg/GpgxXE8mT6r6s40rg==", + "dev": true + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/npm-packlist": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", + "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", + "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest/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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/npm-registry-fetch": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz", + "integrity": "sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==", + "dependencies": { + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/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/nyc/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/nyc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/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/nyc/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/nyc/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/nyc/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/nyc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/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/nyc/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/nyc/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/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.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": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", + "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-config": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/package-config/-/package-config-5.0.0.tgz", + "integrity": "sha512-GYTTew2slBcYdvRHqjhwaaydVMvn/qrGC323+nKclYioNSLTDUM/lGgtGTgyHVtYcozb+XkE8CNhwcraOmZ9Mg==", + "dev": true, + "dependencies": { + "find-up-simple": "^1.0.0", + "load-json-file": "^7.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pacote": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz", + "integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==", + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "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/parent-module/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-conflict-json": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz", + "integrity": "sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/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 + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", + "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-dir/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/pkg-dir/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/pkg-dir/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/pkg-dir/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/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/plur": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", + "dev": true, + "dependencies": { + "irregular-plurals": "^3.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "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, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-data": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/pretty-data/-/pretty-data-0.40.0.tgz", + "integrity": "sha512-YFLnEdDEDnkt/GEhet5CYZHCvALw6+Elyb/tp8kQG03ZSIuzeaDWpZYndCXwgqu4NAjh1PI534dhDS1mHarRnQ==", + "engines": { + "node": "*" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pretty-ms": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", + "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", + "dev": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/promise-all-reject-late": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-call-limit": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.2.tgz", + "integrity": "sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/random-int": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/random-int/-/random-int-3.0.0.tgz", + "integrity": "sha512-QvewnOwigesW2WFyTHiQzR6XUUcSQO/BqmfgRz5N5GpGrKQnTf7ebMz8UtuwaET8IfO1n0wLx8/fHsI8E0Jpow==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-cmd-shim": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", + "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-pkg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", + "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", + "dependencies": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^6.0.0", + "parse-json": "^7.0.0", + "type-fest": "^4.2.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", + "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", + "dependencies": { + "find-up": "^6.3.0", + "read-pkg": "^8.1.0", + "type-fest": "^4.2.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.11.1.tgz", + "integrity": "sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/lines-and-columns": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/read-pkg/node_modules/parse-json": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", + "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", + "dependencies": { + "@babel/code-frame": "^7.21.4", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^3.0.0", + "lines-and-columns": "^2.0.3", + "type-fest": "^3.8.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/parse-json/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.11.1.tgz", + "integrity": "sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "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/require-package-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", + "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==", + "dev": true + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, + "node_modules/sax-wasm": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sax-wasm/-/sax-wasm-2.2.4.tgz", + "integrity": "sha512-KreOdNF02zEEDUyqLZjWQTMf+ev/6gEzp2ZT8w2xvqfHO/DRPL4RBYYeiXQpYEGD+1oZ81pjc3fPG5NLDh5ICg==" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sigstore": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.2.2.tgz", + "integrity": "sha512-2A3WvXkQurhuMgORgT60r6pOWiCOO5LlEqY2ADxGBDGVYLSo5HN0uLtb68YpVpuL/Vi8mLTe7+0Dx2Fq8lLqEg==", + "dependencies": { + "@sigstore/bundle": "^2.2.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.0", + "@sigstore/sign": "^2.2.3", + "@sigstore/tuf": "^2.3.1", + "@sigstore/verify": "^1.1.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/sinon": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", + "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/samsam": "^8.0.0", + "diff": "^5.1.0", + "nise": "^5.1.5", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", + "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "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==", + "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==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/spawn-wrap/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/spawn-wrap/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/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/spawn-wrap/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spawn-wrap/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/spdx-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", + "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.2", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "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==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-expression-validate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz", + "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" + }, + "node_modules/spdx-osi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-osi/-/spdx-osi-3.0.0.tgz", + "integrity": "sha512-7DZMaD/rNHWGf82qWOazBsLXQsaLsoJb9RRjhEUQr5o86kw3A1ErGzSdvaXl+KalZyKkkU5T2a5NjCCutAKQSw==", + "dev": true + }, + "node_modules/spdx-ranges": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", + "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", + "dev": true + }, + "node_modules/spdx-whitelisted": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-whitelisted/-/spdx-whitelisted-1.0.0.tgz", + "integrity": "sha512-X4FOpUCvZuo42MdB1zAZ/wdX4N0lLcWDozf2KYFVDgtLv8Lx+f31LOYLP2/FcwTzsPi64bS/VwKqklI4RBletg==", + "dev": true, + "dependencies": { + "spdx-compare": "^1.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supertap": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", + "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", + "serialize-error": "^7.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "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/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/terser": { + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", + "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/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/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/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/treeverse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tsx": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.1.tgz", + "integrity": "sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==", + "dev": true, + "dependencies": { + "esbuild": "~0.19.10", + "get-tsconfig": "^4.7.2" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tuf-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.0.tgz", + "integrity": "sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==", + "dependencies": { + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "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, + "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/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "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==" + }, + "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==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "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": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/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==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "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==", + "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/wrap-ansi-cjs/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/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==" + }, + "node_modules/wrap-ansi-cjs/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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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==" + }, + "node_modules/wrap-ansi/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==", + "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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yesno": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.4.0.tgz", + "integrity": "sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==" + }, + "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" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..7bb080047 --- /dev/null +++ b/package.json @@ -0,0 +1,94 @@ +{ + "name": "@sap/ui5-linter", + "version": "0.0.1", + "description": "Work in Progress", + "author": { + "name": "SAP SE", + "email": "openui5@sap.com", + "url": "https://www.sap.com" + }, + "license": "Apache-2.0", + "keywords": [ + "openui5", + "sapui5", + "ui5", + "development", + "linter" + ], + "bin": { + "ui5lint": "./bin/ui5lint.js" + }, + "type": "module", + "scripts": { + "build": "npm run cleanup && tsc -p .", + "build-watch": "npm run cleanup && tsc -w -p .", + "check-licenses": "licensee --errors-only", + "cleanup": "rimraf lib coverage", + "coverage": "nyc ava --node-arguments=\"--experimental-loader=@istanbuljs/esm-loader-hook\"", + "depcheck": "depcheck --ignores @commitlint/config-conventional,@istanbuljs/esm-loader-hook,@sapui5/types,@ui5/logger,ava,rimraf,sap,tsx,json-source-map,he,@types/he", + "hooks:pre-push": "npm run lint:commit", + "lint": "eslint .", + "lint:commit": "commitlint -e", + "prepare": "node ./.husky/skip.js || husky", + "test": "npm run lint && npm run build && npm run unit", + "unit": "ava", + "unit-debug": "ava debug", + "unit-update-snapshots": "ava --update-snapshots", + "unit-watch": "ava --watch", + "update-semantic-model-info": "tsx scripts/metadataProvider/createMetadataInfo.ts" + }, + "files": [ + "CHANGELOG.md", + "CONTRIBUTING.md", + "bin/**", + "lib/**", + "LICENSES/**", + ".reuse/**", + "resources/**" + ], + "engines": { + "node": "^20.11.0 || >=21.2.0", + "npm": ">= 10" + }, + "packageManager": "npm@10.1.0", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/trace-mapping": "^0.3.25", + "@sapui5/types": "1.120.9", + "@ui5/fs": "^3.0.5", + "@ui5/logger": "^3.0.0", + "@ui5/project": "^3.9.0", + "chalk": "^5.3.0", + "figures": "^6.1.0", + "he": "^1.2.0", + "json-source-map": "^0.6.1", + "sax-wasm": "^2.2.4", + "typescript": "5.3.x", + "yargs": "^17.7.2" + }, + "devDependencies": { + "@commitlint/cli": "^19.0.3", + "@commitlint/config-conventional": "^19.0.3", + "@istanbuljs/esm-loader-hook": "^0.2.0", + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@types/he": "^1.2.3", + "@types/node": "^20.10.5", + "@types/sinon": "^17.0.3", + "@types/yargs": "^17.0.32", + "@typescript-eslint/eslint-plugin": "^7.1.1", + "@typescript-eslint/parser": "^7.1.1", + "@ui5-language-assistant/semantic-model": "^3.3.1", + "@ui5-language-assistant/semantic-model-types": "^3.3.1", + "ava": "^6.1.2", + "depcheck": "^1.4.7", + "eslint": "^8.57.0", + "eslint-plugin-ava": "^14.0.0", + "esmock": "^2.6.4", + "husky": "^9.0.11", + "licensee": "^10.0.0", + "nyc": "^15.1.0", + "rimraf": "^5.0.5", + "sinon": "^17.0.1", + "tsx": "^4.7.1" + } +} diff --git a/resources/api-extract.json b/resources/api-extract.json new file mode 100644 index 000000000..33c2ab656 --- /dev/null +++ b/resources/api-extract.json @@ -0,0 +1,440 @@ +{ + "framework": { + "name": "SAPUI5", + "version": "1.120.9" + }, + "defaultAggregations": { + "sap.ca.ui.CustomerControlListItem": "content", + "sap.ca.ui.ExpansibleFeedListItem": "actions", + "sap.ca.ui.GrowingTileContainer": "content", + "sap.ca.ui.HierarchicalSelectDialog": "items", + "sap.ca.ui.Notes": "items", + "sap.ca.ui.PictureTile": "content", + "sap.ca.ui.PictureViewer": "items", + "sap.ca.ui.ZoomableScrollContainer": "content", + "sap.f.AvatarGroup": "items", + "sap.f.DynamicPageHeader": "content", + "sap.f.GridContainer": "items", + "sap.f.GridList": "items", + "sap.f.GridListItem": "content", + "sap.f.semantic.SemanticPage": "content", + "sap.f.SidePanelItem": "content", + "sap.gantt.def.cal.Calendar": "timeIntervals", + "sap.gantt.def.cal.CalendarDefs": "defs", + "sap.gantt.def.SvgDefs": "defs", + "sap.gantt.overlays.GanttRowOverlay": "staticOverlay", + "sap.gantt.overlays.Overlay": "shape", + "sap.gantt.simple.ContainerToolbar": "content", + "sap.gantt.simple.GanttChartContainer": "ganttCharts", + "sap.gantt.simple.GanttRowSettings": "shapes1", + "sap.gantt.simple.LegendContainer": "legends", + "sap.gantt.simple.ListLegend": "items", + "sap.gantt.simple.ListLegendItem": "shape", + "sap.gantt.simple.MultiActivityGroup": "task", + "sap.gantt.simple.MultiActivityRowSettings": "tasks", + "sap.gantt.simple.StockChart": "stockChartDimensions", + "sap.gantt.simple.StockChartDimension": "stockChartPeriods", + "sap.gantt.simple.UtilizationBarChart": "periods", + "sap.gantt.simple.UtilizationDimension": "periods", + "sap.gantt.simple.UtilizationLineChart": "dimensions", + "sap.m.ActionSelect": "items", + "sap.m.ActionSheet": "buttons", + "sap.m.App": "pages", + "sap.m.Breadcrumbs": "links", + "sap.m.Carousel": "pages", + "sap.m.Column": "header", + "sap.m.ColumnListItem": "cells", + "sap.m.ComboBox": "items", + "sap.m.ComboBoxBase": "items", + "sap.m.CustomListItem": "content", + "sap.m.CustomTile": "content", + "sap.m.CustomTreeItem": "content", + "sap.m.Dialog": "content", + "sap.m.FacetFilter": "lists", + "sap.m.FacetFilterList": "items", + "sap.m.FeedContent": "_contentTextAgr", + "sap.m.FeedListItem": "actions", + "sap.m.FlexBox": "items", + "sap.m.GenericTag": "value", + "sap.m.GenericTile": "tileContent", + "sap.m.GrowingList": "items", + "sap.m.HBox": "items", + "sap.m.HeaderContainer": "content", + "sap.m.IconTabFilter": "content", + "sap.m.ImageContent": "_content", + "sap.m.Input": "suggestionItems", + "sap.m.InputListItem": "content", + "sap.m.LightBox": "imageContent", + "sap.m.List": "items", + "sap.m.ListBase": "items", + "sap.m.Menu": "items", + "sap.m.MenuButton": "menu", + "sap.m.MenuItem": "items", + "sap.m.MessageItem": "link", + "sap.m.MessagePopover": "items", + "sap.m.MessagePopoverItem": "link", + "sap.m.MessageStrip": "link", + "sap.m.MessageView": "items", + "sap.m.MultiComboBox": "items", + "sap.m.MultiInput": "suggestionItems", + "sap.m.NavContainer": "pages", + "sap.m.NewsContent": "_contentText", + "sap.m.NotificationList": "items", + "sap.m.NotificationListGroup": "items", + "sap.m.ObjectHeader": "attributes", + "sap.m.ObjectListItem": "attributes", + "sap.m.OverflowToolbar": "content", + "sap.m.OverflowToolbarMenuButton": "menu", + "sap.m.p13n.AbstractContainer": "views", + "sap.m.p13n.AbstractContainerItem": "content", + "sap.m.p13n.Container": "views", + "sap.m.P13nColumnsPanel": "items", + "sap.m.P13nDialog": "content", + "sap.m.P13nDimMeasurePanel": "items", + "sap.m.P13nFilterPanel": "items", + "sap.m.P13nGroupPanel": "items", + "sap.m.P13nPanel": "items", + "sap.m.P13nSortPanel": "items", + "sap.m.Page": "content", + "sap.m.Panel": "content", + "sap.m.Popover": "content", + "sap.m.QuickView": "pages", + "sap.m.QuickViewBase": "pages", + "sap.m.QuickViewCard": "pages", + "sap.m.QuickViewGroup": "elements", + "sap.m.QuickViewPage": "groups", + "sap.m.RadioButtonGroup": "buttons", + "sap.m.RangeSlider": "scale", + "sap.m.ResponsivePopover": "content", + "sap.m.ScrollContainer": "content", + "sap.m.SearchField": "suggestionItems", + "sap.m.SegmentedButton": "buttons", + "sap.m.Select": "items", + "sap.m.SelectDialog": "items", + "sap.m.SelectionDetails": "items", + "sap.m.SelectList": "items", + "sap.m.semantic.DetailPage": "content", + "sap.m.semantic.FilterSelect": "items", + "sap.m.semantic.FullscreenPage": "content", + "sap.m.semantic.GroupSelect": "items", + "sap.m.semantic.MasterPage": "content", + "sap.m.semantic.SemanticPage": "content", + "sap.m.semantic.SemanticSelect": "items", + "sap.m.semantic.ShareMenuPage": "content", + "sap.m.semantic.SortSelect": "items", + "sap.m.Shell": "app", + "sap.m.Slider": "scale", + "sap.m.SlideTile": "tiles", + "sap.m.Table": "items", + "sap.m.table.columnmenu.Item": "content", + "sap.m.table.columnmenu.Menu": "quickActions", + "sap.m.table.columnmenu.QuickAction": "content", + "sap.m.TableSelectDialog": "items", + "sap.m.TileContainer": "tiles", + "sap.m.TileContent": "content", + "sap.m.Title": "content", + "sap.m.Tokenizer": "tokens", + "sap.m.Toolbar": "content", + "sap.m.Tree": "items", + "sap.m.upload.Column": "header", + "sap.m.upload.FilePreviewDialog": "additionalFooterButtons", + "sap.m.upload.UploadSet": "items", + "sap.m.upload.UploadSetItem": "attributes", + "sap.m.upload.UploadSetwithTable": "items", + "sap.m.upload.UploadSetwithTableItem": "cells", + "sap.m.UploadCollection": "items", + "sap.m.UploadCollectionItem": "attributes", + "sap.m.VariantManagement": "items", + "sap.m.VBox": "items", + "sap.m.Wizard": "steps", + "sap.m.WizardStep": "content", + "sap.sac.df.FilterBar": "filterItems", + "sap.sac.df.FlexAnalysis": "customPanels", + "sap.sac.df.FlexAnalysisPanel": "content", + "sap.suite.ui.commons.BulletChart": "actual", + "sap.suite.ui.commons.CalculationBuilder": "items", + "sap.suite.ui.commons.ChartContainer": "content", + "sap.suite.ui.commons.CloudFilePicker": "content", + "sap.suite.ui.commons.ColumnMicroChart": "columns", + "sap.suite.ui.commons.ComparisonChart": "data", + "sap.suite.ui.commons.DynamicContainer": "tiles", + "sap.suite.ui.commons.GenericTile": "tileContent", + "sap.suite.ui.commons.HarveyBallMicroChart": "items", + "sap.suite.ui.commons.imageeditor.ImageEditorContainer": "imageEditor", + "sap.suite.ui.commons.imageeditor.ImageEditorResponsiveContainer": "imageEditor", + "sap.suite.ui.commons.JamContent": "_contentTextAgr", + "sap.suite.ui.commons.LinkActionSheet": "buttons", + "sap.suite.ui.commons.MicroAreaChart": "lines", + "sap.suite.ui.commons.MicroAreaChartItem": "points", + "sap.suite.ui.commons.NewsContent": "_contentText", + "sap.suite.ui.commons.ProcessFlow": "lanes", + "sap.suite.ui.commons.ProcessFlowConnection": "_labels", + "sap.suite.ui.commons.statusindicator.CustomShape": "shapes", + "sap.suite.ui.commons.statusindicator.LibraryShape": "shapes", + "sap.suite.ui.commons.statusindicator.ShapeGroup": "shapes", + "sap.suite.ui.commons.statusindicator.StatusIndicator": "groups", + "sap.suite.ui.commons.TileContent": "content", + "sap.suite.ui.commons.Timeline": "content", + "sap.suite.ui.commons.TimelineItem": "embeddedControl", + "sap.suite.ui.commons.VerticalNavigationBar": "items", + "sap.suite.ui.commons.ViewRepeater": "rows", + "sap.suite.ui.microchart.AreaMicroChart": "lines", + "sap.suite.ui.microchart.AreaMicroChartItem": "points", + "sap.suite.ui.microchart.BulletMicroChart": "actual", + "sap.suite.ui.microchart.ColumnMicroChart": "columns", + "sap.suite.ui.microchart.ComparisonMicroChart": "data", + "sap.suite.ui.microchart.HarveyBallMicroChart": "items", + "sap.suite.ui.microchart.InteractiveBarChart": "bars", + "sap.suite.ui.microchart.InteractiveDonutChart": "segments", + "sap.suite.ui.microchart.InteractiveLineChart": "points", + "sap.suite.ui.microchart.LineMicroChart": "points", + "sap.suite.ui.microchart.LineMicroChartLine": "points", + "sap.suite.ui.microchart.StackedBarMicroChart": "bars", + "sap.tnt.NavigationList": "items", + "sap.tnt.NavigationListItem": "items", + "sap.tnt.SideNavigation": "item", + "sap.tnt.ToolHeader": "content", + "sap.ui.commons.Accordion": "sections", + "sap.ui.commons.AccordionSection": "content", + "sap.ui.commons.AutoComplete": "items", + "sap.ui.commons.Carousel": "content", + "sap.ui.commons.ComboBox": "items", + "sap.ui.commons.Dialog": "content", + "sap.ui.commons.DropdownBox": "items", + "sap.ui.commons.form.Form": "formContainers", + "sap.ui.commons.form.FormContainer": "formElements", + "sap.ui.commons.form.FormElement": "fields", + "sap.ui.commons.form.SimpleForm": "content", + "sap.ui.commons.InPlaceEdit": "content", + "sap.ui.commons.layout.AbsoluteLayout": "positions", + "sap.ui.commons.layout.BorderLayoutArea": "content", + "sap.ui.commons.layout.HorizontalLayout": "content", + "sap.ui.commons.layout.MatrixLayout": "rows", + "sap.ui.commons.layout.MatrixLayoutCell": "content", + "sap.ui.commons.layout.MatrixLayoutRow": "cells", + "sap.ui.commons.layout.PositionContainer": "control", + "sap.ui.commons.layout.ResponsiveFlowLayout": "content", + "sap.ui.commons.layout.VerticalLayout": "content", + "sap.ui.commons.ListBox": "items", + "sap.ui.commons.Menu": "items", + "sap.ui.commons.MenuBar": "items", + "sap.ui.commons.MenuButton": "menu", + "sap.ui.commons.MenuItem": "submenu", + "sap.ui.commons.MenuItemBase": "submenu", + "sap.ui.commons.MenuTextFieldItem": "submenu", + "sap.ui.commons.Panel": "content", + "sap.ui.commons.RadioButtonGroup": "items", + "sap.ui.commons.RoadMap": "steps", + "sap.ui.commons.RoadMapStep": "subSteps", + "sap.ui.commons.RowRepeater": "rows", + "sap.ui.commons.Tab": "content", + "sap.ui.commons.TabStrip": "tabs", + "sap.ui.commons.Toolbar": "items", + "sap.ui.commons.Tree": "nodes", + "sap.ui.commons.TreeNode": "nodes", + "sap.ui.comp.filterbar.FilterBar": "content", + "sap.ui.comp.navpopover.NavigationPopover": "content", + "sap.ui.comp.odata.ComboBox": "items", + "sap.ui.comp.smartchart.SmartChart": "items", + "sap.ui.comp.smartfield.ComboBox": "items", + "sap.ui.comp.smartfilterbar.SFBMultiComboBox": "items", + "sap.ui.comp.smartfilterbar.SmartFilterBar": "content", + "sap.ui.comp.smartform.Group": "groupElements", + "sap.ui.comp.smartform.GroupElement": "elements", + "sap.ui.comp.smartform.SemanticGroupElement": "elements", + "sap.ui.comp.smartform.SmartForm": "groups", + "sap.ui.comp.smartlist.SmartList": "items", + "sap.ui.comp.smartmicrochart.SmartAreaMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartBulletMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartColumnMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartComparisonMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartDeltaMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartHarveyBallMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartLineMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartMicroChartBase": "_chart", + "sap.ui.comp.smartmicrochart.SmartRadialMicroChart": "_chart", + "sap.ui.comp.smartmicrochart.SmartStackedBarMicroChart": "_chart", + "sap.ui.comp.smartmultiedit.Container": "layout", + "sap.ui.comp.smarttable.SmartTable": "items", + "sap.ui.comp.smartvariants.SmartVariantManagement": "variantItems", + "sap.ui.comp.smartvariants.SmartVariantManagementBase": "variantItems", + "sap.ui.comp.valuehelpdialog.ValueHelpDialog": "content", + "sap.ui.comp.variants.EditableVariantItem": "cells", + "sap.ui.comp.variants.VariantManagement": "items", + "sap.ui.core.mvc.HTMLView": "content", + "sap.ui.core.mvc.JSONView": "content", + "sap.ui.core.mvc.JSView": "content", + "sap.ui.core.mvc.TemplateView": "content", + "sap.ui.core.mvc.View": "content", + "sap.ui.core.mvc.XMLView": "content", + "sap.ui.core.tmpl.DOMElement": "attributes", + "sap.ui.fl.transport.TransportDialog": "content", + "sap.ui.integration.designtime.baseEditor.BaseEditor": "content", + "sap.ui.layout.BlockLayout": "content", + "sap.ui.layout.BlockLayoutCell": "content", + "sap.ui.layout.BlockLayoutRow": "content", + "sap.ui.layout.cssgrid.CSSGrid": "items", + "sap.ui.layout.DynamicSideContent": "mainContent", + "sap.ui.layout.form.Form": "formContainers", + "sap.ui.layout.form.FormContainer": "formElements", + "sap.ui.layout.form.FormElement": "fields", + "sap.ui.layout.form.SemanticFormElement": "fields", + "sap.ui.layout.form.SimpleForm": "content", + "sap.ui.layout.Grid": "content", + "sap.ui.layout.HorizontalLayout": "content", + "sap.ui.layout.PaneContainer": "panes", + "sap.ui.layout.ResponsiveFlowLayout": "content", + "sap.ui.layout.ResponsiveSplitter": "rootPaneContainer", + "sap.ui.layout.SplitPane": "content", + "sap.ui.layout.Splitter": "contentAreas", + "sap.ui.layout.VerticalLayout": "content", + "sap.ui.mdc.ActionToolbar": "actions", + "sap.ui.mdc.actiontoolbar.ActionToolbarAction": "action", + "sap.ui.mdc.Chart": "items", + "sap.ui.mdc.chart.ChartSelectionDetails": "items", + "sap.ui.mdc.Field": "content", + "sap.ui.mdc.field.CustomFieldInfo": "content", + "sap.ui.mdc.field.FieldBase": "content", + "sap.ui.mdc.field.FieldInput": "suggestionItems", + "sap.ui.mdc.field.FieldMultiInput": "suggestionItems", + "sap.ui.mdc.field.TokenizerDisplay": "tokens", + "sap.ui.mdc.FilterBar": "filterItems", + "sap.ui.mdc.filterbar.FilterBarBase": "filterItems", + "sap.ui.mdc.filterbar.p13n.AdaptationFilterBar": "filterItems", + "sap.ui.mdc.filterbar.vh.CollectiveSearchSelect": "items", + "sap.ui.mdc.filterbar.vh.FilterBar": "filterItems", + "sap.ui.mdc.FilterField": "content", + "sap.ui.mdc.MultiValueField": "items", + "sap.ui.mdc.Table": "columns", + "sap.ui.mdc.table.Column": "template", + "sap.ui.mdc.valuehelp.content.Bool": "items", + "sap.ui.mdc.valuehelp.content.FixedList": "items", + "sap.ui.mdc.valuehelp.content.MDCTable": "table", + "sap.ui.mdc.valuehelp.content.MTable": "table", + "sap.ui.table.AnalyticalColumn": "label", + "sap.ui.table.AnalyticalColumnMenu": "items", + "sap.ui.table.AnalyticalTable": "columns", + "sap.ui.table.Column": "label", + "sap.ui.table.ColumnMenu": "items", + "sap.ui.table.Row": "cells", + "sap.ui.table.RowAction": "items", + "sap.ui.table.Table": "columns", + "sap.ui.table.TreeTable": "columns", + "sap.ui.unified.Menu": "items", + "sap.ui.unified.MenuItem": "submenu", + "sap.ui.unified.MenuItemBase": "submenu", + "sap.ui.unified.MenuTextFieldItem": "submenu", + "sap.ui.unified.Shell": "content", + "sap.ui.unified.ShellLayout": "content", + "sap.ui.unified.ShellOverlay": "content", + "sap.ui.unified.SplitContainer": "content", + "sap.ui.ux3.Exact": "attributes", + "sap.ui.ux3.ExactArea": "content", + "sap.ui.ux3.ExactAttribute": "attributes", + "sap.ui.ux3.ExactBrowser": "attributes", + "sap.ui.ux3.NavigationBar": "items", + "sap.ui.ux3.NavigationItem": "subItems", + "sap.ui.ux3.OverlayContainer": "content", + "sap.ui.ux3.Shell": "content", + "sap.ui.ux3.ThingGroup": "content", + "sap.ui.ux3.ToolPopup": "content", + "sap.ui.vbm.AnalyticMap": "vos", + "sap.ui.vbm.Areas": "items", + "sap.ui.vbm.Boxes": "items", + "sap.ui.vbm.Circles": "items", + "sap.ui.vbm.ClusterBase": "vizTemplate", + "sap.ui.vbm.ClusterDistance": "vizTemplate", + "sap.ui.vbm.ClusterGrid": "vizTemplate", + "sap.ui.vbm.ClusterTree": "vizTemplate", + "sap.ui.vbm.Containers": "items", + "sap.ui.vbm.FeatureCollection": "items", + "sap.ui.vbm.GeoCircles": "items", + "sap.ui.vbm.GeoJsonLayer": "items", + "sap.ui.vbm.GeoMap": "vos", + "sap.ui.vbm.Heatmap": "items", + "sap.ui.vbm.Legend": "items", + "sap.ui.vbm.Pie": "items", + "sap.ui.vbm.Pies": "items", + "sap.ui.vbm.Routes": "items", + "sap.ui.vbm.Spots": "items", + "sap.ui.vk.ContainerBase": "content", + "sap.ui.vk.ContentConnector": "contentResources", + "sap.ui.vk.FlexibleControl": "content", + "sap.ui.vk.MapContainer": "content", + "sap.ui.vk.Viewer": "contentResources", + "sap.ui.vtm.MessagesPopover": "content", + "sap.ui.vtm.Vtm": "extensions", + "sap.ui.webc.fiori.Bar": "middleContent", + "sap.ui.webc.fiori.DynamicSideContent": "content", + "sap.ui.webc.fiori.IllustratedMessage": "actions", + "sap.ui.webc.fiori.MediaGallery": "items", + "sap.ui.webc.fiori.MediaGalleryItem": "content", + "sap.ui.webc.fiori.NotificationListGroupItem": "items", + "sap.ui.webc.fiori.Page": "content", + "sap.ui.webc.fiori.ProductSwitch": "items", + "sap.ui.webc.fiori.ShellBar": "items", + "sap.ui.webc.fiori.SideNavigation": "items", + "sap.ui.webc.fiori.SideNavigationItem": "items", + "sap.ui.webc.fiori.Timeline": "items", + "sap.ui.webc.fiori.TimelineItem": "content", + "sap.ui.webc.fiori.UploadCollection": "items", + "sap.ui.webc.fiori.UploadCollectionItem": "content", + "sap.ui.webc.fiori.Wizard": "steps", + "sap.ui.webc.fiori.WizardStep": "content", + "sap.ui.webc.main.Avatar": "image", + "sap.ui.webc.main.AvatarGroup": "items", + "sap.ui.webc.main.Breadcrumbs": "items", + "sap.ui.webc.main.BusyIndicator": "content", + "sap.ui.webc.main.Calendar": "dates", + "sap.ui.webc.main.Card": "content", + "sap.ui.webc.main.Carousel": "content", + "sap.ui.webc.main.ColorPalette": "colors", + "sap.ui.webc.main.ColorPalettePopover": "colors", + "sap.ui.webc.main.ComboBox": "items", + "sap.ui.webc.main.CustomListItem": "content", + "sap.ui.webc.main.Dialog": "content", + "sap.ui.webc.main.FileUploader": "content", + "sap.ui.webc.main.Input": "suggestionItems", + "sap.ui.webc.main.List": "items", + "sap.ui.webc.main.Menu": "items", + "sap.ui.webc.main.MenuItem": "items", + "sap.ui.webc.main.MultiComboBox": "items", + "sap.ui.webc.main.MultiInput": "suggestionItems", + "sap.ui.webc.main.Panel": "content", + "sap.ui.webc.main.Popover": "content", + "sap.ui.webc.main.ResponsivePopover": "content", + "sap.ui.webc.main.SegmentedButton": "items", + "sap.ui.webc.main.Select": "options", + "sap.ui.webc.main.SelectMenu": "content", + "sap.ui.webc.main.SelectMenuOption": "content", + "sap.ui.webc.main.Tab": "content", + "sap.ui.webc.main.TabContainer": "items", + "sap.ui.webc.main.Table": "rows", + "sap.ui.webc.main.TableCell": "content", + "sap.ui.webc.main.TableColumn": "content", + "sap.ui.webc.main.TableRow": "cells", + "sap.ui.webc.main.Toolbar": "items", + "sap.ui.webc.main.ToolbarSelect": "options", + "sap.ui.webc.main.Tree": "items", + "sap.ui.webc.main.TreeItem": "items", + "sap.ui.webc.main.TreeItemCustom": "items", + "sap.ushell.components.factsheet.controls.PictureTile": "content", + "sap.ushell.components.factsheet.controls.PictureViewer": "items", + "sap.uxap.AnchorBar": "content", + "sap.uxap.BlockBase": "mappings", + "sap.uxap.BreadCrumbs": "links", + "sap.uxap.HierarchicalSelect": "items", + "sap.uxap.ObjectPageDynamicHeaderContent": "content", + "sap.uxap.ObjectPageHeader": "actions", + "sap.uxap.ObjectPageLayout": "sections", + "sap.uxap.ObjectPageLazyLoader": "content", + "sap.uxap.ObjectPageSection": "subSections", + "sap.uxap.ObjectPageSubSection": "blocks", + "sap.zen.commons.layout.AbsoluteLayout": "positions", + "sap.zen.commons.layout.MatrixLayout": "rows", + "sap.zen.commons.layout.MatrixLayoutRow": "cells", + "sap.zen.commons.layout.PositionContainer": "control", + "sap.zen.dsh.ValueHelpDialog": "content" + } +} \ No newline at end of file diff --git a/resources/overrides/index.d.ts b/resources/overrides/index.d.ts new file mode 100644 index 000000000..9bf823e08 --- /dev/null +++ b/resources/overrides/index.d.ts @@ -0,0 +1 @@ +import "./jquery.sap.mobile"; diff --git a/resources/overrides/jquery.sap.mobile.d.ts b/resources/overrides/jquery.sap.mobile.d.ts new file mode 100644 index 000000000..87ffad010 --- /dev/null +++ b/resources/overrides/jquery.sap.mobile.d.ts @@ -0,0 +1,17 @@ +interface JQueryStatic { + /** + * Holds information about the current operating system + * + * @deprecated since 1.20 use {@link sap.ui.Device.os} instead + */ + os: object; + + /** + * @deprecated since 1.20 use the respective functions of {@link sap.ui.Device} instead + */ + device: object; +} + +declare module "jquery.sap.mobile" { + export default jQuery; +} diff --git a/resources/overrides/package.json b/resources/overrides/package.json new file mode 100644 index 000000000..55acd5737 --- /dev/null +++ b/resources/overrides/package.json @@ -0,0 +1,3 @@ +{ + "types": "index.d.ts" +} diff --git a/rfcs/0000-template.md b/rfcs/0000-template.md new file mode 100644 index 000000000..18d93cd16 --- /dev/null +++ b/rfcs/0000-template.md @@ -0,0 +1,52 @@ +- Start Date: YYYY-MM-DD +- RFC PR: - +- Issue: - + + +# RFC 0000 Fancy Title +*Disclaimer: This template is derived from the great [RFC template](https://github.com/yarnpkg/rfcs/blob/main/0000-template.md) that Yarn has come up with. (You may remove this disclaimer).* + +## Summary + + +One paragraph explanation of the feature. + +## Motivation + + +Why are we doing this? What use cases does it support? What is the expected outcome? + +Please focus on explaining the motivation so that if this RFC is not accepted, the motivation could be used to develop alternative solutions. In other words, enumerate the constraints you are trying to solve without coupling them too closely to the solution you have in mind. + +## Detailed design + + +This is the bulk of the RFC. Explain the design in enough detail for somebody familiar with the UI5 linter to understand, and for somebody familiar with the implementation to implement. This should get into specifics and corner-cases, and include examples of how the feature is used. Any new terminology should be defined here. + +## How we teach this + + +What names and terminology work best for these concepts and why? How is this idea best presented? + +Would the acceptance of this proposal mean the UI5 linter or any of its sub-components documentation must be re-organized or altered? + +How should this feature be introduced and taught to existing UI5 linter users? + +## Drawbacks + + +Why should we not do this? Please consider the impact on teaching people to use the UI5 linter, on the integration of this feature with existing and planned features, on the impact of churn on existing users. + +There are trade-offs to choosing any path, please attempt to identify them here. + +## Alternatives + + +What other designs have been considered? What is the impact of not doing this? + +## Unresolved Questions and Bikeshedding + + +*This section should be removed (i.e. resolved) before merging* + +Optional, but suggested for first drafts. What parts of the design are still TBD? Are there any second priority decisions left to be made? diff --git a/scripts/metadataProvider/MetadataProvider.ts b/scripts/metadataProvider/MetadataProvider.ts new file mode 100644 index 000000000..806aec843 --- /dev/null +++ b/scripts/metadataProvider/MetadataProvider.ts @@ -0,0 +1,49 @@ +import {createSemanticModel} from "./model.js"; + +import { + findSymbol +} from "@ui5-language-assistant/semantic-model"; +import { + BaseUI5Node, + UI5Class, + UI5SemanticModel, +} from "@ui5-language-assistant/semantic-model-types"; + +export default class MetadataProvider { + #model: UI5SemanticModel | null = null; + async init(apiJsonsRoot: string) { + this.#model = await createSemanticModel(apiJsonsRoot); + } + + getModel(): UI5SemanticModel { + if (!this.#model) { + throw new Error(`Model not yet initialized`); + } + return this.#model; + } + + getDefaultAggregationForControl(controlName: string): string | undefined { + // console.time("getDefaultAggregationForControl"); + const controlMetadata = findSymbol(this.getModel(), controlName); + if (controlMetadata) { + return this.getDefaultAggregationForSymbol(controlMetadata); + } + } + + getDefaultAggregationForSymbol(symbol: BaseUI5Node): string | undefined { + // console.time("getDefaultAggregationForSymbol"); + if (symbol.kind !== "UI5Class") { + return undefined; + } + let classMetadata = symbol as UI5Class; + while (!classMetadata.defaultAggregation) { + if (!classMetadata.extends) { + return undefined; + } + classMetadata = classMetadata.extends; + } + // console.timeEnd("getDefaultAggregationForSymbol"); + return classMetadata.defaultAggregation?.name; + } +} + diff --git a/scripts/metadataProvider/createMetadataInfo.ts b/scripts/metadataProvider/createMetadataInfo.ts new file mode 100644 index 000000000..d1bc08d5d --- /dev/null +++ b/scripts/metadataProvider/createMetadataInfo.ts @@ -0,0 +1,49 @@ +import {writeFile} from "node:fs/promises"; +import MetadataProvider from "./MetadataProvider"; + +import { + forEachSymbol +} from "@ui5-language-assistant/semantic-model"; + +async function main(apiJsonsRoot: string, sapui5Version: string) { + const metadataProvider = new MetadataProvider(); + await metadataProvider.init(apiJsonsRoot); + + const semanticModel = metadataProvider.getModel(); + + const defaultAggregations: Record = {}; + forEachSymbol(semanticModel, (symbol, symbolName) => { + const defaultAggregation = metadataProvider.getDefaultAggregationForSymbol(symbol); + if (defaultAggregation) { + defaultAggregations[symbolName] = defaultAggregation; + } + }); + + const apiExtract = { + framework: { + name: "SAPUI5", + version: sapui5Version + }, + defaultAggregations + }; + + await writeFile( + new URL("../../resources/api-extract.json", import.meta.url), + JSON.stringify(apiExtract, null, 2) + ); +} + +try { + const apiJsonsRoot = process.argv[2]; + if (!apiJsonsRoot) { + throw new Error("first argument 'apiJsonsRoot' is missing"); + } + const sapui5Version = process.argv[3]; + if (!sapui5Version) { + throw new Error("second argument 'sapui5Version' is missing"); + } + await main(apiJsonsRoot, sapui5Version); +} catch (err) { + process.stderr.write(String(err)); + process.exit(1); +} diff --git a/scripts/metadataProvider/model.ts b/scripts/metadataProvider/model.ts new file mode 100644 index 000000000..d7b96ac61 --- /dev/null +++ b/scripts/metadataProvider/model.ts @@ -0,0 +1,84 @@ +import fs from "fs/promises"; +import path from "node:path"; +import {isLogLevelEnabled} from "@ui5/logger"; +import { + generate, + TypeNameFix, +} from "@ui5-language-assistant/semantic-model"; +import { + UI5SemanticModel +} from "@ui5-language-assistant/semantic-model-types"; + +interface ApiJson { + library: string +} + +function getTypeNameFix(): TypeNameFix { + // From https://github.com/SAP/ui5-language-assistant/blob/44114f34de59e8d415b06b470be6fa3697c7414c/packages/context/src/ui5-model.ts#L229 + const fixes: TypeNameFix = { + Control: "sap.ui.core.Control", + Element: "sap.ui.core.Element", + array: "object[]", + Array: "object[]", + bloolean: "boolean", + any: "any", + "sap.m.PlanningCalendarHeader": undefined, + "sap.m.TimePickerSlider": undefined, + "sap.ui.layout.ResponsiveSplitterPage": undefined, + "sap.gantt.misc.AxisTime": "sap.gantt.misc.AxisTimes", + "sap.gantt.control.Toolbar": undefined, + "sap.gantt.DragOrientation": undefined, + "sap.gantt.simple.GanttHeader": undefined, + "sap.gantt.simple.InnerGanttChart": undefined, + "sap.rules.ui.RuleBase": undefined, + "sap.ui.generic.app.transaction.BaseController": undefined, + "sap.ui.vk.BillboardTextEncoding": undefined, + "sap.ui.vk.BillboardStyle": undefined, + "sap.ui.vk.BillboardBorderLineStyle": undefined, + "sap.ui.vk.BillboardHorizontalAlignment": undefined, + "sap.ui.vk.BillboardCoordinateSpace": undefined, + "sap.ui.vk.DetailViewType": undefined, + "sap.ui.vk.DetailViewShape": undefined, + "sap.ui.vk.tools.HitTestIdMode": undefined, + "sap.ui.vk.tools.CoordinateSystem": undefined, + "sap.ui.vk.AnimationTimeSlider": undefined, + "sap.ui.vk.SelectionMode": undefined, + "sap.ui.vk.RenderMode": undefined, + "sap.viz.ui5.controls.VizRangeSlider": undefined, + }; + return fixes; +} + +let model: UI5SemanticModel | null = null; +export async function createSemanticModel(apiJsonsRoot: string): Promise { + if (model) { + return model; + } + const indexJson: Record = {}; + const apiJsonFiles = await fs.readdir(apiJsonsRoot); + for (const apiJsonFile of apiJsonFiles) { + const apiJson = await fs.readFile(path.join(apiJsonsRoot, apiJsonFile), "utf-8"); + const apiJsonParsed = JSON.parse(apiJson) as ApiJson; + indexJson[apiJsonParsed.library] = apiJsonParsed; + } + /* eslint-disable no-console */ + let originalConsoleError; + if (!isLogLevelEnabled("verbose")) { + // Overwrite console.error with a noop since #generate produces a lot of messages error messages + // that we don't want to deal with right now + originalConsoleError = console.error; + console.error = () => {}; + } + model = generate({ + version: "1.120.9", + libraries: indexJson, + typeNameFix: getTypeNameFix(), + strict: false, // Throw instead of log errors + printValidationErrors: false, + }); + if (originalConsoleError) { + console.error = originalConsoleError; + } + /* eslint-enable no-console */ + return model; +} diff --git a/src/cli.ts b/src/cli.ts new file mode 100644 index 000000000..05dafe657 --- /dev/null +++ b/src/cli.ts @@ -0,0 +1,38 @@ +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; +import base from "./cli/base.js"; +import { fileURLToPath } from "node:url"; +import { setVersion } from "./cli/version.js"; +import { createRequire } from "module"; + +export default async function () { + const cli = yargs(hideBin(process.argv)); + cli.parserConfiguration({ + "parse-numbers": false + }); + + // Explicitly set CLI version as the yargs default might + // be wrong in case a local CLI installation is used + // Also add CLI location + const require = createRequire(import.meta.url); + const pkg = require("../package.json") as { version: string }; + const ui5LintJsPath = fileURLToPath(new URL("../bin/ui5lint.js", import.meta.url)); + const pkgVersion = `${pkg.version} (from ${ui5LintJsPath})`; + + setVersion(pkgVersion); + cli.version(pkgVersion); + + // Explicitly set script name to prevent windows from displaying "ui5-linter.js" + cli.scriptName("ui5lint"); + + // Setup base command + base(cli); + + // Format terminal output to full available width + cli.wrap(cli.terminalWidth()); + + // await cli.parse(); + // yargs registers a get method on the argv property. + // The property needs to be accessed to initialize everything. + cli.argv; +} diff --git a/src/cli/base.ts b/src/cli/base.ts new file mode 100644 index 000000000..ba285e086 --- /dev/null +++ b/src/cli/base.ts @@ -0,0 +1,180 @@ +import {Argv, ArgumentsCamelCase} from "yargs"; +import path from "node:path"; +import { lintProject } from "../linter/linter.js"; +import { Text } from "../formatter/text.js"; +import { Json } from "../formatter/json.js"; +import { Coverage } from "../formatter/coverage.js"; +import { writeFile } from "node:fs/promises"; +import baseMiddleware from "./middlewares/base.js"; +import chalk from "chalk"; +import { isLogLevelEnabled } from "@ui5/logger"; +import ConsoleWriter from "@ui5/logger/writers/Console"; + +const lintCommand = { + command: "$0", + describe: "Runs linter", + handler: handleLint, + middlewares: [baseMiddleware], + builder: function (cli: Argv) { + cli.usage("Usage: $0 [options]") + .option("file-paths", { + describe: "", + type: "string" + }) + .array("file-paths") + .option("coverage", { + describe: "Whether to provide a coverage report", + type: "boolean" + }) + .option("details", { + describe: "Print complementary information for each finding, if available", + type: "boolean" + }) + .option("loglevel", { + alias: "log-level", + describe: "Set the logging level", + default: "info", + type: "string", + choices: ["silent", "error", "warn", "info", "perf", "verbose", "silly"] + }) + .option("verbose", { + describe: "Enable verbose logging.", + default: false, + type: "boolean" + }) + .option("perf", { + describe: "Enable performance measurements and related logging.", + default: false, + type: "boolean" + }) + .option("silent", { + describe: "Disable all log output.", + default: false, + type: "boolean" + }) + .option("format", { + alias: "f", + describe: "Set the output format for the linter result", + default: "stylish", + type: "string", + choices: ["stylish", "json"] + }) + .coerce([ + // base.js + "log-level" + ], (arg) => { + // If an option is specified multiple times, yargs creates an array for all the values, + // independently of whether the option is of type "array" or "string". + // This is unexpected for options listed above, which should all only have only one + // definitive value. The yargs behavior could be disabled by using the parserConfiguration + // "duplicate-arguments-array": true. However, yargs would then cease to create arrays for + // those options where we *do* expect the automatic creation of arrays in case the option + // is specified multiple times. Like "--include-task". + // Also see https://github.com/yargs/yargs/issues/1318 + // Note: This is not necessary for options of type "boolean" + if (Array.isArray(arg)) { + // If the option is specified multiple times, use the value of the last option + return arg[arg.length - 1]; + } + return arg; + }) + .example("ui5lint --coverage", + "Execute ui5lint with coverage enabled") + .example("ui5lint --file-paths /path/to/resources", + "Execute command with scope of file-paths"); + + return cli; + } +}; + +async function handleLint(argv: ArgumentsCamelCase) { + const { + coverage, + filePaths, + details, + format + } = <{ coverage: boolean, filePaths: string[], details: boolean, format: string }>argv; + + let profile; + if (process.env.UI5LINT_PROFILE) { + profile = await import("./utils/profile.js"); + await profile.start(); + } + + const res = await lintProject({ + rootDir: path.join(process.cwd()), + filePaths: filePaths && filePaths.map((filePath) => path.resolve(process.cwd(), filePath)), + }); + + if (process.env.UI5LINT_COVERAGE_REPORT || coverage) { + const coverageFormatter = new Coverage(); + await writeFile("ui5lint-report.html", await coverageFormatter.format(res)); + } + + if (format === "json") { + const jsonFormatter = new Json(); + process.stdout.write(jsonFormatter.format(res, details)); + + } else if (format === "" || format === "stylish") { + const textFormatter = new Text(); + process.stderr.write(textFormatter.format(res, details)); + } + // Stop profiling after CLI finished execution + if (profile) { + await profile.stop(); + } +} + +export default function base(cli: Argv) { + cli + .showHelpOnFail(true) + .strict(true) + .fail(function (msg, err) { + if (err) { + ConsoleWriter.stop(); + // Exception + if (isLogLevelEnabled("error")) { + process.stderr.write("\n"); + process.stderr.write(chalk.bold.red("⚠️ Process Failed With Error\n")); + + process.stderr.write("\n"); + process.stderr.write(chalk.underline("Error Message:\n")); + process.stderr.write(err.message + "\n"); + + // Unexpected errors should always be logged with stack trace + const unexpectedErrors = ["SyntaxError", "ReferenceError", "TypeError"]; + if (unexpectedErrors.includes(err.name) || isLogLevelEnabled("verbose")) { + process.stderr.write("\n"); + if (err.stack) { + process.stderr.write(chalk.underline("Stack Trace:\n")); + process.stderr.write(err.stack + "\n"); + process.stderr.write("\n"); + } + if (err.cause instanceof Error && err.cause.stack) { + process.stderr.write(chalk.underline("Error Cause Stack Trace:\n")); + process.stderr.write(err.cause.stack + "\n"); + process.stderr.write("\n"); + } + process.stderr.write( + chalk.dim( + `If you think this is an issue of the ui5-linter, you might report it using the ` + + `following URL: `) + + chalk.dim.bold.underline(`https://github.com/SAP/ui5-linter/issues/new/choose`)+"\n"); + } else { + process.stderr.write("\n"); + process.stderr.write(chalk.dim(`For details, execute the same command again with an` + + ` additional '--verbose' parameter`) + "\n"); + } + } + } else { + // Yargs error + process.stderr.write(chalk.bold.yellow("Command Failed:\n")); + process.stderr.write(`${msg}\n`); + process.stderr.write("\n"); + process.stderr.write(chalk.dim(`See 'ui5lint --help'`)+"\n"); + } + process.exit(1); + }); + + cli.command(lintCommand); +} diff --git a/src/cli/middlewares/base.ts b/src/cli/middlewares/base.ts new file mode 100644 index 000000000..0c48e62a4 --- /dev/null +++ b/src/cli/middlewares/base.ts @@ -0,0 +1,14 @@ +import { initLogger } from "./logger.js"; +import type { ArgumentsCamelCase } from "yargs"; +/** + * Base middleware for CLI commands. + * + * This middleware should be executed for every CLI command to enable basic features (e.g. logging). + * + * @param {object} argv The CLI arguments + * @returns {object} + */ +export default async function (argv: ArgumentsCamelCase) { + await initLogger(argv); + return {}; +} diff --git a/src/cli/middlewares/logger.ts b/src/cli/middlewares/logger.ts new file mode 100644 index 000000000..83bd2eb31 --- /dev/null +++ b/src/cli/middlewares/logger.ts @@ -0,0 +1,34 @@ +import {setLogLevel, isLogLevelEnabled, getLogger} from "@ui5/logger"; +import ConsoleWriter from "@ui5/logger/writers/Console"; +import {getVersion} from "../version.js"; +import type { ArgumentsCamelCase } from "yargs"; +/** + * Logger middleware to enable logging capabilities + * + * @param {object} argv logger arguments + */ +export async function initLogger(argv: ArgumentsCamelCase) { + if (argv.silent) { + setLogLevel("silent"); + } + if (argv.perf) { + setLogLevel("perf"); + } + if (argv.verbose) { + setLogLevel("verbose"); + } + if (argv.loglevel && argv.loglevel !== "info") { + // argv.loglevel defaults to "info", which is anyways already the Logger's default + // Therefore do not explicitly set it again in order to allow overwriting the log level + // using the UI5_LOG_LVL environment variable + setLogLevel(argv.loglevel); + } + + // Initialize writer + ConsoleWriter.init(); + if (isLogLevelEnabled("verbose")) { + const log = getLogger("cli:middlewares:base"); + log.verbose(`using ui5lint version ${getVersion()}`); + log.verbose(`using node version ${process.version}`); + } +} diff --git a/src/cli/utils/profile.ts b/src/cli/utils/profile.ts new file mode 100644 index 000000000..2e88e71bd --- /dev/null +++ b/src/cli/utils/profile.ts @@ -0,0 +1,98 @@ +import {writeFile} from "node:fs/promises"; +import {Session, Profiler} from "node:inspector"; +import {getLogger} from "@ui5/logger"; +const log = getLogger("cli:utils:profile"); + +let session: Session | null; +type ProcessSignals = Record void> +let processSignals: ProcessSignals | null; + +export async function start() { + if (session) { + return; + } + session = new Session(); + session.connect(); + await new Promise((resolve) => { + session?.post("Profiler.enable", () => { + log.info(`Recording CPU profile...`); + session?.post("Profiler.start", () => { + processSignals = registerSigHooks(); + resolve(); + }); + }); + }); +} + +async function writeProfile(profile: Profiler.Profile) { + const formatter = new Intl.DateTimeFormat("en-GB", { + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); + const dateParts = Object.create(null); + const parts = formatter.formatToParts(new Date()); + parts.forEach((p) => { + dateParts[p.type] = p.value; + }); + + const fileName = `./ui5_${dateParts.year}-${dateParts.month}-${dateParts.day}_` + + `${dateParts.hour}-${dateParts.minute}-${dateParts.second}.cpuprofile`; + log.info(`\nSaving CPU profile to ${fileName}...`); + await writeFile(fileName, JSON.stringify(profile)); +} + +export async function stop() { + if (!session) { + return; + } + if (processSignals) { + deregisterSigHooks(processSignals); + processSignals = null; + } + const profile = await new Promise((resolve) => { + session?.post("Profiler.stop", (err, {profile}) => { + if (err) { + resolve(null); + } else { + resolve(profile); + } + }); + session = null; + }); + if (profile) { + await writeProfile(profile); + } +} + +function registerSigHooks() { + function createListener(exitCode: number) { + return function() { + // Gracefully end profiling, then exit + stop().then(() => { + process.exit(exitCode); + }); + }; + } + + const processSignals: ProcessSignals = { + "SIGHUP": createListener(128 + 1), + "SIGINT": createListener(128 + 2), + "SIGTERM": createListener(128 + 15), + "SIGBREAK": createListener(128 + 21) + }; + + for (const signal of Object.keys(processSignals)) { + process.on(signal, processSignals[signal]); + } + return processSignals; +} + +function deregisterSigHooks(signals: ProcessSignals) { + for (const signal of Object.keys(signals)) { + process.removeListener(signal, signals[signal]); + } +} diff --git a/src/cli/version.ts b/src/cli/version.ts new file mode 100644 index 000000000..98d70eff3 --- /dev/null +++ b/src/cli/version.ts @@ -0,0 +1,9 @@ +let version: string; + +// This module holds the CLI's version information (set via cli.js) for later retrieval (e.g. from middlewares/logger) +export function setVersion(v: string) { + version = v; +} +export function getVersion(): string { + return version || ""; +} diff --git a/src/detectors/AbstractDetector.ts b/src/detectors/AbstractDetector.ts new file mode 100644 index 000000000..be7a13989 --- /dev/null +++ b/src/detectors/AbstractDetector.ts @@ -0,0 +1,69 @@ +import {Project} from "@ui5/project"; + +// Data types are structured very similar to the ESLint types for better compatibility into existing integrations: +// https://eslint.org/docs/latest/integrate/nodejs-api#-lintresult-type +export interface LintResult { + filePath: string, + messages: LintMessage[], + coverageInfo: CoverageInfo[], + errorCount: number, // includes fatal errors + fatalErrorCount: number, + warningCount: number, +} + +export enum LintMessageSeverity { + Warning = 1, + Error = 2 +} + +export interface LintMessage { + ruleId: string, + severity: LintMessageSeverity, + message: string, + messageDetails?: string, + fatal?: boolean | undefined, // e.g. parsing error + line?: number | undefined, // 1 based to be aligned with most IDEs + column?: number | undefined, // 1 based to be aligned with most IDEs + endLine?: number | undefined, + endColumn?: number | undefined +} + +export enum CoverageCategory { + CallExpressionUnknownType = 1, +} + +export interface CoverageInfo { + category: CoverageCategory + message: string, + messageDetails?: string, + line?: number | undefined, // 1 based to be aligned with most IDEs + column?: number | undefined, // 1 based to be aligned with most IDEs + endLine?: number | undefined, + endColumn?: number | undefined +} + +// export interface DetectorCapabilities { +// // TODO: Expose supported file types and names +// } + +abstract class AbstractDetector { + abstract createReports(filePaths: string[]): Promise + // abstract getCapabilities(): DetectorCapabilities +} +export abstract class FileBasedDetector extends AbstractDetector{ + rootDir: string; + + constructor(rootDir: string) { + super(); + this.rootDir = rootDir; + } +} + +export abstract class ProjectBasedDetector extends AbstractDetector{ + project: Project; + + constructor(project: Project) { + super(); + this.project = project; + } +} diff --git a/src/detectors/BaseReporter.ts b/src/detectors/BaseReporter.ts new file mode 100644 index 000000000..966b5b321 --- /dev/null +++ b/src/detectors/BaseReporter.ts @@ -0,0 +1,34 @@ +import type ts from "typescript"; +import type { LintMessage, CoverageInfo, LintResult } from "../detectors/AbstractDetector.js"; + +export interface BaseReporter { + addMessage(args: ReporterMessage): void, + addCoverageInfo(args: ReporterCoverageInfo): void, + getReport(): LintResult +} + +export type ReporterMessage = { + node?: ts.Node | string, + message: LintMessage["message"], + messageDetails?: LintMessage["messageDetails"], + severity: LintMessage["severity"], + ruleId: LintMessage["ruleId"], + fatal?: LintMessage["fatal"], +} + +export interface PositionInfo { + line: number, + column: number, +} + +export interface PositionRange { + start: PositionInfo + end?: PositionInfo +} + +export interface ReporterCoverageInfo { + node: ts.Node | string, + message: CoverageInfo["message"], + messageDetails?: CoverageInfo["messageDetails"], + category: CoverageInfo["category"], +} diff --git a/src/detectors/Reporter.ts b/src/detectors/Reporter.ts new file mode 100644 index 000000000..469ad8927 --- /dev/null +++ b/src/detectors/Reporter.ts @@ -0,0 +1,170 @@ +import path from "path"; +import ts from "typescript"; +import { + TraceMap, + originalPositionFor, + LEAST_UPPER_BOUND, + GREATEST_LOWER_BOUND +} from "@jridgewell/trace-mapping"; + +import {LintMessageSeverity} from "./AbstractDetector.js"; +import {resolveLinks} from "../formatter/lib/resolveLinks.js"; + +import type {LintResult, LintMessage, CoverageInfo} from "./AbstractDetector.js"; +import type { + BaseReporter, + ReporterMessage, + ReporterCoverageInfo, + PositionInfo, + PositionRange +} from "./BaseReporter.js"; + +export default class Reporter implements BaseReporter { + #rootDir: string; + #filePath: string; + #sourceFile: ts.SourceFile | undefined; + #traceMap: TraceMap | undefined; + #messages: LintMessage[] = []; + #coverageInfo: CoverageInfo[] = []; + + constructor(rootDir: string, filePath: string, sourceFile?: ts.SourceFile, sourceMap?: string) { + this.#rootDir = rootDir; + this.#filePath = filePath; + this.#sourceFile = sourceFile; + if (sourceMap) { + this.#traceMap = new TraceMap(sourceMap); + } + } + + addMessage({node, message, messageDetails, severity, ruleId, fatal = undefined}: ReporterMessage) { + if (fatal && severity !== LintMessageSeverity.Error) { + throw new Error(`Reports flagged as "fatal" must be of severity "Error"`); + } + + let line = 1, column = 1; + if (node) { + const {start} = this.#getPositionsForNode(node); + // One-based to be aligned with most IDEs + line = start.line + 1; + column = start.column + 1; + // endLine = end.line + 1; + // endColumn = end.column + 1; + } + + const msg: LintMessage = { + ruleId, + severity, + fatal, + line, + column, + message, + }; + + if (messageDetails) { + msg["messageDetails"] = resolveLinks(messageDetails); + } + + this.#messages.push(msg); + } + + addCoverageInfo({node, message, messageDetails, category}: ReporterCoverageInfo) { + const {start} = this.#getPositionsForNode(node); + const coverageInfo: CoverageInfo = { + category, + // One-based to be aligned with most IDEs + line: start.line + 1, + column: start.column + 1, + // endLine: end.line + 1, + // endColumn: end.column + 1, + message + }; + + if (messageDetails) { + coverageInfo["messageDetails"] = resolveLinks(messageDetails); + } + + this.#coverageInfo.push(coverageInfo); + } + + #getPositionsForNode(node: ts.Node): PositionRange { + return { + start: this.#getPosition(node.getStart()), + // end: this.#getPosition(node.getEnd()) + }; + } + + #getPosition(pos: number): PositionInfo { + if (!this.#sourceFile) { + throw new Error(`No source file available for file ${this.#filePath}`); + } + // Typescript positions are all zero-based + const {line, character: column} = this.#sourceFile.getLineAndCharacterOfPosition(pos); + + if (this.#traceMap) { + // trace-mapping's originalPositionFor uses one-based lines and zero-based columns for input and output + let tracedPos = originalPositionFor(this.#traceMap, { + line: line + 1, + column, + bias: GREATEST_LOWER_BOUND + }); + + if (tracedPos.line === null) { + // No source map found at or before the given position. + // Try again with the least upper bound (i.e. the first mapping after the given position) + tracedPos = originalPositionFor(this.#traceMap, { + line: line + 1, + column, + bias: LEAST_UPPER_BOUND + }); + } + + if (tracedPos.line === null) { + throw new Error( + `Failed to map back to source: ${this.#sourceFile.fileName} ` + + `(line: ${line + 1}, column: ${column + 1})`); + } + return { + line: tracedPos.line - 1, // Subtract 1 again to restore zero-based lines to match TypeScript output + column: tracedPos.column + }; + } + return { + line, + column + }; + } + + #getFileName(): string { + let formattedFilePath: string = this.#filePath; + if (this.#traceMap?.sources?.length && this.#traceMap.sources[0] && + this.#traceMap.sources[0] !== "UNKNOWN") { + formattedFilePath = path.join(path.dirname(this.#filePath), this.#traceMap.sources[0]); + } + // re-format from absolute to relative path: + return path.relative(this.#rootDir, formattedFilePath); + } + + getReport(): LintResult { + let errorCount = 0; + let warningCount = 0; + let fatalErrorCount = 0; + for (const {severity, fatal} of this.#messages) { + if (severity === LintMessageSeverity.Error) { + errorCount++; + if (fatal) { + fatalErrorCount++; + } + } else { + warningCount++; + } + } + return { + filePath: this.#getFileName(), + messages: this.#messages, + coverageInfo: this.#coverageInfo, + errorCount, + warningCount, + fatalErrorCount, + }; + } +} diff --git a/src/detectors/transpilers/AbstractTranspiler.ts b/src/detectors/transpilers/AbstractTranspiler.ts new file mode 100644 index 000000000..3a108ddde --- /dev/null +++ b/src/detectors/transpilers/AbstractTranspiler.ts @@ -0,0 +1,7 @@ +import {LintMessage} from "../AbstractDetector.js"; + +export interface TranspileResult { + source: string, + map: string, + messages?: LintMessage[], +} diff --git a/src/detectors/transpilers/amd/TsTransformer.ts b/src/detectors/transpilers/amd/TsTransformer.ts new file mode 100644 index 000000000..5f7843329 --- /dev/null +++ b/src/detectors/transpilers/amd/TsTransformer.ts @@ -0,0 +1,165 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import parseModuleDeclaration from "./parseModuleDeclaration.js"; +import moduleDeclarationToDefinition, {ModuleDefinition} from "./moduleDeclarationToDefinition.js"; +import parseRequire from "./parseRequire.js"; +import {transformAsyncRequireCall, transformSyncRequireCall} from "./requireExpressionToTransformation.js"; +import pruneNode, {UnsafeNodeRemoval} from "./pruneNode.js"; +import replaceNodeInParent, {NodeReplacement} from "./replaceNodeInParent.js"; +import {UnsupportedModuleError} from "./util.js"; + +const log = getLogger("transpilers:amd:TsTransformer"); + +// Augment typescript's Node interface to add a property for marking nodes for removal +declare module "typescript" { + interface Node { + _remove?: boolean + } +} + +/** + * Creates a TypeScript "transformer" that will be applied to each source file, doing the actual transpilation + * The source file is expected to be classic UI5 JavaScript, using UI5s's AMD loader and other UI5 specific API. + * Modern JavaScript language features are generally supported, however there might be gaps in the implementation + * at the time of writing this comment. + * + * If a transformation of a specific API (such as "sap.ui.define") is not possible for some reason, an "Unsupported*" + * error is thrown. In that case, the rest of the module is still processed. However it's possible that the result + * will be equal to the input. +*/ +export function createTransformer(resourcePath: string, program: ts.Program): ts.TransformerFactory { + return function transformer(context: ts.TransformationContext) { + return (sourceFile: ts.SourceFile): ts.SourceFile => { + return transform(resourcePath, program, sourceFile, context); + }; + }; +} + +function transform( + resourcePath: string, program: ts.Program, sourceFile: ts.SourceFile, context: ts.TransformationContext +): ts.SourceFile { + const checker = program.getTypeChecker(); + const {factory: nodeFactory} = context; + const moduleDefinitions: ModuleDefinition[] = []; + // TODO: Filter duplicate imports, maybe group by module definition + const requireImports: ts.ImportDeclaration[] = []; + const requireFunctions: ts.FunctionDeclaration[] = []; + const nodeReplacements = new Map(); + + function replaceNode(node: ts.Node, substitute: ts.Node) { + let replacements = nodeReplacements.get(node.parent); + if (!replacements) { + replacements = []; + nodeReplacements.set(node.parent, replacements); + } + replacements.push({original: node, substitute}); + } + + // Visit the AST depth-first and collect module definitions + function visit(nodeIn: ts.Node): ts.VisitResult { + const node = ts.visitEachChild(nodeIn, visit, context); + if (ts.isCallExpression(node) && + ts.isPropertyAccessExpression(node.expression)) { + if (matchPropertyAccessExpression(node.expression, "sap.ui.define")) { + try { + const moduleDeclaration = parseModuleDeclaration(node.arguments, checker); + const moduleDefinition = moduleDeclarationToDefinition(moduleDeclaration, sourceFile, nodeFactory); + moduleDefinitions.push(moduleDefinition); + pruneNode(node); // Mark the define call for removal + } catch(err) { + if (err instanceof UnsupportedModuleError) { + log.verbose(`Failed to transform sap.ui.define call in ${resourcePath}: ${err.message}`); + } else { + throw err; + } + } + } else if (matchPropertyAccessExpression(node.expression, "sap.ui.require")) { + try { + const requireExpression = parseRequire(node.arguments, checker); + if (requireExpression.async) { + const res = transformAsyncRequireCall(node, requireExpression, nodeFactory); + requireImports.push(...res.imports); + if (res.callback) { + replaceNode(node, res.callback); + if (res.errback) { + requireFunctions.push(res.errback); + } + } else { + // async sap.ui.require without a callback (import only) + try { + pruneNode(node); + } catch(err) { + if (err instanceof UnsafeNodeRemoval) { + // If removal is not possible, replace the CallExpression with "undefined" + // (i.e. the original return value) + replaceNode(node, nodeFactory.createIdentifier("undefined")); + } else { + throw err; + } + } + } + } else { + const res = transformSyncRequireCall(node, requireExpression, nodeFactory); + requireImports.push(res.import); + replaceNode(node, res.requireStatement); + } + } catch(err) { + if (err instanceof UnsupportedModuleError) { + log.verbose(`Failed to transform sap.ui.require call in ${resourcePath}: ${err.message}`); + } else { + throw err; + } + } + } + } + return node; + } + let processedSourceFile = ts.visitNode(sourceFile, visit) as ts.SourceFile; + + const statements = [ + ...requireImports, + ...processedSourceFile.statements as unknown as ts.Statement[], + ...requireFunctions, + ]; + moduleDefinitions.forEach(({imports, body}) => { + // Add imports of each module definition to the top of the program + statements.unshift(...imports); + // Add the module definition body to the end of the program + statements.push(...body); + }); + + // Update the AST with extracted nodes from the module definitions and require expressions + processedSourceFile = nodeFactory.updateSourceFile(processedSourceFile, statements); + + // Visit the AST breadth-first and remove nodes marked for remove as well as + // replacing nodes marked for replacement + function removeAndReplaceNodes(node: ts.Node): ts.VisitResult { + if (node._remove) { + // console.log(`Cleanup: Removing node ${ts.SyntaxKind[node.kind]}`); + return undefined; + } + const replacements = nodeReplacements.get(node); + if (replacements) { + for (const replacement of replacements) { + node = replaceNodeInParent(node, replacement, nodeFactory); + } + } + return ts.visitEachChild(node, removeAndReplaceNodes, context); + } + processedSourceFile = ts.visitNode(processedSourceFile, removeAndReplaceNodes) as ts.SourceFile; + return processedSourceFile; +} + +// TODO PERF: Use a match array instead of string to be able to match individual parts of the property access chain +// early (i.e. exist immediately if the last expression does not match the last match) +function matchPropertyAccessExpression(node: ts.PropertyAccessExpression, match: string) : boolean { + const propAccessChain: string[] = []; + propAccessChain.push(node.expression.getText()); + + let scanNode: ts.Node = node; + while (ts.isPropertyAccessExpression(scanNode)) { + propAccessChain.push(scanNode.name.getText()); + scanNode = scanNode.parent; + } + return propAccessChain.join(".") === match; +} diff --git a/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts b/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts new file mode 100644 index 000000000..15d7b1586 --- /dev/null +++ b/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts @@ -0,0 +1,326 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import {ModuleDeclaration} from "./parseModuleDeclaration.js"; +import rewriteExtendCall, {UnsupportedExtendCall} from "./rewriteExtendCall.js"; +import {UnsupportedModuleError, toPosStr} from "./util.js"; +import pruneNode from "./pruneNode.js"; +const {SyntaxKind} = ts; + +const log = getLogger("transpilers:amd:moduleDeclarationToDefinition"); + +export interface ModuleDefinition { + name?: string, + body: ts.Statement[], + imports: ts.ImportDeclaration[] +} + +export default function( + moduleDeclaration: ModuleDeclaration, sourceFile: ts.SourceFile, nodeFactory: ts.NodeFactory +): ModuleDefinition { + const {imports, identifiers: importIdentifiers} = collectImports(moduleDeclaration, nodeFactory); + const body = getModuleBody(moduleDeclaration, sourceFile, nodeFactory, importIdentifiers); + /* Ignore module name and export flag for now */ + return { + imports, + body, + }; +} + +/** Convert dependencies declaration to import statements: + * a) If dependencies is an ArrayExpression, extract the values and create import statements. + * If factory is a Function extract the names of the parameters and use them for the imports. + * If no parameter is found, assume it's a side effect import. + * If factory is an Identifier, derive import identifier names from the import module name for later usage + * b) If dependencies is an Identifier, abort with an error. +*/ +function collectImports( + moduleDeclaration: ModuleDeclaration, + nodeFactory: ts.NodeFactory, +): {imports: ts.ImportDeclaration[], identifiers: ts.Identifier[]} { + const imports: ts.ImportDeclaration[] = []; + const identifiers: ts.Identifier[] = []; + if (!moduleDeclaration.dependencies) { + // No dependencies declared + return {imports, identifiers}; + } + + let factoryParams: ts.Identifier[] | undefined; + let factoryRequiresCallWrapper = false; + if (moduleDeclaration.factory) { + if (ts.isFunctionExpression(moduleDeclaration.factory) || + ts.isArrowFunction(moduleDeclaration.factory) || + ts.isFunctionDeclaration(moduleDeclaration.factory)) { + // Extract parameter names + factoryParams = moduleDeclaration.factory.parameters.map((param) => { + if (!ts.isIdentifier(param.name)) { + // Indicates destructuring in factory signature. This is not (yet?) supported + throw new UnsupportedModuleError( + `Unexpected parameter type ${ts.SyntaxKind[param.kind]} ` + + `at ${toPosStr(param)}`); + } + return param.name; + }); + } else if (ts.isIdentifier(moduleDeclaration.factory)) { + factoryRequiresCallWrapper = true; + } + } + + if (ts.isIdentifier(moduleDeclaration.dependencies)) { + throw new UnsupportedModuleError(`Unable to determine dependencies for module. Can't parse variable at ` + + `${toPosStr(moduleDeclaration.dependencies)}`); + } + + // Create import statements based on factory parameters + moduleDeclaration.dependencies.elements.forEach((dep, i) => { + // Create import statements + let moduleSpecifier: ts.StringLiteral; + if (!ts.isStringLiteralLike(dep)) { + log.verbose(`Skipping non-string dependency entry of type ${ts.SyntaxKind[dep.kind]} at ` + + toPosStr(dep)); + return; + } + if (ts.isNoSubstitutionTemplateLiteral(dep)) { + moduleSpecifier = nodeFactory.createStringLiteral(dep.text); + // Set pos to the original position to preserve source mapping capability + // (cast type to avoid TS error due to modifying a read only property) + (moduleSpecifier.pos as ts.Node["pos"]) = dep.pos; + } else { + moduleSpecifier = dep; + } + let identifier: ts.Identifier | undefined; + if (factoryRequiresCallWrapper) { + // Generate variable name based on import module + // Later this variable will be used to call the factory function + identifier = nodeFactory.createUniqueName(dep.text.replace(/[^a-zA-Z0-9]/g, "_")); + } else if (factoryParams && factoryParams[i]) { + // Use factory parameter identifier as import identifier + identifier = factoryParams[i]; + } // else: Side effect imports. No identifier needed + + let importClause; + if (identifier) { + identifiers.push(identifier); + importClause = nodeFactory.createImportClause(false, identifier, undefined); + } + + imports.push(nodeFactory.createImportDeclaration( + undefined, + importClause, + moduleSpecifier + )); + }); + pruneNode(moduleDeclaration.dependencies); + + return {imports, identifiers}; +} + +/** Convert factory to module body: + * a) If factory is a FunctionExpression or ArrowFunctionExpression, extract the body and create default + * export for it's return value + * b) If factory is any other kind of _value_, use it directly + * c) If factory is an Identifier, create a function and call it with all dependencies + * + * Then create default export: + * a) If factory body contains a single return statement, use its argument for the default export + * b) If factory body contains multiple return statements, wrap the whole body + * in a function and use that for the default export + */ +function getModuleBody( + moduleDeclaration: ModuleDeclaration, + sourceFile: ts.SourceFile, + nodeFactory: ts.NodeFactory, + importIdentifiers: ts.Identifier[], +): ts.Statement[] { + if (!moduleDeclaration.factory) { + return []; + } + let body: ts.Statement[]; + if ((ts.isFunctionExpression(moduleDeclaration.factory) || + ts.isArrowFunction(moduleDeclaration.factory) || + ts.isFunctionDeclaration(moduleDeclaration.factory))) { + + if (!moduleDeclaration.factory.body) { + // Empty function body, no export + body = []; + } else if (ts.isBlock(moduleDeclaration.factory.body)) { + const factoryBody = moduleDeclaration.factory.body.statements; + /* Convert factory to module body: + a) If body contains a single return statement, add all nodes to body but wrap + the return statement's argument with a default export + b) If body contains multiple return statements, wrap body in an iife + use that for the body, wrapped in a default export declaration + */ + + const returnStatements = collectReturnStatementsInScope(moduleDeclaration.factory, 2); + if (returnStatements.length > 1) { + log.verbose(`Multiple return statements found in factory at ${toPosStr(moduleDeclaration.factory)}`); + let factoryCall: ts.CallExpression; + if (ts.isFunctionExpression(moduleDeclaration.factory) || + ts.isArrowFunction(moduleDeclaration.factory)) { + // Wrap factory in iife + factoryCall = nodeFactory.createCallExpression( + moduleDeclaration.factory, undefined, importIdentifiers); + } else if (ts.isFunctionDeclaration(moduleDeclaration.factory) && moduleDeclaration.factory.name) { + // Call the declaration + factoryCall = nodeFactory.createCallExpression( + moduleDeclaration.factory.name, undefined, importIdentifiers); + } else { + throw new UnsupportedModuleError( + `Unable to call factory of type ${ts.SyntaxKind[moduleDeclaration.factory.kind]} at ` + + toPosStr(moduleDeclaration.factory)); + } + body = [createDefaultExport(nodeFactory, factoryCall)]; + } else { + body = []; + // One return statement in scope + for (const node of factoryBody) { + if (ts.isReturnStatement(node) && node.expression) { + if (ts.isCallExpression(node.expression)) { + try { + const classDeclaration = rewriteExtendCall(nodeFactory, + node.expression, [ + nodeFactory.createToken(ts.SyntaxKind.ExportKeyword), + nodeFactory.createToken(ts.SyntaxKind.DefaultKeyword) + ]); + body.push(classDeclaration); + } catch(err) { + if (err instanceof UnsupportedExtendCall) { + log.verbose(`Failed to transform extend call: ${err.message}`); + body.push(createDefaultExport(nodeFactory, node.expression)); + } else { + throw err; + } + } + } else { + body.push(createDefaultExport(nodeFactory, node.expression)); + // body.push(factory.createExportAssignment(undefined, undefined, + // node.expression)); + } + } else if (ts.isExpressionStatement(node) && ts.isStringLiteral(node.expression) && + node.expression.text === "use strict") { + // Ignore "use strict" directive + continue; + } else { + body.push(node); + } + } + + pruneNode(moduleDeclaration.factory); + } + } else if (ts.isCallExpression(moduleDeclaration.factory.body)) { + // Arrow function with expression body + try { + const classDeclaration = rewriteExtendCall(nodeFactory, + moduleDeclaration.factory.body, [ + nodeFactory.createToken(ts.SyntaxKind.ExportKeyword), + nodeFactory.createToken(ts.SyntaxKind.DefaultKeyword) + ]); + body = [classDeclaration]; + } catch(err) { + if (err instanceof UnsupportedExtendCall) { + log.verbose(`Failed to transform extend call: ${err.message}`); + body = [createDefaultExport(nodeFactory, moduleDeclaration.factory.body)]; + } else { + throw err; + } + } + } else { + // Export expression directly + body = [createDefaultExport(nodeFactory, moduleDeclaration.factory.body)]; + } + } else if (ts.isClassDeclaration(moduleDeclaration.factory) || + ts.isLiteralExpression(moduleDeclaration.factory) || + ts.isArrayLiteralExpression(moduleDeclaration.factory) || + ts.isObjectLiteralExpression(moduleDeclaration.factory) || + ts.isPropertyAccessExpression(moduleDeclaration.factory)) { + // Use factory directly + body = [createDefaultExport(nodeFactory, moduleDeclaration.factory)]; + } else { // Identifier + throw new Error(`FIXME: Unsupported factory type ${ts.SyntaxKind[moduleDeclaration.factory.kind]} at ` + + toPosStr(moduleDeclaration.factory)); + } + return body; +} + +/** + * Collect all return statements in the provided node's function scope + */ +function collectReturnStatementsInScope(node: ts.Node, maxCount?: number): ts.ReturnStatement[] { + const returnStatements: ts.ReturnStatement[] = []; + function visitNode(node: ts.Node) { + switch(node.kind) { + case SyntaxKind.ReturnStatement: + returnStatements.push(node as ts.ReturnStatement); + return; + + // Do not traverse into nodes that declare a new function scope + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessor: + return; + } + if (maxCount && returnStatements.length >= maxCount) { + return; + } + ts.forEachChild(node, visitNode); + } + + ts.forEachChild(node, visitNode); + return returnStatements; +} + +function createDefaultExport(factory: ts.NodeFactory, node: ts.Node): ts.Statement { + if (ts.isLiteralExpression(node)) { + // Use factory directly + return factory.createExportAssignment(undefined, undefined, node); + } + const exportModifiers = [ + factory.createToken(ts.SyntaxKind.ExportKeyword), + factory.createToken(ts.SyntaxKind.DefaultKeyword) + ]; + switch(node.kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + return factory.createExportAssignment(undefined, undefined, node as ts.Expression); + case SyntaxKind.ClassDeclaration: + return factory.updateClassDeclaration( + (node as ts.ClassDeclaration), + exportModifiers, + (node as ts.ClassDeclaration).name, + (node as ts.ClassDeclaration).typeParameters, + (node as ts.ClassDeclaration).heritageClauses, + (node as ts.ClassDeclaration).members); + case SyntaxKind.FunctionDeclaration: + return factory.updateFunctionDeclaration( + (node as ts.FunctionDeclaration), + exportModifiers, + (node as ts.FunctionDeclaration).asteriskToken, + (node as ts.FunctionDeclaration).name, + (node as ts.FunctionDeclaration).typeParameters, + (node as ts.FunctionDeclaration).parameters, + (node as ts.FunctionDeclaration).type, + (node as ts.FunctionDeclaration).body); + case SyntaxKind.FunctionExpression: + return factory.createFunctionDeclaration( + exportModifiers, + (node as ts.FunctionExpression).asteriskToken, + (node as ts.FunctionExpression).name, + (node as ts.FunctionExpression).typeParameters, + (node as ts.FunctionExpression).parameters, + (node as ts.FunctionExpression).type, + (node as ts.FunctionExpression).body); + default: + throw new UnsupportedModuleError( + `Unable to create default export assignment for node of type ${SyntaxKind[node.kind]} at ` + + toPosStr(node)); + } +} diff --git a/src/detectors/transpilers/amd/parseModuleDeclaration.ts b/src/detectors/transpilers/amd/parseModuleDeclaration.ts new file mode 100644 index 000000000..d9be77db1 --- /dev/null +++ b/src/detectors/transpilers/amd/parseModuleDeclaration.ts @@ -0,0 +1,235 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import {UnsupportedModuleError} from "./util.js"; +const log = getLogger("transpilers:amd:parseModuleDeclaration"); + +const {SyntaxKind} = ts; + +export interface ModuleDeclaration { + moduleName?: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral, + dependencies?: ts.ArrayLiteralExpression, + factory: DefineCallArgument, + export?: ts.BooleanLiteral, +} + +/** + * For a given array of arguments, try to match them to the parameters of the sap.ui.define and sap.ui.predefine + * signatures + */ +export default function parseModuleDeclaration( + args: ts.CallExpression["arguments"], checker: ts.TypeChecker +): ModuleDeclaration { + /* + Signature: sap.ui.define(sModuleName?, aDependencies?, vFactory, bExport?) + * sModuleName can be omitted, or is string Literal + * aDependencies can be omitted, or is an ArrayExpression (containing string Literals) + * vFactory must be provided and can be anything (typically an (Arrow-)FunctionExpression or an ObjectExpression) + * bExport can be omitted, or is a boolean Literal + + Each arguments can also be an Identifier. Whenever an Identifier is used, try to resolve it to a concrete type + before attempting to match it to a parameter. If it can't be resolved, an UnsupportedModuleError is thrown. + + Similarly, each argument can also be a CallExpression, in which case we would have to try and resolve its + return type, which is currently out-of-scope. + + Signature: sap.ui.predefine(sModuleName, aDependencies?, vFactory, bExport?) + * sModuleName is required + */ + + if (args.length > 4) { + throw new UnsupportedModuleError(`Unexpected number of arguments (${args.length}) in sap.ui.define call`); + } + const resolvedArgs = args.map((arg): ts.Expression | ts.Declaration => { + if (ts.isIdentifier(arg)) { + // Try and resolve the identifier to a more concrete node + const sym = checker.getSymbolAtLocation(arg); + if (sym?.declarations) { + for (const decl of sym.declarations) { + if (ts.isVariableDeclaration(decl)) { + if (decl.initializer) { + return decl.initializer; + } + } else if (ts.isParameter(decl)) { + // Check for iife + if (decl?.parent.kind === SyntaxKind.FunctionExpression && + decl.parent.parent?.kind === SyntaxKind.ParenthesizedExpression && + decl.parent.parent.parent?.kind === SyntaxKind.CallExpression) { + log.verbose(`Found iife`); + const funcExp = decl.parent; + const callExp = decl.parent.parent.parent as ts.CallExpression; + // Determine parameter position + const paramIdx = funcExp.parameters.indexOf(decl); + if (paramIdx === -1) { + throw new Error(`Failed to determine parameter index for iife`); + } + return callExp.arguments[paramIdx]; + } // Else: It is's not an iife, we can't resolve the argument value + } else { + return decl; + } + } + } + } + return arg; + }); + + return _matchArgumentsToParameters(assertSupportedTypes(resolvedArgs)); +} + +// Keep this type in sync with the "assertSupportedTypes" function +export type DefineCallArgument = ts.StringLiteral |ts.NoSubstitutionTemplateLiteral | ts.NumericLiteral | + ts.ArrayLiteralExpression | ts.BooleanLiteral | ts.PropertyAccessExpression | + ts.ObjectLiteralExpression | ts.ArrowFunction | ts.FunctionExpression | + ts.FunctionDeclaration | ts.ClassDeclaration | ts.NoSubstitutionTemplateLiteral; + +function assertSupportedTypes(args: (ts.Expression | ts.Declaration)[]): DefineCallArgument[] { + args.forEach((arg, idx) => { + // We only support a certain set of types. Abort if we encounter anything else + switch (arg.kind) { + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.PropertyAccessExpression: + return; + default: + throw new UnsupportedModuleError( + `Unsupported type for argument in sap.ui.define call at index ${idx}: ${SyntaxKind[arg.kind]}`); + } + }); + return args as unknown as DefineCallArgument[]; +} + +const enum Param { + ModuleName = 0, + Dependencies = 1, + Factory = 2, + Export = 3, +} + +export function _matchArgumentsToParameters(args: DefineCallArgument[]): ModuleDeclaration { + // Create a grid of possible matches between the provided arguments and the expected parameters + const matchGrid = []; + + if (args[0]) { + matchGrid.push(permute(args[0], Param.ModuleName)); + } + if (args[1]) { + matchGrid.push(permute(args[1], Param.Dependencies)); + } + if (args[2]) { + matchGrid.push(permute(args[2], Param.Factory)); + } + if (args[3]) { + matchGrid.push(permute(args[3], Param.Export)); + } + + // This results in a two dimensional array containing values + // for all allowed permutations of the provided arguments + // Now we calculate the best match + for (let i = 0; i < matchGrid.length; i++) { + for (let j = 0; j < matchGrid[i].length; j++) { + if (matchGrid[i][j]) { + // Match + if (i > 0 && j > 0) { + matchGrid[i][j] = matchGrid[i - 1][j - 1] + 1; + } else { + matchGrid[i][j] = 1; + } + } else { + // No match + let prevI = 0, prevJ = 0; + if (i > 0) { + prevI = matchGrid[i - 1][j]; + } + if (j > 0) { + prevJ = matchGrid[i][j - 1]; + } + matchGrid[i][j] = Math.max(prevI, prevJ); + } + } + } + /* Visualization for the resulting "matchGrid": + // Case 1 + Input (3 arguments): ArrayLiteralExpression, FunctionExpression, TrueKeyword + ┌─────────────────┐ + │arg\param│ 0 │ 1 │ 2 │ 3 │ + ├─────────────────┤ + │ 0 │ 0 │ 1 │ 1 │ 1 │ + │ 1 │ 0 │ 1 │ 2 │ 2 │ + │ 2 │ 0 │ 1 │ 2 │ 3 │ + └─────────────────┘ + Solution: + arg #0 => dependencies, arg #1 => factory, arg #2 => export flag + (=> moduleName has been omitted) + + Legend for the for-loop below: + arg = i + param = j + */ + + // Find the highest matches and assign parameters accordingly + const result: Partial = {}; + let highestMatch = 0; + + for (let i = 0; i < matchGrid.length; i++) { + for (let j = 0; j <= Param.Export; j++) { + if (matchGrid[i][j] > highestMatch) { + highestMatch = matchGrid[i][j]; + if (j === Param.ModuleName) { + result.moduleName = args[i] as ModuleDeclaration["moduleName"]; + } else if (j === Param.Dependencies) { + result.dependencies = args[i] as ModuleDeclaration["dependencies"]; + } else if (j === Param.Factory) { + result.factory = args[i] as ModuleDeclaration["factory"]; + } else if (j === Param.Export) { + result.export = args[i] as ModuleDeclaration["export"]; + } + } + } + } + return result as ModuleDeclaration; +} + +// Compute which parameters the given argument could match with based on it's type +// For example an ArrayLiteralExpression could only be the dependencies or the factory parameter +function permute(arg: DefineCallArgument, startAt: Param): number[] { + const perm = Array(4).fill(0); + + if (startAt <= Param.ModuleName && canBeModuleName(arg)) { + perm[0] = 1; + } + + if (startAt <= Param.Dependencies && canBeDependencies(arg)) { + perm[1] = 1; + } + if(startAt <= Param.Factory && canBeFactory(arg)) { + perm[2] = 1; + } + + if(startAt <= Param.Export && canBeExport(arg)) { + perm[3] = 1; + } + return perm; +} + +function canBeModuleName(arg: DefineCallArgument) { + return arg.kind === SyntaxKind.StringLiteral || + arg.kind === SyntaxKind.NoSubstitutionTemplateLiteral; +} +function canBeDependencies(arg: DefineCallArgument) { + return arg.kind === SyntaxKind.ArrayLiteralExpression; +} +function canBeFactory(_arg: DefineCallArgument) { + return true; // All supported types can be used for factory +} +function canBeExport(arg: DefineCallArgument) { + return arg.kind === SyntaxKind.TrueKeyword || arg.kind === SyntaxKind.FalseKeyword; +} diff --git a/src/detectors/transpilers/amd/parseRequire.ts b/src/detectors/transpilers/amd/parseRequire.ts new file mode 100644 index 000000000..2f2f1e768 --- /dev/null +++ b/src/detectors/transpilers/amd/parseRequire.ts @@ -0,0 +1,153 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import {UnsupportedModuleError, toPosStr} from "./util.js"; +const log = getLogger("amd:parseRequire"); + +const {SyntaxKind} = ts; + +export interface ProbingRequireExpression { + async: false, + dependency: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral, +} +export interface RequireExpression { + async: true, + dependencies: ts.ArrayLiteralExpression, + callback?: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration, + errback?: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration +} + +/** + * For a given array of arguments, try to match them to the parameters of the sap.ui.define and sap.ui.predefine + * signatures + */ +export default function parseRequire( + args: ts.CallExpression["arguments"], checker: ts.TypeChecker +): ProbingRequireExpression | RequireExpression { + /* + Signature: sap.ui.require(vDependencies, fnCallback?, fnErrback?) + * vDependencies must be provided and can be a string literal or an array of string literals + * fnCallback can be omitted, or is an (Arrow-)FunctionExpression receiving the resolved dependencies + * fnErrback can be omitted, or is an (Arrow-)FunctionExpression receiving the error + + If vDependencies is a string literal, synchronous probing for a potentially already loaded module is assumed. + In that case the return value is either the module content or undefined (in case the module is not available). + => Always generate a type annotation in this case + + If vDependencies is an array, the return value is always undefined. + + Each arguments can also be an Identifier. Whenever an Identifier is used, try to resolve it to a concrete type + before attempting to match it to a parameter. If it can't be resolved, an UnsupportedModuleError is thrown. + + Similarly, each argument can also be a CallExpression, in which case we would have to try and resolve its + return type, which is currently out-of-scope. + */ + + if (args.length < 1 || args.length > 3) { + throw new UnsupportedModuleError(`Unexpected number of arguments (${args.length}) in sap.ui.require call`); + } + + // TODO: Create reuse between this and parseModuleDeclaration + const resolvedArgs = args.map((arg): ts.Expression | ts.Declaration => { + if (ts.isIdentifier(arg)) { + // Try and resolve the identifier to a more concrete node + const sym = checker.getSymbolAtLocation(arg); + if (sym && sym.declarations) { + for (const decl of sym.declarations) { + if (ts.isVariableDeclaration(decl)) { + if (decl.initializer) { + return decl.initializer; + } + } else if (ts.isParameter(decl)) { + // Check for iife + if (decl?.parent.kind === SyntaxKind.FunctionExpression && + decl.parent.parent?.kind === SyntaxKind.ParenthesizedExpression && + decl.parent.parent.parent?.kind === SyntaxKind.CallExpression) { + log.verbose(`Found iife`); + const funcExp = decl.parent; + const callExp = decl.parent.parent.parent as ts.CallExpression; + // Determine parameter position + const paramIdx = funcExp.parameters.indexOf(decl); + if (paramIdx === -1) { + throw new Error(`Failed to determine parameter index for iife`); + } + return callExp.arguments[paramIdx]; + } // Else: It is's not an iife, we can't resolve the argument value + } else { + return decl; + } + } + } + return arg; + } else { + return arg; + } + }); + + return _matchArgumentsToParameters(assertSupportedTypes(resolvedArgs)); +} + +// Keep this type in sync with the "assertSupportedTypes" function +export type RequireCallArgument = ts.StringLiteral | ts.NoSubstitutionTemplateLiteral | ts.ArrayLiteralExpression | + ts.ArrowFunction | ts.FunctionExpression | + ts.FunctionDeclaration; + +function assertSupportedTypes(args: (ts.Expression | ts.Declaration)[]): RequireCallArgument[] { + args.forEach((arg, idx) => { + // We only support a certain set of types. Abort if we encounter anything else + switch (arg.kind) { + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.PropertyAccessExpression: + return; + default: + throw new UnsupportedModuleError( + `Unsupported type for argument in sap.ui.define call at index ${idx}: ${SyntaxKind[arg.kind]}`); + } + }); + return args as unknown as RequireCallArgument[]; +} + +function _matchArgumentsToParameters(args: RequireCallArgument[]): ProbingRequireExpression | RequireExpression { + const [dependencies, callback, errback] = args; + + if (ts.isArrayLiteralExpression(dependencies)) { + if (callback && !(ts.isFunctionExpression(callback) || + ts.isArrowFunction(callback) || + ts.isFunctionDeclaration(callback))) { + throw new UnsupportedModuleError( + `Expected second argument of sap.ui.require call to be a function but got ` + + `${ts.SyntaxKind[callback.kind]} at ${toPosStr(callback)}`); + } + if (errback && !(ts.isFunctionExpression(errback) || + ts.isArrowFunction(errback) || + ts.isFunctionDeclaration(errback))) { + throw new UnsupportedModuleError( + `Expected second argument of sap.ui.require call to be a function but got ` + + `${ts.SyntaxKind[errback.kind]} at ${toPosStr(errback)}`); + } + return { + async: true, + dependencies, + callback, + errback, + }; + } else if (ts.isStringLiteralLike(dependencies)) { + return { + async: false, + dependency: dependencies, + }; + } else { + throw new UnsupportedModuleError( + `Expected first argument of sap.ui.require call to be a string literal or array expression but got ` + + `${ts.SyntaxKind[dependencies.kind]} at ${toPosStr(dependencies)}`); + } +} diff --git a/src/detectors/transpilers/amd/pruneNode.ts b/src/detectors/transpilers/amd/pruneNode.ts new file mode 100644 index 000000000..eadc6b80b --- /dev/null +++ b/src/detectors/transpilers/amd/pruneNode.ts @@ -0,0 +1,328 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import {toPosStr, UnsupportedModuleError} from "./util.js"; +const {SyntaxKind} = ts; +const log = getLogger("transpilers:amd:pruneNode"); + +export class UnsafeNodeRemoval extends Error { + constructor(message: string) { + super(message); + this.name = this.constructor.name; + } +} + +/** + * Marks a given node for removal. The node will be removed during a later step in the the transformation process. + * + * If the node's parent would become completely empty after removing the node, the parent is also marked for removal. + * If the node's parent can't exist without the to-be-removed node, the node won't be removed. + * + * This is checked recursively for all parents + */ +export default function(node: ts.Node) { + let nodeToRemove: ts.Node | undefined = node; + try { + while (nodeToRemove) { + // Attempt to prune the node, if the parent can exist without it + if (pruneNode(nodeToRemove)) { + nodeToRemove = nodeToRemove.parent; + } else { + nodeToRemove = undefined; + } + } + } catch(err) { + if ((err instanceof UnsafeNodeRemoval || err instanceof UnsupportedModuleError) && + node !== nodeToRemove) { + // Ignore UnsafeNodeRemoval and UnsupportedModuleError exceptions produced by parent nodes + return; + } + throw err; + } +} + +/** + * Attempt to prune a node, if the parent can exist without it (=> UnsafeNodeRemoval exception) + * + * Returns true if parent can be removed. This way the caller can continue to check the parent's parent, knowing + * that the parent is already safe to be removed. Therefore no check is required at the beginning of this function. + */ +function pruneNode(node: ts.Node): boolean { + log.verbose(`Pruning node ${SyntaxKind[node.kind]}`); + node._remove = true; + try { + const parent = node.parent; + if (isNodeRemovable(parent)) { + // Parent can be removed + log.verbose(`Parent node ${SyntaxKind[parent.kind]} can be removed`); + return true; + } + } catch(err) { + if (err instanceof UnsafeNodeRemoval || err instanceof UnsupportedModuleError) { + // If an UnsafeNodeRemoval or UnsupporedModuleError is detected, revert the removal of the node as + // this would indicate that the parent can't exist without it + node._remove = false; + } + // Re-throw error in any case + throw err; + } + return false; +} + +/** + * Check whether a given node can be marked for removal by checking whether + * relevant child nodes have already been marked for removal. + * + * If removing the given node is not possible, but it is also not possible to keep it with the given + * child nodes marked for removal, an error is thrown. + * + * Note that some nodes can't exist without certain child nodes. Leaving those + * nodes after removing their children will cause errors during later AST processing + */ +function isNodeRemovable(node: ts.Node): boolean { + switch(node.kind) { + case SyntaxKind.SourceFile: + // Never remove the source file + return false; + + // Nodes with only one child + case SyntaxKind.Identifier: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.ReturnStatement: + case SyntaxKind.AwaitExpression: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.Parameter: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + // These nodes can only have one child + // So if the child is removed, the parent must be removed as well + return true; + + // Nodes with multiple children + case SyntaxKind.FunctionExpression: + return isRemovableFunctionExpression(node as ts.FunctionExpression); + case SyntaxKind.MethodDeclaration: + return isRemovableMethodDeclaration(node as ts.MethodDeclaration); + case SyntaxKind.NewExpression: + return isRemovableNewExpression(node as ts.NewExpression); + case SyntaxKind.ArrowFunction: + return isRemovableArrowFunction(node as ts.ArrowFunction); + case SyntaxKind.IfStatement: + return isRemovableIfStatement(node as ts.IfStatement); + case SyntaxKind.BinaryExpression: + return isRemovableBinaryExpression(node as ts.BinaryExpression); + case SyntaxKind.ConditionalExpression: + return isRemovableConditionalExpression(node as ts.ConditionalExpression); + case SyntaxKind.ForStatement: + return isRemovableForStatement(node as ts.ForStatement); + case SyntaxKind.WhileStatement: + return isRemovableWhileStatement(node as ts.WhileStatement); + case SyntaxKind.DoStatement: + return isRemovableDoStatement(node as ts.DoStatement); + case SyntaxKind.PropertyAccessExpression: + return isRemovablePropertyAccessExpression(node as ts.PropertyAccessExpression); + case SyntaxKind.ElementAccessExpression: + return isRemovableElementAccessExpression(node as ts.ElementAccessExpression); + case SyntaxKind.FunctionDeclaration: + return isRemovableFunctionDeclaration(node as ts.FunctionDeclaration); + case SyntaxKind.PropertyAssignment: + return isRemovablePropertyAssignment(node as ts.PropertyAssignment); + case SyntaxKind.PropertyDeclaration: + return isRemovablePropertyDeclaration(node as ts.PropertyDeclaration); + case SyntaxKind.YieldExpression: + return isRemovableYieldExpression(node as ts.YieldExpression); + case SyntaxKind.ArrayLiteralExpression: + return isRemovableArrayLiteralExpression(node as ts.ArrayLiteralExpression); + + case SyntaxKind.VariableDeclarationList: + return isRemovableVariableDeclarationList(node as ts.VariableDeclarationList); + case SyntaxKind.Block: + return isRemovableBlock(node as ts.Block); + case SyntaxKind.ObjectLiteralExpression: + return isRemovableObjectLiteralExpression(node as ts.ObjectLiteralExpression); + case SyntaxKind.CallExpression: + return isRemovableCallExpression(node as ts.CallExpression); + case SyntaxKind.ClassDeclaration: + return isRemovableClassDeclaration(node as ts.ClassDeclaration); + default: + throw new UnsupportedModuleError( + `Unsupported parent node type for prune operation: ${SyntaxKind[node.kind]} at ` + + `${toPosStr(node)}`); + } +} + +function isNotMarkedForRemoval(node: ts.Node) { + return !node._remove; +} + +function hasAllNodesMarkedForRemoval(nodes: ts.NodeArray) { + return !nodes.some(isNotMarkedForRemoval); +} + +function isRemovableFunctionExpression(node: ts.FunctionExpression): boolean { + // If the body is marked for removal, remove the whole function + // Even if parameters are not marked for removal + return !!node.body?._remove; +} + +function isRemovableMethodDeclaration(node: ts.MethodDeclaration): boolean { + // If the body is marked for removal, remove the whole function + // Even if parameters are not marked for removal + return !!node.body?._remove; +} + +function isRemovableNewExpression(node: ts.NewExpression): boolean { + return !!node.expression._remove && (!node.arguments|| hasAllNodesMarkedForRemoval(node.arguments)); +} + +function isRemovableArrowFunction(node: ts.ArrowFunction): boolean { + return !!node.body._remove; +} + +function isRemovableIfStatement(node: ts.IfStatement): boolean { + if (node.thenStatement._remove && (!node.elseStatement || node.elseStatement?._remove)) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove IfStatement with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovableBinaryExpression(node: ts.BinaryExpression): boolean { + // Both sides of the binary expression are marked for removal => Remove the whole expression + if(node.left._remove && node.right._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove BinaryExpression with only one side marked for removal at ${toPosStr(node)}`); +} + +function isRemovableConditionalExpression(node: ts.ConditionalExpression): boolean { + if (node.condition._remove && node.whenTrue._remove && node.whenFalse._remove) { + // All parts of the conditional expression are marked for removal => Remove the whole expression + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove ConditionalExpression with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovableForStatement( + node: ts.ForStatement +): boolean { + if (node.statement._remove && (!node.initializer || node.initializer._remove) && + (!node.condition || node.condition._remove) && (!node.incrementor || node.incrementor._remove)) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove ForStatement with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovableWhileStatement( + node: ts.WhileStatement +): boolean { + if (node.statement._remove && node.expression._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove WhileStatment with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovableDoStatement( + node: ts.DoStatement +): boolean { + if (node.statement._remove && node.expression._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove DoStatement with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovablePropertyAccessExpression( + node: ts.PropertyAccessExpression +): boolean { + + if (node.name._remove && node.expression._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove PropertyAccessExpression with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovableElementAccessExpression( + node: ts.ElementAccessExpression +): boolean { + if (node.argumentExpression._remove && node.expression._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove ElementAccessExpression with only one part marked for removal at ${toPosStr(node)}`); +} + +function isRemovableFunctionDeclaration( + node: ts.FunctionDeclaration +): boolean { + // If the body is marked for removal, remove the whole function + return !!node.body?._remove; +} + +function isRemovablePropertyAssignment( + node: ts.PropertyAssignment +): boolean { + // If the name is marked for removal, remove the whole property assignment + if (node.name?._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove PropertyAssignment with only the initializer marked for removal at ${toPosStr(node)}`); +} + +function isRemovablePropertyDeclaration( + node: ts.PropertyDeclaration +): boolean { + // If the name is marked for removal, remove the whole property declaration + if (node.name?._remove) { + return true; + } + throw new UnsafeNodeRemoval( + `Cannot remove PropertyDeclaration with only the initializer marked for removal at ${toPosStr(node)}`); +} + +function isRemovableYieldExpression( + node: ts.YieldExpression +): boolean { + // If the expression is marked for removal, remove the whole yield expression + return !!node.expression?._remove; +} + +function isRemovableArrayLiteralExpression( + node: ts.ArrayLiteralExpression +): boolean { + // All elements are marked for removal => Remove the whole array literal + return hasAllNodesMarkedForRemoval(node.elements); +} + +function isRemovableVariableDeclarationList(node: ts.VariableDeclarationList): boolean { + // All declarations are marked for removal => Remove the whole list + return hasAllNodesMarkedForRemoval(node.declarations); +} + +function isRemovableBlock(node: ts.Block): boolean { + // All statements in the block are marked for removal => Remove the whole block + return hasAllNodesMarkedForRemoval(node.statements); +} + +function isRemovableObjectLiteralExpression(node: ts.ObjectLiteralExpression): boolean { + // All properties are marked for removal => Remove the whole object literal + return hasAllNodesMarkedForRemoval(node.properties); +} + +function isRemovableCallExpression(node: ts.CallExpression): boolean { + // All arguments are marked for removal => Remove the whole call expression + return !!node.expression._remove && hasAllNodesMarkedForRemoval(node.arguments); +} + +function isRemovableClassDeclaration(node: ts.ClassDeclaration): boolean { + // If the body is marked for removal, remove the whole class + return hasAllNodesMarkedForRemoval(node.members); +} diff --git a/src/detectors/transpilers/amd/replaceNodeInParent.ts b/src/detectors/transpilers/amd/replaceNodeInParent.ts new file mode 100644 index 000000000..f1547d6fd --- /dev/null +++ b/src/detectors/transpilers/amd/replaceNodeInParent.ts @@ -0,0 +1,764 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +const {SyntaxKind} = ts; +import {toPosStr, UnsupportedModuleError} from "./util.js"; +const log = getLogger("transpilers:amd:replaceNodeInParent"); + +export interface NodeReplacement { + original: ts.Node, + substitute: ts.Node, +} + +/** + * Replaces a node in its parent with another node + */ +export default function( + parent: ts.Node, replacement: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.Node { + const {original, substitute} = replacement; + log.verbose( + `Replacing child of ${ts.SyntaxKind[parent.kind]}\n` + + ` Old: ${ts.SyntaxKind[original.kind]}\n` + + ` New: ${ts.SyntaxKind[substitute.kind]}`); + + switch(parent.kind) { + case SyntaxKind.ExpressionStatement: + return replaceInExpressionStatement(parent as ts.ExpressionStatement, replacement, nodeFactory); + case SyntaxKind.ParenthesizedExpression: + return replaceInParenthesizedExpression(parent as ts.ParenthesizedExpression, replacement, nodeFactory); + case SyntaxKind.CallExpression: + return replaceInCallExpression(parent as ts.CallExpression, replacement, nodeFactory); + case SyntaxKind.NewExpression: + return replaceInNewExpression(parent as ts.NewExpression, replacement, nodeFactory); + case SyntaxKind.BinaryExpression: + return replaceInBinaryExpression(parent as ts.BinaryExpression, replacement, nodeFactory); + case SyntaxKind.ConditionalExpression: + return replaceInConditionalExpression(parent as ts.ConditionalExpression, replacement, nodeFactory); + case SyntaxKind.PrefixUnaryExpression: + return replaceInPrefixUnaryExpression(parent as ts.PrefixUnaryExpression, replacement, nodeFactory); + case SyntaxKind.PostfixUnaryExpression: + return replaceInPostfixUnaryExpression(parent as ts.PostfixUnaryExpression, replacement, nodeFactory); + case SyntaxKind.YieldExpression: + return replaceInYieldExpression(parent as ts.YieldExpression, replacement, nodeFactory); + case SyntaxKind.AwaitExpression: + return replaceInAwaitExpression(parent as ts.AwaitExpression, replacement, nodeFactory); + case SyntaxKind.VariableStatement: + return replaceInVariableStatement(parent as ts.VariableStatement, replacement, nodeFactory); + case SyntaxKind.VariableDeclaration: + return replaceInVariableDeclaration(parent as ts.VariableDeclaration, replacement, nodeFactory); + case SyntaxKind.VariableDeclarationList: + return replaceInVariableDeclarationList(parent as ts.VariableDeclarationList, replacement, nodeFactory); + case SyntaxKind.PropertyAssignment: + return replaceInPropertyAssignment(parent as ts.PropertyAssignment, replacement, nodeFactory); + case SyntaxKind.PropertyDeclaration: + return replaceInPropertyDeclaration(parent as ts.PropertyDeclaration, replacement, nodeFactory); + case SyntaxKind.IfStatement: + return replaceInIfStatement(parent as ts.IfStatement, replacement, nodeFactory); + case SyntaxKind.WhileStatement: + return replaceInWhileStatement(parent as ts.WhileStatement, replacement, nodeFactory); + case SyntaxKind.DoStatement: + return replaceInDoStatement(parent as ts.DoStatement, replacement, nodeFactory); + case SyntaxKind.ForStatement: + return replaceInForStatement(parent as ts.ForStatement, replacement, nodeFactory); + case SyntaxKind.ReturnStatement: + return replaceInReturnStatement(parent as ts.ReturnStatement, replacement, nodeFactory); + case SyntaxKind.ArrayLiteralExpression: + return replaceInArrayLiteralExpression(parent as ts.ArrayLiteralExpression, replacement, nodeFactory); + case SyntaxKind.ObjectLiteralExpression: + return replaceInObjectLiteralExpression(parent as ts.ObjectLiteralExpression, replacement, nodeFactory); + case SyntaxKind.PropertyAccessExpression: + return replaceInPropertyAccessExpression(parent as ts.PropertyAccessExpression, replacement, nodeFactory); + case SyntaxKind.ElementAccessExpression: + return replaceInElementAccessExpression(parent as ts.ElementAccessExpression, replacement, nodeFactory); + case SyntaxKind.Block: + return replaceInBlock(parent as ts.Block, replacement, nodeFactory); + case SyntaxKind.ArrowFunction: + return replaceInArrowFunction(parent as ts.ArrowFunction, replacement, nodeFactory); + case SyntaxKind.FunctionExpression: + return replaceInFunctionExpression(parent as ts.FunctionExpression, replacement, nodeFactory); + case SyntaxKind.FunctionDeclaration: + return replaceInFunctionDeclaration(parent as ts.FunctionDeclaration, replacement, nodeFactory); + case SyntaxKind.MethodDeclaration: + return replaceInMethodDeclaration(parent as ts.MethodDeclaration, replacement, nodeFactory); + case SyntaxKind.ClassDeclaration: + return replaceInClassDeclaration(parent as ts.ClassDeclaration, replacement, nodeFactory); + case SyntaxKind.ComputedPropertyName: + return replaceInComputedPropertyName(parent as ts.ComputedPropertyName, replacement, nodeFactory); + case SyntaxKind.Parameter: + return replaceInParameterDeclaration(parent as ts.ParameterDeclaration, replacement, nodeFactory); + case SyntaxKind.SourceFile: + return replaceInSourceFile(parent as ts.SourceFile, replacement, nodeFactory); + default: + throw new UnsupportedModuleError( + `Unsupported parent node type for replacement operation: ${ts.SyntaxKind[parent.kind]} at ` + + `${toPosStr(parent)}`); + } +} + +function replaceNodeInArray>( + original: ts.Node, substitute: ts.Node, array: T +): T { + // First create a flat copy of the array + const newArray = array.slice(); + + const index = array.indexOf(original); + if (index < 0) { + throw new Error(`Node not found in array`); + } + newArray[index] = substitute; + return newArray as unknown as T; +} + +function replaceInExpressionStatement( + node: ts.ExpressionStatement, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ExpressionStatement { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ExpressionStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateExpressionStatement(node, substitute); +} + +function replaceInParenthesizedExpression( + node: ts.ParenthesizedExpression, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ParenthesizedExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ParenthesizedExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateParenthesizedExpression(node, substitute); +} + +function replaceInCallExpression( + node: ts.CallExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.CallExpression { + if (node.expression === original) { + // Replace expression + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for CallExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateCallExpression( + node, + substitute, + node.typeArguments, + node.arguments); + } else if (node.arguments.includes(original as ts.Expression)) { + // Replace argument + const args = replaceNodeInArray(original, substitute, node.arguments); + return nodeFactory.updateCallExpression( + node, + node.expression, + node.typeArguments, + args); + } else { + throw new UnsupportedModuleError( + `Unexpected child node for CallExpression replacement: ${ts.SyntaxKind[original.kind]} at ` + + `${toPosStr(original)}`); + } +} + +function replaceInNewExpression( + node: ts.NewExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.NewExpression { + if (node.expression === original) { + // Replace expression + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for NewExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateNewExpression( + node, + substitute, + node.typeArguments, + node.arguments); + } else if (node.arguments?.includes(original as ts.Expression)) { + // Replace argument + const args = replaceNodeInArray(original, substitute, node.arguments); + return nodeFactory.updateNewExpression( + node, + node.expression, + node.typeArguments, + args); + } else { + throw new UnsupportedModuleError( + `Unexpected child node for NewExpression replacement: ${ts.SyntaxKind[original.kind]} at ` + + `${toPosStr(original)}`); + } +} + +function replaceInBinaryExpression( + node: ts.BinaryExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.BinaryExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for BinaryExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + if (node.left === original) { + // Replace left + return nodeFactory.updateBinaryExpression( + node, + substitute, + node.operatorToken, + node.right); + } else { // Must be right + // Replace right + return nodeFactory.updateBinaryExpression( + node, + node.left, + node.operatorToken, + substitute); + } +} + +function replaceInConditionalExpression( + node: ts.ConditionalExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ConditionalExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ConditionalExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + if (node.condition === original) { + // Replace condition + return nodeFactory.updateConditionalExpression( + node, + substitute, + node.questionToken, + node.whenTrue, + node.colonToken, + node.whenFalse); + } else if (node.whenTrue === original) { + // Replace whenTrue + return nodeFactory.updateConditionalExpression( + node, + node.condition, + node.questionToken, + substitute, + node.colonToken, + node.whenFalse); + } else { // Must be whenFalse + // Replace whenFalse + return nodeFactory.updateConditionalExpression( + node, + node.condition, + node.questionToken, + node.whenTrue, + node.colonToken, + substitute); + } +} + +function replaceInPrefixUnaryExpression( + node: ts.PrefixUnaryExpression, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.PrefixUnaryExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for PrefixUnaryExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updatePrefixUnaryExpression( + node, + substitute); +} + +function replaceInPostfixUnaryExpression( + node: ts.PostfixUnaryExpression, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.PostfixUnaryExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for PostfixUnaryExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updatePostfixUnaryExpression( + node, + substitute); +} + +function replaceInYieldExpression( + node: ts.YieldExpression, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.YieldExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for YieldExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateYieldExpression( + node, + node.asteriskToken, + substitute); +} + +function replaceInAwaitExpression( + node: ts.AwaitExpression, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.AwaitExpression { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for AwaitExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateAwaitExpression( + node, + substitute); +} + +function replaceInVariableStatement( + node: ts.VariableStatement, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.VariableStatement { + const declarationList = replaceNodeInArray(original, substitute, node.declarationList.declarations); + return nodeFactory.updateVariableStatement( + node, + node.modifiers, + nodeFactory.updateVariableDeclarationList( + node.declarationList, + declarationList)); +} + +function replaceInVariableDeclaration( + node: ts.VariableDeclaration, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.VariableDeclaration { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for VariableDeclaration (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateVariableDeclaration( + node, + node.name, + node.exclamationToken, + node.type, + substitute); +} + +function replaceInVariableDeclarationList( + node: ts.VariableDeclarationList, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.VariableDeclarationList { + const declarations = replaceNodeInArray(original, substitute, node.declarations); + return nodeFactory.updateVariableDeclarationList(node, declarations); +} + +function replaceInPropertyAssignment( + node: ts.PropertyAssignment, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.PropertyAssignment { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for PropertyAssignment (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updatePropertyAssignment( + node, + node.name, + substitute); +} + +function replaceInPropertyDeclaration( + node: ts.PropertyDeclaration, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.PropertyDeclaration { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for PropertyDeclaration (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updatePropertyDeclaration( + node, + node.modifiers, + node.name, + node.questionToken || node.exclamationToken, + node.type, + substitute); +} + +function replaceInIfStatement( + node: ts.IfStatement, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.IfStatement { + if (node.expression === original) { + // Replace expression + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for IfStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateIfStatement( + node, + substitute, + node.thenStatement, + node.elseStatement); + } else if (node.thenStatement === original) { + // Replace statement + if (!ts.isStatement(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for IfStatement (expected Statement): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateIfStatement( + node, + node.expression, + substitute, + node.elseStatement); + } else { // Must be elseStatement + // Replace statement + if (!ts.isStatement(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for IfStatement (expected Statement): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateIfStatement( + node, + node.expression, + node.thenStatement, + substitute); + } +} + +function replaceInWhileStatement( + node: ts.WhileStatement, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.WhileStatement { + if (node.expression === original) { + // Replace expression + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for WhileStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateWhileStatement( + node, + substitute, + node.statement); + } else { // Must be statement + // Replace statement + if (!ts.isStatement(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for WhileStatement (expected Statement): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateWhileStatement( + node, + node.expression, + substitute); + } +} + +function replaceInDoStatement( + node: ts.DoStatement, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.DoStatement { + if (node.statement === original) { + // Replace statement + if (!ts.isStatement(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for DoStatement (expected Statement): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateDoStatement( + node, + substitute, + node.expression); + } else { // Must be expression + // Replace expression + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for DoStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateDoStatement( + node, + node.statement, + substitute); + } +} + +function replaceInForStatement( + node: ts.ForStatement, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ForStatement { + if (node.initializer === original) { + // Replace initializer + if (!ts.isForInitializer(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ForStatement (expected ForInitializer): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateForStatement( + node, + substitute, + node.condition, + node.incrementor, + node.statement); + } else if (node.condition === original) { + // Replace condition + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ForStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateForStatement( + node, + node.initializer, + substitute, + node.incrementor, + node.statement); + } else if (node.incrementor === original) { + // Replace incrementor + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ForStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateForStatement( + node, + node.initializer, + node.condition, + substitute, + node.statement); + } else { // Must be statement + // Replace statement + if (!ts.isStatement(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ForStatement (expected Statement): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateForStatement( + node, + node.initializer, + node.condition, + node.incrementor, + substitute); + } +} + +function replaceInReturnStatement( + node: ts.ReturnStatement, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ReturnStatement { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ReturnStatement (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateReturnStatement(node, substitute); +} + +function replaceInArrayLiteralExpression( + node: ts.ArrayLiteralExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ArrayLiteralExpression { + const elements = replaceNodeInArray(original, substitute, node.elements); + return nodeFactory.updateArrayLiteralExpression(node, elements); +} + +function replaceInObjectLiteralExpression( + node: ts.ObjectLiteralExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ObjectLiteralExpression { + const properties = replaceNodeInArray(original, substitute, node.properties); + return nodeFactory.updateObjectLiteralExpression(node, properties); +} + +function replaceInPropertyAccessExpression( + node: ts.PropertyAccessExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.PropertyAccessExpression { + if (node.name === original) { + // Replace name + if (!ts.isIdentifier(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for PropertyAccessExpression (expected Identifier): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updatePropertyAccessExpression( + node, + node.expression, + substitute); + } else { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for PropertyAccessExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updatePropertyAccessExpression( + node, + substitute, + node.name); + } +} + +function replaceInBlock( + node: ts.Block, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.Block { + const statements = replaceNodeInArray(original, substitute, node.statements); + return nodeFactory.updateBlock(node, statements); +} + +function replaceInElementAccessExpression( + node: ts.ElementAccessExpression, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ElementAccessExpression { + if (node.expression === original) { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ElementAccessExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateElementAccessExpression( + node, + substitute, + node.argumentExpression); + } else { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ElementAccessExpression (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateElementAccessExpression( + node, + node.expression, + substitute); + } +} + +function replaceInArrowFunction( + node: ts.ArrowFunction, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ArrowFunction { + if (!ts.isBlock(substitute) && !ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ArrowFunction (expected Block or Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateArrowFunction( + node, + node.modifiers, + node.typeParameters, + node.parameters, + node.type, + node.equalsGreaterThanToken, + substitute); +} + +function replaceInFunctionExpression( + node: ts.FunctionExpression, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.FunctionExpression { + if (!ts.isBlock(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for FunctionExpression (expected Block): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateFunctionExpression( + node, + node.modifiers, + node.asteriskToken, + node.name, + node.typeParameters, + node.parameters, + node.type, + substitute); +} +function replaceInFunctionDeclaration( + node: ts.FunctionDeclaration, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.FunctionDeclaration { + if (!ts.isBlock(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for FunctionDeclaration (expected Block): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateFunctionDeclaration( + node, + node.modifiers, + node.asteriskToken, + node.name, + node.typeParameters, + node.parameters, + node.type, + substitute); +} + +function replaceInMethodDeclaration( + node: ts.MethodDeclaration, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.MethodDeclaration { + if (!ts.isBlock(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for MethodDeclaration (expected Block): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateMethodDeclaration( + node, + node.modifiers, + node.asteriskToken, + node.name, + node.questionToken, + node.typeParameters, + node.parameters, + node.type, + substitute); +} + +function replaceInClassDeclaration( + node: ts.ClassDeclaration, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ClassDeclaration { + if (node.heritageClauses?.includes(original as ts.HeritageClause)) { + if (!ts.isHeritageClause(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ClassDeclaration (expected HeritageClause): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + const heritageClauses = replaceNodeInArray(original, substitute, node.heritageClauses); + return nodeFactory.updateClassDeclaration( + node, + node.modifiers, + node.name, + node.typeParameters, + heritageClauses, + node.members); + } else if (node.members.includes(original as ts.ClassElement)) { + if (!ts.isClassElement(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ClassDeclaration (expected ClassElement): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + const members = replaceNodeInArray(original, substitute, node.members); + return nodeFactory.updateClassDeclaration( + node, + node.modifiers, + node.name, + node.typeParameters, + node.heritageClauses, + members); + } else { + throw new UnsupportedModuleError( + `Unexpected child node for ClassDeclaration replacement: ${ts.SyntaxKind[original.kind]} at ` + + `${toPosStr(original)}`); + } +} + +function replaceInComputedPropertyName( + node: ts.ComputedPropertyName, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ComputedPropertyName { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ComputedPropertyName (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateComputedPropertyName(node, substitute); +} + +function replaceInParameterDeclaration( + node: ts.ParameterDeclaration, {substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.ParameterDeclaration { + if (!ts.isExpression(substitute)) { + throw new UnsupportedModuleError( + `Unexpected replacement type for ParameterDeclaration (expected Expression): ` + + `${ts.SyntaxKind[substitute.kind]} at ${toPosStr(node)}`); + } + return nodeFactory.updateParameterDeclaration( + node, + node.modifiers, + node.dotDotDotToken, + node.name, + node.questionToken, + node.type, + substitute); +} + +function replaceInSourceFile( + node: ts.SourceFile, {original, substitute}: NodeReplacement, nodeFactory: ts.NodeFactory +): ts.SourceFile { + const statements = replaceNodeInArray(original, substitute, node.statements); + return nodeFactory.updateSourceFile(node, statements); +} diff --git a/src/detectors/transpilers/amd/requireExpressionToTransformation.ts b/src/detectors/transpilers/amd/requireExpressionToTransformation.ts new file mode 100644 index 000000000..9c30c3fc6 --- /dev/null +++ b/src/detectors/transpilers/amd/requireExpressionToTransformation.ts @@ -0,0 +1,161 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import {UnsupportedModuleError, toPosStr} from "./util.js"; +import {ProbingRequireExpression, RequireExpression} from "./parseRequire.js"; +const log = getLogger("transpilers:amd:transformRequireCall"); + +export interface RequireTransformationAsync { + imports: ts.ImportDeclaration[], + callback?: ts.CallExpression, + errback?: ts.FunctionDeclaration, +} + +export interface RequireTransformationSync { + import: ts.ImportDeclaration, + requireStatement: ts.Identifier | ts.AsExpression // Identifier for JS transpilation, AsExpression for TS +} + +export function transformAsyncRequireCall( + node: ts.CallExpression, requireExpression: RequireExpression, nodeFactory: ts.NodeFactory +): RequireTransformationAsync { + const {dependencies, callback, errback} = requireExpression; + const imports: ts.ImportDeclaration[] = []; + const importIdentifiers: ts.Identifier[] = []; + + let callbackParams: ts.Identifier[] | undefined; + let callbackRequiresCallWrapper = false; + if (callback) { + if (ts.isFunctionExpression(callback) || + ts.isArrowFunction(callback) || + ts.isFunctionDeclaration(callback)) { + // Extract parameter names + callbackParams = callback.parameters.map((param) => { + if (!ts.isIdentifier(param.name)) { + // Indicates destructuring in factory signature. This is not (yet?) supported + throw new UnsupportedModuleError( + `Unexpected parameter type ${ts.SyntaxKind[param.kind]} ` + + `at ${toPosStr(param)}`); + } + return param.name; + }); + } else if (ts.isIdentifier(callback)) { + callbackRequiresCallWrapper = true; + } + } + + // Create import statements based on callback parameters + dependencies.elements.forEach((dep, i) => { + // Create import statements + let moduleSpecifier: ts.StringLiteral; + if (!ts.isStringLiteralLike(dep)) { + log.verbose(`Skipping non-string dependency entry of type ${ts.SyntaxKind[dep.kind]} at ` + + toPosStr(dep)); + return; + } + if (ts.isNoSubstitutionTemplateLiteral(dep)) { + moduleSpecifier = nodeFactory.createStringLiteral(dep.text); + // Set pos to the original position to preserve source mapping capability + // (cast type to avoid TS error due to modifying a read only property) + (moduleSpecifier.pos as ts.Node["pos"]) = dep.pos; + } else { + moduleSpecifier = dep; + } + let identifier: ts.Identifier | undefined; + if (callbackRequiresCallWrapper) { + // Generate variable name based on import module + // Later this variable will be used to call the factory function + identifier = nodeFactory.createUniqueName(dep.text.replace(/[^a-zA-Z0-9]/g, "_")); + } else if (callbackParams && callbackParams[i]) { + // Use factory parameter identifier as import identifier + identifier = callbackParams[i]; + } // else: Side effect imports. No identifier needed + + let importClause; + if (identifier) { + importIdentifiers.push(identifier); + importClause = nodeFactory.createImportClause(false, identifier, undefined); + } + + imports.push(nodeFactory.createImportDeclaration( + undefined, + importClause, + moduleSpecifier + )); + }); + + let callbackStatement: ts.CallExpression | undefined; + if (callback) { + if (ts.isFunctionExpression(callback) || ts.isArrowFunction(callback)) { + // Transform callback into iife rather than extracting the body. This way we preserve the scope and + // prevent clashes with variable declarations from other scopes + callbackStatement = nodeFactory.createCallExpression(callback, undefined, importIdentifiers); + } else if (ts.isFunctionDeclaration(callback) && callback.name) { + // Call the declaration + callbackStatement = nodeFactory.createCallExpression(callback.name, undefined, importIdentifiers); + } + } + + let errbackDeclaration: ts.FunctionDeclaration | undefined; + if (errback) { + if (ts.isFunctionExpression(errback)) { + // Convert into a function declaration that is not called. This way the content can still be analyzed + // but there are no runtime effects given that such a callback doesn't exist in the ESM world + errbackDeclaration = nodeFactory.createFunctionDeclaration( + errback.modifiers, + errback.asteriskToken, + errback.name, + errback.typeParameters, + errback.parameters, + errback.type, + errback.body); + } else if (ts.isArrowFunction(errback)) { + let body: ts.Block; + if (ts.isBlock(errback.body)) { + body = errback.body; + } else { // isExpression + body = nodeFactory.createBlock([nodeFactory.createReturnStatement(errback.body)]); + } + errbackDeclaration = nodeFactory.createFunctionDeclaration( + errback.modifiers, + errback.asteriskToken, + nodeFactory.createUniqueName("extracted_require_errback"), + errback.typeParameters, + errback.parameters, + errback.type, + body); + } + } + return { + imports, + callback: callbackStatement, + errback: errbackDeclaration, + }; +} + +export function transformSyncRequireCall( + node: ts.CallExpression, requireExpression: ProbingRequireExpression, nodeFactory: ts.NodeFactory +): RequireTransformationSync { + const {dependency} = requireExpression; + + // Generate variable name based on import module + // Later this variable will be used to call the factory function + const identifier = nodeFactory.createUniqueName(dependency.text.replace(/[^a-zA-Z0-9]/g, "_")); + const importDeclaration = nodeFactory.createImportDeclaration( + undefined, + nodeFactory.createImportClause(false, identifier, undefined), + dependency + ); + + // TODO: The following is only possible if we can emit TypeScript with source maps + // Annotate sap.ui.require call return type with the type of the dependency + // const requireStatement = nodeFactory.createExpressionStatement( + // nodeFactory.createAsExpression(node, nodeFactory.createTypeReferenceNode(dependency.text, undefined))); + // const requireStatement = + // nodeFactory.createAsExpression(node, nodeFactory.createTypeReferenceNode(identifier, undefined)); + + const requireStatement = identifier; + return { + import: importDeclaration, + requireStatement + }; +} diff --git a/src/detectors/transpilers/amd/rewriteExtendCall.ts b/src/detectors/transpilers/amd/rewriteExtendCall.ts new file mode 100644 index 000000000..3120ce9f3 --- /dev/null +++ b/src/detectors/transpilers/amd/rewriteExtendCall.ts @@ -0,0 +1,114 @@ +import ts from "typescript"; +import {toPosStr} from "./util.js"; + +export class UnsupportedExtendCall extends Error { + constructor(message: string) { + super(message); + this.name = this.constructor.name; + } +} + +/** + * Rewrite a UI5-typical `Class.extend("MyClass", {})` CallExpression to a ClassDeclaration + */ +export default function rewriteExtendCall(nodeFactory: ts.NodeFactory, + callExp: ts.CallExpression, modifiers?: ts.ModifierLike[]): ts.ClassDeclaration { + if (!(ts.isPropertyAccessExpression(callExp.expression) && ts.isIdentifier(callExp.expression.name) && + callExp.expression.name.text === "extend")) { + throw new UnsupportedExtendCall(`Not a UI5 Class#extends call ${toPosStr(callExp.expression)}`); + } + + const className = getClassNameFromArguments(callExp.arguments); + const body = getClassBodyFromArguments(nodeFactory, callExp.arguments); + return nodeFactory.createClassDeclaration(modifiers, + className, + undefined, + [nodeFactory.createHeritageClause( + ts.SyntaxKind.ExtendsKeyword, + [nodeFactory.createExpressionWithTypeArguments( + callExp.expression.expression, undefined + )] + )], + body); +} + +function getClassNameFromArguments(args: ts.CallExpression["arguments"]): string { + const firstArg = args[0]; + if (firstArg && !ts.isStringLiteralLike(firstArg)) { + throw new UnsupportedExtendCall(`Unexpected extends argument of type ${ts.SyntaxKind[firstArg.kind]} at ` + + toPosStr(firstArg)); + } + // Just like OpenUI5's ObjectPath... + const nameSegments = firstArg.text.split("."); + return nameSegments[nameSegments.length - 1]; +} + +function getClassBodyFromArguments( + nodeFactory: ts.NodeFactory, args: ts.CallExpression["arguments"]): ts.ClassElement[] { + let classBody: ts.ObjectLiteralExpression | undefined; + for (let i = args.length - 1; i >= 0; i--) { + const arg = args[i]; + if (ts.isObjectLiteralExpression(arg)) { + classBody = arg; + break; + } + } + if (!classBody) { + throw new UnsupportedExtendCall(`No class body found in extends call at ${toPosStr(args[0])}`); + } + if (classBody.properties.find((prop) => ts.isSpreadAssignment(prop) || ts.isShorthandPropertyAssignment(prop))) { + // TODO: Support spread elements(?) + throw new UnsupportedExtendCall(`Unsupported spread element in extends call body`); + } + return classBody.properties.map((prop): ts.ClassElement | undefined => { + if (ts.isMethodDeclaration(prop)) { + // Use method declarations as-is + // e.g. "method() {}" + return prop; + } else if (ts.isPropertyAssignment(prop)) { + if (ts.isFunctionExpression(prop.initializer)) { + return nodeFactory.createMethodDeclaration( + undefined, undefined, + prop.name, + undefined, undefined, + prop.initializer.parameters, + undefined, + prop.initializer.body); + } else if (ts.isObjectLiteralExpression(prop.initializer) && + ts.isIdentifier(prop.name) && prop.name.text === "metadata") { + // Transform to *static* property declaration? + // This would align it with how UI5 projects should declare metadata in TypeScript, + // however it's unclear whether this helps our static analysis + return nodeFactory.createPropertyDeclaration( + [nodeFactory.createToken(ts.SyntaxKind.StaticKeyword)], + prop.name, + undefined, undefined, + prop.initializer); + } else { + // Assign all other properties (including arrow functions) to the class prototype + // This transformation does not reflect the runtime behavior where + // properties are set on the Class's prototype. However, tsc won't derive *any* + // type information from Object.defineProperty(Class.prototype, "prob", ...) + // So the current approach works better for the static analysis + if (prop.initializer.kind === ts.SyntaxKind.NullKeyword || + prop.initializer.kind === ts.SyntaxKind.UndefinedKeyword) { + // Skip property assignments that declare a null value, in the hope + // that tsc can infer a more useful type based on other assignment + // in one of the methods. If we would define a class property, tsc + // would not attempt to infer more type information. + return; + } + return nodeFactory.createPropertyDeclaration( + undefined, + prop.name, + undefined, undefined, + prop.initializer); + } + } else { + throw new UnsupportedExtendCall( + `While generating class body: Unexpected property type ${ts.SyntaxKind[prop.kind]} at ` + + toPosStr(prop)); + } + + }).filter(_ => _) as ts.ClassElement[]; +} diff --git a/src/detectors/transpilers/amd/transpiler.ts b/src/detectors/transpilers/amd/transpiler.ts new file mode 100644 index 000000000..95fda556a --- /dev/null +++ b/src/detectors/transpilers/amd/transpiler.ts @@ -0,0 +1,153 @@ +import ts from "typescript"; +import {getLogger} from "@ui5/logger"; +import path from "node:path/posix"; +import {taskStart} from "../../util/perf.js"; +import {TranspileResult} from "../AbstractTranspiler.js"; +import {createTransformer} from "./TsTransformer.js"; +import {UnsupportedModuleError} from "./util.js"; + +const log = getLogger("transpilers:amd:transpiler"); + +export function amdToEsm(moduleId: string, content: string, strict?: boolean): TranspileResult { + try { + const taskEnd = taskStart("Transform JS", moduleId, true); + const esmContent = transpile(moduleId, content, strict); + taskEnd(); + if (!esmContent.source) { + log.verbose(`ESM transpiler returned no result for ${moduleId}`); + return {source: content, map: ""}; + } + return esmContent; + } catch (err) { + if (err instanceof Error) { + throw new Error(`Failed to transpile module ${moduleId}: ${err.message}`, { + cause: err + }); + } else { + throw err; + } + } +} + +function transpile(resourcePath: string, content: string, strict?: boolean): TranspileResult { + // This is heavily inspired by the TypesScript "transpileModule" API, + // which sadly does not expose the program instance, which we need to access the type checker + const moduleName = path.basename(resourcePath, ".js"); + const inputFileName = `${moduleName}.js`; + const outputFileName = `${moduleName}.ts`; + const sourceFile = ts.createSourceFile( + inputFileName, + content, + { + languageVersion: ts.ScriptTarget.ES2022, + jsDocParsingMode: ts.JSDocParsingMode.ParseNone, + }, + ); + + // Output + let outputText: string | undefined; + let sourceMapText: string | undefined; + let sourceMapName: string | undefined; + + const compilerOptions = { + moduleResolution: ts.ModuleResolutionKind.NodeNext, + checkJs: true, + allowJs: true, + skipLibCheck: true, + + target: ts.ScriptTarget.ES2022, + module: ts.ModuleKind.ES2022, + isolatedModules: true, + sourceMap: true, + suppressOutputPathCheck: true, + noLib: true, + noResolve: true, + allowNonTsExtensions: true + }; + + // TODO: Investigate whether it would be faster to create one host + program to transpile many files in + // one batch + const compilerHost: ts.CompilerHost = { + getSourceFile: fileName => fileName === inputFileName ? sourceFile : undefined, + writeFile: (name, text) => { + if (name.endsWith(".map")) { + if (sourceMapText) { + throw new Error(`Unexpected multiple source maps for module ${resourcePath}`); + } + sourceMapText = text; + sourceMapName = name; + } else { + if (outputText) { + throw new Error(`Unexpected multiple outputs for module ${resourcePath}`); + } + outputText = text; + } + }, + getDefaultLibFileName: () => "lib.d.ts", + useCaseSensitiveFileNames: () => false, + getCanonicalFileName: fileName => fileName, + getCurrentDirectory: () => "", + getNewLine: () => "\n", + fileExists: (fileName): boolean => fileName === inputFileName, + readFile: () => "", + directoryExists: () => true, + getDirectories: () => [], + }; + const program = ts.createProgram([inputFileName], compilerOptions, compilerHost); + + const transformers: ts.CustomTransformers = { + before: [createTransformer(resourcePath, program)] + }; + + try { + // ts.setEmitFlags(sourceFile, ts.EmitFlags.NoTrailingSourceMap); + // TODO: Investigate whether we can retrieve a source file that can be fed directly into the typeChecker + program.emit( + /*targetSourceFile*/ undefined, /*writeFile*/ undefined, + /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, + transformers); + + /* tsc currently does not provide an API to emit TypeScript *with* a source map + (see https://github.com/microsoft/TypeScript/issues/51329) + + The below can be used to emit TypeScript without a source map: + + const result = ts.transform( + sourceFile, + [createTransformer(resourcePath, program)], compilerOptions); + + const printer = ts.createPrinter(); + const printed = printer.printNode(ts.EmitHint.SourceFile, result.transformed[0], sourceFile); + const printed = printer.printFile(result.transformed[0]); + outputText = printed; + */ + } catch(err) { + if (strict) { + throw err; + } + if (err instanceof UnsupportedModuleError) { + log.verbose(`Failed to transform module ${resourcePath}: ${err.message}`); + if (err.stack && log.isLevelEnabled("verbose")) { + log.verbose(`Stack trace:`); + log.verbose(err.stack); + } + return { source: content, map: "" }; + } else if (err instanceof Error && err.message.startsWith("Debug Failure")) { + // We probably failed to create a valid AST + log.verbose(`AST transformation failed for module ${resourcePath}: ${err.message}`); + if (err.stack && log.isLevelEnabled("verbose")) { + log.verbose(`Stack trace:`); + log.verbose(err.stack); + } + return { source: content, map: "" }; + } + throw err; + } + + if (outputText === undefined) throw new Error(`Transpiling yielded no result for ${resourcePath}`); + + // Convert sourceMappingURL ending with ".js" to ".ts" + outputText = outputText + .replace(`//# sourceMappingURL=${sourceMapName}`, `//# sourceMappingURL=${outputFileName}.map`); + return { source: outputText, map: sourceMapText as string }; +} diff --git a/src/detectors/transpilers/amd/util.ts b/src/detectors/transpilers/amd/util.ts new file mode 100644 index 000000000..ca70514be --- /dev/null +++ b/src/detectors/transpilers/amd/util.ts @@ -0,0 +1,13 @@ +import ts from "typescript"; + +export function toPosStr(node: ts.Node) { + const {line, character: column} = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()); + return `${line + 1}:${column + 1}`; +} + +export class UnsupportedModuleError extends Error { + constructor(message: string) { + super(message); + this.name = this.constructor.name; + } +} diff --git a/src/detectors/transpilers/xml/Parser.ts b/src/detectors/transpilers/xml/Parser.ts new file mode 100644 index 000000000..c57f43ffd --- /dev/null +++ b/src/detectors/transpilers/xml/Parser.ts @@ -0,0 +1,574 @@ +import {Attribute as SaxAttribute, Tag as SaxTag, Position as SaxPosition} from "sax-wasm"; +import he from "he"; +import ViewGenerator from "./generator/ViewGenerator.js"; +import FragmentGenerator from "./generator/FragmentGenerator.js"; +import JSTokenizer from "./lib/JSTokenizer.js"; +import {LintMessage, LintMessageSeverity} from "../../AbstractDetector.js"; +import {TranspileResult} from "../AbstractTranspiler.js"; +import AbstractGenerator from "./generator/AbstractGenerator.js"; +import {getLogger} from "@ui5/logger"; +import {ApiExtract} from "./transpiler.js"; +const log = getLogger("transpilers:xml:Parser"); + +export type Namespace = string; +export interface NamespaceDeclaration { + localName: string | null, // null for default namespace + namespace: Namespace +} + +// Parse the XML node by node. We only expect four types of node +// Once parsed, render the nodes as JavaScript code, starting with the leaves +export const enum NodeKind { + Unknown = 0, + Control = 1 << 0, + Aggregation = 1 << 1, + FragmentDefinition = 1 << 2, + Template = 1 << 3, + Xhtml = 1 << 4, // Should generally be ignored + Svg = 1 << 5, // Should generally be ignored +} + +export interface Position { + line: number, + column: number, +} + +export interface NodeDeclaration { + kind: NodeKind, + name: string, + namespace: Namespace, + start: Position, + end: Position, +} + +export interface ControlDeclaration extends NodeDeclaration { + kind: NodeKind.Control, + properties: Set, + aggregations: Map, + variableName?: string, // Will be populated during generation phase +} + +export interface AggregationDeclaration extends NodeDeclaration { + kind: NodeKind.Aggregation, + owner: ControlDeclaration, + controls: ControlDeclaration[], +} + +export interface FragmentDefinitionDeclaration extends NodeDeclaration { + kind: NodeKind.FragmentDefinition, + controls: Set, +} + +// interface TemplateDeclaration extends NodeDeclaration { +// kind: NodeKind.Template +// } + +interface AttributeDeclaration { + name: string, + value: string, + localNamespace?: string, + start: Position, + end: Position, +} + +interface PropertyDeclaration extends AttributeDeclaration {} + +export interface RequireExpression extends AttributeDeclaration { + declarations: RequireDeclaration[] +} + +export interface RequireDeclaration { + moduleName: string, + variableName?: string, +} + +interface NamespaceStackEntry { + namespace: NamespaceDeclaration, + level: number +} + +const XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; +const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; +const TEMPLATING_NAMESPACE = "http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1"; +const FESR_NAMESPACE ="http://schemas.sap.com/sapui5/extension/sap.ui.core.FESR/1"; +const SAP_BUILD_NAMESPACE ="sap.build"; +const SAP_UI_DT_NAMESPACE ="sap.ui.dt"; +const CUSTOM_DATA_NAMESPACE ="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"; +const CORE_NAMESPACE = "sap.ui.core"; +const PATTERN_LIBRARY_NAMESPACES = /^([a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*)$/; + +const enum DocumentKind { + View, + Fragment +} + +function determineDocumentKind(resourceName: string): DocumentKind | null { + if ( /\.view.xml$/.test(resourceName) ) { + return DocumentKind.View; + } else if ( /\.fragment.xml$/.test(resourceName) ) { + return DocumentKind.Fragment; + } else if ( /\.control.xml$/.test(resourceName) ) { + throw new Error(`Control XML analysis is currently not supported for resource ${resourceName}`); + } else { + return null; + } +} + +function toPosition(saxPos: SaxPosition): Position { + return { + line: saxPos.line, + column: saxPos.character + }; +} + +export default class Parser { + #resourceName: string; + #xmlDocumentKind: DocumentKind; + + #messages: LintMessage[] = []; + #namespaceStack: NamespaceStackEntry[] = []; + #nodeStack: NodeDeclaration[] = []; + + #generator: AbstractGenerator; + #apiExtract: ApiExtract; + + constructor(resourceName: string, apiExtract: ApiExtract) { + const xmlDocumentKind = determineDocumentKind(resourceName); + if (xmlDocumentKind === null) { + throw new Error(`Unknown document type for resource ${resourceName}`); + } + this.#resourceName = resourceName; + this.#xmlDocumentKind = xmlDocumentKind; + this.#generator = xmlDocumentKind === DocumentKind.View ? + new ViewGenerator(resourceName) : new FragmentGenerator(resourceName); + + this.#apiExtract = apiExtract; + } + + pushTag(tag: SaxTag) { + this.#nodeStack.push(this._createNode(tag)); + } + + popTag(_tag: SaxTag) { // No need to use the parsed tag, we rely on our nodeStack + const level = this.#nodeStack.length; + const closingNode = this.#nodeStack.pop(); + + if (closingNode && + (closingNode.kind & (NodeKind.Control | NodeKind.FragmentDefinition))) { + // Generate view code for this control + // If this is the root control, export it + if (level === 1) { + // Actually closingNode might be a FragmentDefinitionDeclaration here + // But that's tricky with the current generator signatures + this.#generator.writeRootControl(closingNode as ControlDeclaration); + } else { + this.#generator.writeControl(closingNode as ControlDeclaration); + } + } + // Cleanup stacks stacks + this._removeNamespacesForLevel(level); + } + + generate(): TranspileResult { + const {source, map} = this.#generator.getModuleContent(); + return { + source, + map, + messages: this.#messages, + }; + } + + _findParentNode(kindFilter: number): NodeDeclaration | null { + for (let i = this.#nodeStack.length - 1; i >= 0; i--) { + if (this.#nodeStack[i].kind & kindFilter) { + return this.#nodeStack[i]; + } + } + return null; + } + + _addNamespace(namespace: NamespaceDeclaration, level: number,) { + this.#namespaceStack.push({ + namespace, + level + }); + } + + _resolveNamespace(localName: string | null,): Namespace | undefined { + // Search this.#namespaceStack in reverse order + for (let i = this.#namespaceStack.length - 1; i >= 0; i--) { + const ns = this.#namespaceStack[i]; + if (ns.namespace.localName === localName) { + return ns.namespace.namespace; + } + } + } + + _removeNamespacesForLevel(level: number,) { + // Remove all namespaces for the given level + let i = this.#namespaceStack.length - 1; + while (i >= 0 && this.#namespaceStack[i].level >= level) { + this.#namespaceStack.pop(); + i--; + } + } + + _addDefaultAggregation( + owner: ControlDeclaration, control: ControlDeclaration + ) { + let aggregationName = this.#apiExtract.defaultAggregations[`${owner.namespace}.${owner.name}`]; + + if (!aggregationName) { + log.verbose(`Failed to determine default aggregation for control ${owner.name} used in ` + + `resource ${this.#resourceName}. Falling back to 'dependents'`); + // In case the default aggregation is unknown (e.g. in case of custom controls), + // fallback to use the generic "dependents" aggregation + // This is not correct at runtime, but it's the best we can do for linting purposes + aggregationName = "dependents"; + } + if (!owner.aggregations.has(aggregationName)) { + const aggregation = { + kind: NodeKind.Aggregation, + name: aggregationName, + owner, + controls: [control], + namespace: owner.namespace, + start: control.start, + end: control.end, + }; + owner.aggregations.set(aggregationName, aggregation); + } else { + owner.aggregations.get(aggregationName)!.controls.push(control); + } + } + + _parseRequireAttribute(attrValue: string): RequireDeclaration[] { + try { + // This is no well-formed JSON, therefore we have to parse it manually + const requireMap = JSTokenizer.parseJS(attrValue); + return Object.keys(requireMap).map((variableName) => { + return { + moduleName: requireMap[variableName], + variableName + }; + }); + } catch (err) { + throw new Error(`Failed to parse require attribute value ${attrValue} in resource ${this.#resourceName}`); + } + } + + _createNode(tag: SaxTag): NodeDeclaration { + let tagName = tag.name; + let tagNamespace = null; // default namespace + + // Extract optional namespace from attribute name + if (tagName.includes(":")) { + [tagNamespace, tagName] = tagName.split(":"); + } + + const attributes = new Set(); + tag.attributes.forEach((attr: SaxAttribute) => { + const attrName = attr.name.value; + const attrValue = he.decode(attr.value.value); + // Extract namespaces immediately so we can resolve namespaced attributes in the next go + if (attrName === "xmlns") { + // Declares the default namespace + this._addNamespace({ + localName: null, + namespace: attrValue + }, this.#nodeStack.length); + } else if (attrName.startsWith("xmlns:")) { + // Named namespace + this._addNamespace({ + localName: attrName.slice(6), // Remove "xmlns:" + namespace: attrValue + }, this.#nodeStack.length); + } else if (attrName.includes(":")) { + // Namespaced attribute + const [attrNamespace, attrLocalName] = attrName.split(":"); + attributes.add({ + name: attrLocalName, + value: attrValue, + localNamespace: attrNamespace, + start: toPosition(attr.name.start), + end: toPosition({ + line: attr.value.end.line, + character: attr.value.end.character + 1 // Add 1 to include the closing quote + }) + }); + } else { + attributes.add({ + name: attrName, + value: attrValue, + start: toPosition(attr.name.start), + end: toPosition({ + line: attr.value.end.line, + character: attr.value.end.character + 1 // Add 1 to include the closing quote + }) + }); + } + }); + + // Note: Resolve namespace *after* evaluating all attributes, since it might have been defined + // by one of them + let namespace = this._resolveNamespace(tagNamespace); + if (!namespace) { + throw new Error(`Unknown namespace ${tagNamespace} for tag ${tagName} in resource ${this.#resourceName}`); + } else if (namespace === SVG_NAMESPACE) { + // Ignore SVG nodes + this.#messages.push({ + ruleId: "ui5-linter-no-deprecated-api", + severity: LintMessageSeverity.Error, + line: tag.openStart.line + 1, // Add one to align with IDEs + column: tag.openStart.character, + message: `Usage of SVG in XML Views/Fragments is deprecated`, + }); + return { + kind: NodeKind.Svg, + name: tagName, + namespace, + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + } else if (namespace === XHTML_NAMESPACE) { + // Ignore XHTML nodes for now + this.#messages.push({ + ruleId: "ui5-linter-no-deprecated-api", + severity: LintMessageSeverity.Error, + line: tag.openStart.line + 1, // Add one to align with IDEs + column: tag.openStart.character, + message: `Usage of native HTML in XML Views/Fragments is deprecated`, + messageDetails: + `{@link topic:be54950cae1041f59d4aa97a6bade2d8 Using Native HTML in XML Views (deprecated)}` + }); + return { + kind: NodeKind.Xhtml, + name: tagName, + namespace, + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + } else if (namespace === TEMPLATING_NAMESPACE) { + return { + kind: NodeKind.Template, + name: tagName, + namespace, + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + } else if (PATTERN_LIBRARY_NAMESPACES.test(namespace)) { + + const lastIdx = tagName.lastIndexOf("."); + if (lastIdx !== -1) { + // Resolve namespace prefix, e.g. "sap:m.Button" + namespace += `.${tagName.slice(0, lastIdx)}`; + tagName = tagName.slice(lastIdx + 1); + } + + return this._handleUi5LibraryNamespace(tagName, namespace, attributes, tag); + } else { + return { + kind: NodeKind.Unknown, + name: tagName, + namespace, + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + } + } + + _handleUi5LibraryNamespace( + moduleName: string, namespace: Namespace, attributes: Set, + tag: SaxTag + ): ControlDeclaration | AggregationDeclaration | FragmentDefinitionDeclaration { + const controlProperties = new Set(); + const customDataElements: ControlDeclaration[] = []; + attributes.forEach((attr) => { + if (attr.localNamespace) { + // Resolve namespace + const resolvedNamespace = this._resolveNamespace(attr.localNamespace); + if (!resolvedNamespace) { + throw new Error(`Unknown namespace ${attr.localNamespace} for attribute ${attr.name} ` + + `in resource ${this.#resourceName}`); + } + if ((resolvedNamespace === CORE_NAMESPACE || + resolvedNamespace === TEMPLATING_NAMESPACE) && attr.name === "require") { + // sap.ui.core:require or template:require declaration + let requireDeclarations: RequireDeclaration[]; + if (resolvedNamespace === TEMPLATING_NAMESPACE && !attr.value.startsWith("{")) { + /* From: https://github.com/SAP/openui5/blob/959dcf4d0ac771aa53ce4f4bf02832356afd8c23/src/sap.ui.core/src/sap/ui/core/util/XMLPreprocessor.js#L1301-L1306 + * "template:require" attribute may contain either a space separated list of + * dot-separated module names or a JSON representation of a map from alias to + * slash-separated Unified Resource Names (URNs). In the first case, the resulting + * modules must be accessed from the global namespace. In the second case, they are + * available as local names (AMD style) similar to instructions. + */ + requireDeclarations = []; + attr.value.split(" ").map(function (sModuleName) { + const requiredModuleName = sModuleName.replace(/\./g, "/"); + // We can't (and also really shouldn't) declare a global namespace for the imported + // module, so we just use the module name as variable name + const variableName = requiredModuleName.replaceAll("/", "_"); + requireDeclarations.push({ + moduleName: requiredModuleName, + variableName + }); + }); + } else { + // Common case: JSON-like representation + requireDeclarations = this._parseRequireAttribute(attr.value); + } + const requireExpression = { + name: attr.name, + value: attr.value, + declarations: requireDeclarations, + start: attr.start, + end: attr.end + } as RequireExpression; + + this.#generator.writeRequire(requireExpression); + } else if (resolvedNamespace === FESR_NAMESPACE || + resolvedNamespace === SAP_BUILD_NAMESPACE || resolvedNamespace === SAP_UI_DT_NAMESPACE) { + // Silently ignore FESR, sap.build and sap.ui.dt attributes + } else if (resolvedNamespace === CUSTOM_DATA_NAMESPACE) { + // Add custom data element and add it as an aggregation + const customData: ControlDeclaration ={ + kind: NodeKind.Control, + name: "CustomData", + namespace: CORE_NAMESPACE, + properties: new Set([ + { + name: "key", + value: attr.name, + start: attr.start, + end: attr.end, + }, + { + name: "value", + value: attr.value, + start: attr.start, + end: attr.end, + } + ]), + aggregations: new Map(), + start: attr.start, + end: attr.end, + }; + customDataElements.push(customData); + // Immediately write the custom data element declaration to make it usable + // in the control aggregation + this.#generator.writeControl(customData); + } else { + log.warn(`Ignoring unknown namespaced attribute ${attr.localNamespace}:${attr.name} ` + + `for ${moduleName} in resource ${this.#resourceName}`); + } + } else { + controlProperties.add(attr as PropertyDeclaration); + } + }); + + const parentNode = this._findParentNode( + NodeKind.Control | NodeKind.Aggregation | NodeKind.FragmentDefinition); + + if (moduleName.match(/^[a-z]/)) { + const aggregationName = moduleName; + // TODO: Replace the above with a check against known controls. Even though there are + // no known cases of lower case control names in the framework. + // This node likely declares an aggregation + if (!parentNode || parentNode.kind === NodeKind.FragmentDefinition) { + if (this.#xmlDocumentKind !== DocumentKind.Fragment) { + throw new Error(`Unexpected top-level aggregation declaration: ` + + `${aggregationName} in resource ${this.#resourceName}`); + } + // In case of top-level aggregations in fragments, generate an sap.ui.core.Control instance and + // add the aggregation's content to it's dependents aggregation + const coreControl: ControlDeclaration = { + kind: NodeKind.Control, + name: "Control", + namespace: CORE_NAMESPACE, + properties: new Set(), + aggregations: new Map(), + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + return coreControl; + } else if (parentNode.kind === NodeKind.Aggregation) { + throw new Error(`Unexpected aggregation ${aggregationName} within aggregation ${parentNode.name} ` + + `in resource ${this.#resourceName}`); + } + const owner = parentNode as ControlDeclaration; + + let ownerAggregation = owner.aggregations.get(aggregationName); + if (!ownerAggregation) { + // Create aggregation declaration if not already declared before + // (duplicate aggregation tags are merged into the first occurrence) + ownerAggregation = { + kind: NodeKind.Aggregation, + name: aggregationName, + namespace, + owner: parentNode as ControlDeclaration, + controls: [], + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + owner.aggregations.set(aggregationName, ownerAggregation); + } + return ownerAggregation; + } else if (this.#xmlDocumentKind === DocumentKind.Fragment && moduleName === "FragmentDefinition" && + namespace === CORE_NAMESPACE) { + // This node declares a fragment definition + const node: FragmentDefinitionDeclaration = { + kind: NodeKind.FragmentDefinition, + name: moduleName, + namespace, + controls: new Set(), + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + + if (parentNode) { + throw new Error(`Unexpected nested FragmentDefiniton in resource ${this.#resourceName}`); + } + return node; + } else { + // This node declares a control + // Or a fragment definition in case of a fragment + const node: ControlDeclaration ={ + kind: NodeKind.Control, + name: moduleName, + namespace, + properties: controlProperties, + aggregations: new Map(), + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }; + if (customDataElements && customDataElements.length) { + node.aggregations.set("customData", { + kind: NodeKind.Aggregation, + name: "customData", + namespace, + owner: node, + controls: customDataElements, + start: toPosition(tag.openStart), + end: toPosition(tag.openEnd), + }); + } + + if (parentNode) { + if (parentNode.kind === NodeKind.Control) { + // Insert the current control in the default aggregation of the last control + this._addDefaultAggregation(parentNode as ControlDeclaration, node as ControlDeclaration); + } else if (parentNode.kind === NodeKind.Aggregation) { + const aggregationNode = parentNode as AggregationDeclaration; + aggregationNode.controls.push(node); + } else if (parentNode.kind === NodeKind.FragmentDefinition) { + // Add the control to the fragment definition + (parentNode as FragmentDefinitionDeclaration).controls.add(node as ControlDeclaration); + } else { + throw new Error(`Unexpected node kind ${parentNode.kind} in resource ${this.#resourceName}`); + } + } + return node; + } + } +} diff --git a/src/detectors/transpilers/xml/generator/AbstractGenerator.ts b/src/detectors/transpilers/xml/generator/AbstractGenerator.ts new file mode 100644 index 000000000..023f0f28e --- /dev/null +++ b/src/detectors/transpilers/xml/generator/AbstractGenerator.ts @@ -0,0 +1,116 @@ +import { + ControlDeclaration, RequireExpression, Position +} from "../Parser.js"; +import Writer from "./Writer.js"; + +interface ImportStatement { + moduleName: string + variableName: string, + start?: Position, + end?: Position, +} + +// TODO: Generate type information to make View#byId() access typed? + +export default abstract class AbstractGenerator { + _imports = new Set(); + _variableNames = new Set(); + _body: Writer; + + constructor(resourceName: string) { + this._body = new Writer(resourceName.replace(/.xml$/, ".js"), resourceName); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + writeRootControl(controlDeclaration: ControlDeclaration) { + throw new Error("Not implemented"); + } + + writeControl(controlDeclaration: ControlDeclaration) { + const importVariableName = this._getUniqueVariableName(controlDeclaration.name); + + // Add import + this._imports.add({ + moduleName: controlDeclaration.namespace.replaceAll(".", "/") + `/${controlDeclaration.name}`, + variableName: importVariableName, + start: controlDeclaration.start, + end: controlDeclaration.end, + }); + // Generate variable name + controlDeclaration.variableName = this._getUniqueVariableName(`o${controlDeclaration.name}`); + + // Create the control + this._body.write(`const ${controlDeclaration.variableName} = `); + this._body.writeln(`new ${importVariableName}({`, controlDeclaration.start, controlDeclaration.end); + // Write properties + controlDeclaration.properties.forEach((attribute) => { + // TODO: Determine attribute type based on metadata and parse/write value accordingly + this._body.write(` `); + this._body.writeln( + `${attribute.name}: ${JSON.stringify(attribute.value)},`, + attribute.start, attribute.end); + }); + // Write aggregations + controlDeclaration.aggregations.forEach((aggregationDeclaration, aggregationName) => { + this._body.write(` `); + this._body.write(aggregationName, aggregationDeclaration.start, aggregationDeclaration.end); + this._body.writeln(`: [`); + aggregationDeclaration.controls.forEach((control) => { + if (!control.variableName) { + throw new Error( + `Control ${control.name} required in aggregation ` + + `${aggregationName} of control ${controlDeclaration.name} has no yet been declared`); + } + this._body.writeln(` ${control.variableName},`); + }); + this._body.writeln(` ],`); + }); + this._body.writeln("});\n"); + } + + writeRequire(requireExpression: RequireExpression) { + requireExpression.declarations.forEach((declaration) => { + if (!declaration.variableName) { + // Side effect require? + declaration.variableName = "_"; + } + const variableName = this._getUniqueVariableName(declaration.variableName); + declaration.variableName = variableName; + this._imports.add({ + moduleName: declaration.moduleName, + variableName: variableName, + start: requireExpression.start, + end: requireExpression.end + }); + }); + } + + getModuleContent() { + // Sort by import variable name + const imports = Array.from(this._imports).sort((a, b) => { + return b.variableName.localeCompare(a.variableName); + }); + imports.forEach((importStatment) => { + this._body.prependln(`import ${importStatment.variableName} from "${importStatment.moduleName}";`, + importStatment.start, importStatment.end); + }); + + return { + source: this._body.getString(), + map: JSON.stringify(this._body.getSourceMap()), + }; + } + + _getUniqueVariableName(variableName: string): string { + let variableNameCandidate = variableName; + if (this._variableNames.has(variableNameCandidate)) { + let counter = 2; + while (this._variableNames.has(variableNameCandidate)) { + variableNameCandidate = `${variableName}${counter}`; + counter++; + } + } + this._variableNames.add(variableNameCandidate); + return variableNameCandidate; + } +} diff --git a/src/detectors/transpilers/xml/generator/FragmentGenerator.ts b/src/detectors/transpilers/xml/generator/FragmentGenerator.ts new file mode 100644 index 000000000..ea1eb3a4a --- /dev/null +++ b/src/detectors/transpilers/xml/generator/FragmentGenerator.ts @@ -0,0 +1,29 @@ +import AbstractGenerator from "./AbstractGenerator.js"; +import {ControlDeclaration, FragmentDefinitionDeclaration, NodeKind} from "../Parser.js"; + +export default class FragmentGenerator extends AbstractGenerator { + writeRootControl(controlInfo: ControlDeclaration | FragmentDefinitionDeclaration) { + let returnVal; + + if (controlInfo.kind === NodeKind.Control) { + this.writeControl(controlInfo); + returnVal = controlInfo.variableName; + } else if (controlInfo.kind === NodeKind.FragmentDefinition) { + const variables = Array.from(controlInfo.controls.values()).map((control) => { + if (!control.variableName) { + throw new Error( + `Control ${control.name} required in fragment definition ` + + `${controlInfo.name} has no yet been declared`); + } + return control.variableName; + }); + returnVal = `[${variables.join(", ")}]`; + } + + this._body.writeln(`export default { + createContent: function () { + return ${returnVal}; + }; +}`); + } +} diff --git a/src/detectors/transpilers/xml/generator/ViewGenerator.ts b/src/detectors/transpilers/xml/generator/ViewGenerator.ts new file mode 100644 index 000000000..cf45f4de4 --- /dev/null +++ b/src/detectors/transpilers/xml/generator/ViewGenerator.ts @@ -0,0 +1,9 @@ +import AbstractGenerator from "./AbstractGenerator.js"; +import {ControlDeclaration} from "../Parser.js"; + +export default class ViewGenerator extends AbstractGenerator { + writeRootControl(controlInfo: ControlDeclaration) { + this._body.write(`export default `); + this.writeControl(controlInfo); + } +} diff --git a/src/detectors/transpilers/xml/generator/Writer.ts b/src/detectors/transpilers/xml/generator/Writer.ts new file mode 100644 index 000000000..48ee0e3fc --- /dev/null +++ b/src/detectors/transpilers/xml/generator/Writer.ts @@ -0,0 +1,129 @@ +import {encode, SourceMapMappings, SourceMapSegment} from "@jridgewell/sourcemap-codec"; +import {EncodedSourceMap} from "@jridgewell/trace-mapping"; +import {Position} from "../Parser.js"; +const NL = "\n"; + +interface Mapping { + generated: Position + original: Position +} + +export default class Writer { + #buf: string = ""; + // #map: GenMapping; + #mappings = new Set(); + lineOffset = 0; + columnOffset = 0; + #sourceName: string; + #targetName: string; + + constructor(targetName: string, sourceName: string) { + // this.#map = new GenMapping({ + // file: targetName, + // }); + this.#targetName = targetName; + this.#sourceName = sourceName; + } + + write(str: string, start?: Position, end?: Position) { + if (str === null || str === "") { + return; + } + start && this.#addMapping(start); + + const strSplit = str.split(NL); + this.lineOffset += strSplit.length - 1; + this.columnOffset += strSplit[strSplit.length - 1].length; + this.#buf += str; + + end && this.#addMapping(end); + } + + writeln(str: string, start?: Position, end?: Position) { + this.write(str, start, end); + this.#buf += NL; + this.lineOffset += 1; + this.columnOffset = 0; + } + + // ln version only so we don't need to worry about the column offset + prependln(str: string, start?: Position, end?: Position) { + const strSplit = str.split(NL); + const lineOffset = strSplit.length - 1; + const columnOffset = strSplit[strSplit.length - 1].length; + + this.#shiftMappings(lineOffset + 1); // Adding one for the additional new line we'll be adding + + start && this.#addMapping(start, { + line: 0, + column: 0 + }); + + this.lineOffset += lineOffset + 1; // Adding one for the additional new line + this.#buf = str + NL + this.#buf; + + end && this.#addMapping(end, { + line: lineOffset, + column: columnOffset + }); + } + + getString() { + return this.#buf; + } + + /** + * Generate the final source map for the generated code. + * + * Important notes: + * * Default aggregations will be mapped to the control that started it + */ + getSourceMap(): EncodedSourceMap { + const mappings: SourceMapMappings = []; + this.#mappings.forEach((mapping) => { + let missingLineMappings = mapping.generated.line - mappings.length + 1; + if (missingLineMappings > 0) { + while (missingLineMappings--) { + mappings.push([]); + } + } + // [generatedColumn, sourceIndex, sourceLine, sourceColumn, nameIndex] + const segment: SourceMapSegment = [ + mapping.generated.column, + 0, + mapping.original.line, + mapping.original.column + ]; + mappings[mapping.generated.line].push(segment); + }); + + return { + version: 3, + names: [], + file: this.#targetName, + sources: [this.#sourceName], + mappings: encode(mappings), + }; + } + + getLength() { + return this.#buf.length; + } + + #addMapping(sourcePos: Position, targetPos?: Position) { + this.#mappings.add({ + generated: targetPos || { + line: this.lineOffset, + column: this.columnOffset, + }, + original: sourcePos + }); + } + + #shiftMappings(offset: number) { + // Add offset to all mappings + this.#mappings.forEach((mapping) => { + mapping.generated.line += offset; + }); + } +} diff --git a/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts b/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts new file mode 100644 index 000000000..d6b20c3fb --- /dev/null +++ b/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts @@ -0,0 +1,7 @@ +interface RequireMap { + [key: string]: string +} +export function parseJS(sSource: string): RequireMap +export default class JSTokenizer { + static parseJS(sSource: string): RequireMap +} diff --git a/src/detectors/transpilers/xml/lib/JSTokenizer.js b/src/detectors/transpilers/xml/lib/JSTokenizer.js new file mode 100644 index 000000000..7e173fcbc --- /dev/null +++ b/src/detectors/transpilers/xml/lib/JSTokenizer.js @@ -0,0 +1,387 @@ +/* + * This is a copy of the sap/base/util/JSTokenizer.js module from OpenUI5 + * https://github.com/SAP/openui5/blob/99ddaf3e3d2b1217fba25d570235bc28cea736fd/src/sap.ui.core/src/sap/base/util/JSTokenizer.js + */ + +/* eslint-disable */ + +/*! + * ${copyright} + */ +/* + * IMPORTANT: This is a private module, its API must not be used and is subject to change. + * Code other than the OpenUI5 libraries must not introduce dependencies to this module. + */ +//sap.ui.define([], function() { + //"use strict"; + + /* + * The following code has been taken from the component JSON in JavaScript + * from Douglas Crockford which is licensed under Public Domain + * (http://www.json.org/ > JavaScript > json-2). The code contains + * local modifications. + * + * Git URL: https://github.com/douglascrockford/JSON-js/blob/42c18c621a411c3f39a81bb0a387fc50dcd738d9/json_parse.js + */ + + /** + * Tokenizer for JS values. + * + * Contains functions to consume tokens on an input string. + * + * @example + * sap.ui.require(["sap/base/util/JSTokenizer"], function(JSTokenizer){ + * JSTokenizer().parseJS("{test:'123'}"); // {test:'123'} + * }); + * + * @class sap/base/util/JSTokenizer + * @since 1.58 + * @private + * @ui5-restricted sap.ui.core + */ + var JSTokenizer = function() { + + this.at; // The index of the current character + this.ch; // The current character + this.escapee = { + '"': '"', + '\'': '\'', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t' + }; + this.text; + }; + + + JSTokenizer.prototype.error = function(m) { + + // Call error when something is wrong. + throw { + name: 'SyntaxError', + message: m, + at: this.at, + text: this.text + }; + }; + + JSTokenizer.prototype.next = function(c) { + + // If a c parameter is provided, verify that it matches the current character. + if (c && c !== this.ch) { + this.error("Expected '" + c + "' instead of '" + this.ch + "'"); + } + + // Get the next character. When there are no more characters, + // return the empty string. + this.ch = this.text.charAt(this.at); + this.at += 1; + return this.ch; + }; + + JSTokenizer.prototype.number = function() { + + // Parse a number value. + var number, string = ''; + + if (this.ch === '-') { + string = '-'; + this.next('-'); + } + while (this.ch >= '0' && this.ch <= '9') { + string += this.ch; + this.next(); + } + if (this.ch === '.') { + string += '.'; + while (this.next() && this.ch >= '0' && this.ch <= '9') { + string += this.ch; + } + } + if (this.ch === 'e' || this.ch === 'E') { + string += this.ch; + this.next(); + if (this.ch === '-' || this.ch === '+') { + string += this.ch; + this.next(); + } + while (this.ch >= '0' && this.ch <= '9') { + string += this.ch; + this.next(); + } + } + number = +string; + if (!isFinite(number)) { + this.error("Bad number"); + } else { + return number; + } + }; + + JSTokenizer.prototype.string = function() { + + // Parse a string value. + var hex, i, string = '', quote, + uffff; + + // When parsing for string values, we must look for " and \ characters. + if (this.ch === '"' || this.ch === '\'') { + quote = this.ch; + while (this.next()) { + if (this.ch === quote) { + this.next(); + return string; + } + if (this.ch === '\\') { + this.next(); + if (this.ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(this.next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof this.escapee[this.ch] === 'string') { + string += this.escapee[this.ch]; + } else { + break; + } + } else { + string += this.ch; + } + } + } + this.error("Bad string"); + }; + + JSTokenizer.prototype.name = function() { + + // Parse a name value. + var name = '', + allowed = function(ch) { + return ch === "_" || ch === "$" || + (ch >= "0" && ch <= "9") || + (ch >= "a" && ch <= "z") || + (ch >= "A" && ch <= "Z"); + }; + + if (allowed(this.ch)) { + name += this.ch; + } else { + this.error("Bad name"); + } + + while (this.next()) { + if (this.ch === ' ') { + this.next(); + return name; + } + if (this.ch === ':') { + return name; + } + if (allowed(this.ch)) { + name += this.ch; + } else { + this.error("Bad name"); + } + } + this.error("Bad name"); + }; + + JSTokenizer.prototype.white = function() { + + // Skip whitespace. + while (this.ch && this.ch <= ' ') { + this.next(); + } + }; + + JSTokenizer.prototype.word = function() { + + // true, false, or null. + switch (this.ch) { + case 't': + this.next('t'); + this.next('r'); + this.next('u'); + this.next('e'); + return true; + case 'f': + this.next('f'); + this.next('a'); + this.next('l'); + this.next('s'); + this.next('e'); + return false; + case 'n': + this.next('n'); + this.next('u'); + this.next('l'); + this.next('l'); + return null; + } + this.error("Unexpected '" + this.ch + "'"); + }; + + //value, // Place holder for the value function. + JSTokenizer.prototype.array = function() { + + // Parse an array value. + var array = []; + + if (this.ch === '[') { + this.next('['); + this.white(); + if (this.ch === ']') { + this.next(']'); + return array; // empty array + } + while (this.ch) { + array.push(this.value()); + this.white(); + if (this.ch === ']') { + this.next(']'); + return array; + } + this.next(','); + this.white(); + } + } + this.error("Bad array"); + }; + + var object = function() { + + // Parse an object value. + var key, object = {}; + + if (this.ch === '{') { + this.next('{'); + this.white(); + if (this.ch === '}') { + this.next('}'); + return object; // empty object + } + while (this.ch) { + if (this.ch >= "0" && this.ch <= "9") { + key = this.number(); + } else if (this.ch === '"' || this.ch === '\'') { + key = this.string(); + } else { + key = this.name(); + } + this.white(); + this.next(':'); + if (Object.hasOwnProperty.call(object, key)) { + this.error('Duplicate key "' + key + '"'); + } + object[key] = this.value(); + this.white(); + if (this.ch === '}') { + this.next('}'); + return object; + } + this.next(','); + this.white(); + } + } + this.error("Bad object"); + }; + + JSTokenizer.prototype.value = function() { + + // Parse a JS value. It could be an object, an array, a string, a number, + // or a word. + this.white(); + switch (this.ch) { + case '{': + return object.call(this); + case '[': + return this.array(); + case '"': + case '\'': + return this.string(); + case '-': + return this.number(); + default: + return this.ch >= '0' && this.ch <= '9' ? this.number() : this.word(); + } + }; + + /** + * Returns the index of the current character. + * + * @private + * @returns {int} The current character's index. + */ + JSTokenizer.prototype.getIndex = function() { + return this.at - 1; + }; + + JSTokenizer.prototype.getCh = function() { + return this.ch; + }; + + JSTokenizer.prototype.init = function(sSource, iIndex) { + this.text = sSource; + this.at = iIndex || 0; + this.ch = ' '; + }; + + /** + * Advances the index in the text to iIndex. Fails if the new index + * is smaller than the previous index. + * + * @private + * @param {int} iIndex - the new index + */ + JSTokenizer.prototype.setIndex = function(iIndex) { + if (iIndex < this.at - 1) { + throw new Error("Must not set index " + iIndex + + " before previous index " + (this.at - 1)); + } + this.at = iIndex; + this.next(); + }; + + /** + * Return the parse function. It will have access to all of the above + * functions and variables. + * + * @private + * @ui5-restricted sap.ui.core + * @static + * @param {string} sSource The js source + * @param {int} iStart The start position + * @returns {object} the JavaScript object + */ + JSTokenizer.parseJS = function(sSource, iStart) { + + var oJSTokenizer = new JSTokenizer(); + var result; + oJSTokenizer.init(sSource, iStart); + result = oJSTokenizer.value(); + + if ( isNaN(iStart) ) { + oJSTokenizer.white(); + if (oJSTokenizer.getCh()) { + oJSTokenizer.error("Syntax error"); + } + return result; + } else { + return { result : result, at : oJSTokenizer.getIndex()}; + } + + }; + +// return JSTokenizer; +//}); + +export default JSTokenizer; diff --git a/src/detectors/transpilers/xml/transpiler.ts b/src/detectors/transpilers/xml/transpiler.ts new file mode 100644 index 000000000..37e698572 --- /dev/null +++ b/src/detectors/transpilers/xml/transpiler.ts @@ -0,0 +1,107 @@ +import {SaxEventType, SAXParser, Tag as SaxTag} from "sax-wasm"; +import {ReadStream} from "node:fs"; +import fs from "node:fs/promises"; +import {finished} from "node:stream/promises"; +import {fileURLToPath} from "node:url"; +import {taskStart} from "../../util/perf.js"; +import {TranspileResult} from "../AbstractTranspiler.js"; +import Parser from "./Parser.js"; +import { getLogger } from "@ui5/logger"; + +const log = getLogger("transpilers:xml:transpiler"); + +export interface ApiExtract { + framework: { + name: string; + version: string; + }; + defaultAggregations: Record; +} + +let saxWasmBuffer: Buffer; +let apiExtract: ApiExtract; + +export async function xmlToJs(resourceName: string, contentStream: ReadStream): Promise { + await init(); + try { + const taskEnd = taskStart("Transpile XML", resourceName, true); + const res = await transpileXmlToJs(resourceName, contentStream); + taskEnd(); + if (!res.source) { + log.verbose(`XML transpiler returned no result for ${resourceName}`); + return res; + } + return res; + } catch (err) { + if (err instanceof Error) { + throw new Error(`Failed to transpile resource ${resourceName}: ${err.message}`, { + cause: err + }); + } else { + throw err; + } + } +} + +let initializing: Promise; +async function init() { + if (initializing) { + return initializing; + } + // Get the path to the WebAssembly binary and load it + const saxPath = fileURLToPath(import.meta.resolve(("sax-wasm/lib/sax-wasm.wasm"))); + const taskEnd = taskStart("XML Transpiler initialization"); + + return initializing = Promise.all([ + fs.readFile(saxPath), + fs.readFile(new URL("../../../../resources/api-extract.json", import.meta.url), {encoding: "utf-8"}) + ]).then(async (results) => { + saxWasmBuffer = results[0]; + apiExtract = JSON.parse(results[1]); + taskEnd(); + }); +} + +async function transpileXmlToJs(resourceName: string, contentStream: ReadStream): Promise { + const parser = new Parser(resourceName, apiExtract); + + // Initialize parser + const options = {highWaterMark: 32 * 1024}; // 32k chunks + const saxParser = new SAXParser( + SaxEventType.OpenTag | SaxEventType.CloseTag, + options); + + saxParser.eventHandler = (event, tag) => { + if (tag instanceof SaxTag) { + if (event === SaxEventType.OpenTag) { + parser.pushTag(tag); + } else if (event === SaxEventType.CloseTag) { + parser.popTag(tag); + } + } + }; + + // Instantiate and prepare the wasm for parsing + if (!await saxParser.prepareWasm(saxWasmBuffer)) { + throw new Error("Unknown error during WASM Initialization"); + } + + // stream from a file in the current directory + contentStream.on("data", (chunk: Uint8Array) => { + try { + saxParser.write(chunk); + } catch(err) { + if (err instanceof Error) { + // In case of an error, destroy the content stream to make the + // error bubble up to our callers + contentStream.destroy(err); + } else { + throw err; + } + } + }); + await finished(contentStream); + saxParser.end(); + + return parser.generate(); +} diff --git a/src/detectors/typeChecker/FileLinter.ts b/src/detectors/typeChecker/FileLinter.ts new file mode 100644 index 000000000..38e7ed9c2 --- /dev/null +++ b/src/detectors/typeChecker/FileLinter.ts @@ -0,0 +1,388 @@ +import ts, {Identifier} from "typescript"; +import Reporter from "../Reporter.js"; +import {CoverageCategory, LintMessageSeverity, LintResult} from "../AbstractDetector.js"; + +export default class FileLinter { + #filePath: string; + #sourceFile: ts.SourceFile; + #checker: ts.TypeChecker; + #reporter: Reporter; + #boundVisitNode: (node: ts.Node) => void; + + constructor( + rootDir: string, filePath: string, sourceFile: ts.SourceFile, sourceMap: string | undefined, + checker: ts.TypeChecker + ) { + this.#filePath = filePath; + this.#sourceFile = sourceFile; + this.#checker = checker; + this.#reporter = new Reporter(rootDir, filePath, sourceFile, sourceMap); + this.#boundVisitNode = this.visitNode.bind(this); + } + + async getReport(): Promise { + try { + this.visitNode(this.#sourceFile); + return this.#reporter.getReport(); + } catch (err) { + if (err instanceof Error) { + throw new Error(`Failed to produce report for ${this.#filePath}: ${err.message}`, { + cause: err + }); + } + throw err; + } + } + + visitNode(node: ts.Node) { + if (node.kind === ts.SyntaxKind.NewExpression) { // e.g. "new Button({\n\t\t\t\tblocked: true\n\t\t\t})" + const nodeType = this.#checker.getTypeAtLocation(node); // checker.getContextualType(node); + if (nodeType.symbol && this.isSymbolOfUi5OrThirdPartyType(nodeType.symbol)) { + this.analyzeNewExpression(nodeType, node as ts.NewExpression); + } + } else if (node.kind === ts.SyntaxKind.CallExpression) { // ts.isCallLikeExpression too? + // const nodeType = this.#checker.getTypeAtLocation(node); + this.analyzePropertyAccessExpression(node as ts.CallExpression); // Check for global + this.analyzeCallExpression(node as ts.CallExpression); // Check for deprecation + } else if (node.kind === ts.SyntaxKind.PropertyAccessExpression || + node.kind === ts.SyntaxKind.ElementAccessExpression) { + this.analyzePropertyAccessExpression( + node as (ts.PropertyAccessExpression | ts.ElementAccessExpression)); // Check for global + this.analyzePropertyAccessExpressionForDeprecation( + node as (ts.PropertyAccessExpression | ts.ElementAccessExpression)); // Check for deprecation + } else if (node.kind === ts.SyntaxKind.ImportDeclaration) { + this.analyzeImportDeclaration(node as ts.ImportDeclaration); // Check for deprecation + } + + // Traverse the whole AST from top to bottom + ts.forEachChild(node, this.#boundVisitNode); + } + + isDeprecated(symbol: ts.Symbol) : boolean { + if (symbol && this.isSymbolOfUi5Type(symbol)) { + const jsdocTags = symbol.getJsDocTags(this.#checker); + for (const tag of jsdocTags) { + if (tag.name === "deprecated") { + return true; + } + } + } + + return false; + } + + analyzeNewExpression(nodeType: ts.Type, node: ts.NewExpression) { + const classType = this.#checker.getTypeAtLocation(node.expression); + + // There can be multiple and we need to find the right one + const [constructSignature] = classType.getConstructSignatures(); + + node.arguments?.forEach((arg, argIdx) => { + const argumentType = constructSignature.getTypeParameterAtPosition(argIdx); + if (ts.isObjectLiteralExpression(arg)) { + arg.properties.forEach((prop) => { + if (ts.isPropertyAssignment(prop)) { // TODO: Necessary? + const propNameIdentifier = prop.name as Identifier; + const propText = propNameIdentifier.escapedText! || propNameIdentifier.text; + const propertySymbol = argumentType.getProperty(propText); + + // this.#checker.getContextualType(arg) // same as nodeType + // const propertySymbol = allProps.find((symbol) => { + // return symbol.escapedName === propNameIdentifier; + // }); + if (propertySymbol) { + if (this.isDeprecated(propertySymbol)) { + this.#reporter.addMessage({ + node: prop, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-deprecated-api", + message: `Use of deprecated property '${propertySymbol.escapedName}' ` + + `of class '${this.#checker.typeToString(nodeType)}'`, + messageDetails: this.extractDeprecatedMessage(propertySymbol) + }); + } + } + } + }); + } + }); + } + + extractNamespace(node: ts.PropertyAccessExpression) : string { + const propAccessChain: string[] = []; + propAccessChain.push(node.expression.getText()); + + let scanNode: ts.Node = node; + while (ts.isPropertyAccessExpression(scanNode)) { + if (!ts.isIdentifier(scanNode.name)) { + throw new Error( + `Unexpected PropertyAccessExpression node: Expected name to be identifier but got ` + + ts.SyntaxKind[scanNode.name.kind]); + } + propAccessChain.push(scanNode.name.getText()); + scanNode = scanNode.parent; + } + return propAccessChain.join("."); + } + + extractDeprecatedMessage(symbol: ts.Symbol) : string { + if (symbol && this.isSymbolOfUi5Type(symbol)) { + const jsdocTags = symbol.getJsDocTags(this.#checker); + const deprecatedTag = jsdocTags.find((tag) => tag.name === "deprecated"); + + if (deprecatedTag && deprecatedTag.text) { + // (Workaround) There's an issue in some UI5 TS definition versions and where the + // deprecation text gets merged with the description. Splitting on double + // new line could be considered as a clear separation between them. + // https://github.com/SAP/ui5-typescript/issues/429 + return deprecatedTag.text.map((text) => text.text).join("").split("\n\n")[0]; + } + } + + return ""; + } + + analyzeCallExpression(node: ts.CallExpression) { + const exprNode = node.expression; + const exprType = this.#checker.getTypeAtLocation(exprNode); + if (!(exprType?.symbol && this.isSymbolOfUi5OrThirdPartyType(exprType.symbol))) { + this.handleCallExpressionUnknownType(exprType, node); + return; + } + + if (ts.isNewExpression(exprNode)) { + // e.g. new Class()(); + // This is usually unexpected and there are currently no known deprecations of functions + // returned by a class constructor. + // However, the OPA Matchers are a known exception where constructors do return a function. + return; + } + + if (!ts.isPropertyAccessExpression(exprNode) && + !ts.isElementAccessExpression(exprNode) && + !ts.isIdentifier(exprNode)) { + // TODO: Transform into coverage message if it's really ok not to handle this + throw new Error(`Unhandled CallExpression expression syntax: ${ts.SyntaxKind[exprNode.kind]}`); + } + + if (!this.isDeprecatedType(exprType)) { + return; + } + + let symbol; + if (ts.isPropertyAccessExpression(exprNode)) { + symbol = this.#checker.getSymbolAtLocation(exprNode.name); + } else if (ts.isElementAccessExpression(exprNode)) { + symbol = this.#checker.getSymbolAtLocation(exprNode.argumentExpression); + } else { // Identifier + symbol = this.#checker.getSymbolAtLocation(exprNode); + } + + if (!symbol) { + throw new Error(`Failed to determine symbol for deprecated node of type ${ts.SyntaxKind[exprNode.kind]}`); + } + + let additionalMessage = ""; + // Get the type to the left of the call expression (i.e. what the function is being called on) + const classNodeType = this.findClassOrInterface(node.expression); + if (classNodeType) { + additionalMessage = ` of class '${this.#checker.typeToString(classNodeType)}'`; + } else if (ts.isPropertyAccessExpression(exprNode)) { + additionalMessage = ` (${this.extractNamespace(exprNode)})`; + } + this.#reporter.addMessage({ + node, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-deprecated-api", + message: + `Call to deprecated function ` + + `'${symbol.escapedName}'${additionalMessage}`, + messageDetails: this.extractDeprecatedMessage(symbol) + }); + } + + isDeprecatedAccess(node: ts.AccessExpression) : ts.Symbol | undefined{ + let symbol; + if (ts.isPropertyAccessExpression(node)) { + symbol = this.#checker.getSymbolAtLocation(node.name); + } else { // ElementAccessExpression + symbol = this.#checker.getSymbolAtLocation(node.argumentExpression); + } + if (symbol && this.isDeprecated(symbol)) { + return symbol; + } + } + + isDeprecatedType(nodeType: ts.Type) : boolean { + if (nodeType.symbol && this.isDeprecated(nodeType.symbol)) { + return true; + } + return false; + } + + analyzePropertyAccessExpressionForDeprecation(node: ts.AccessExpression) { + if (ts.isCallExpression(node.parent)) { + // TODO: Swap with call expression check? + return; // Already analyzed in context of call expression + } + + const symbol = this.isDeprecatedAccess(node); + if (symbol) { + this.#reporter.addMessage({ + node, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-deprecated-property", + message: + `Access of deprecated property ` + + `'${symbol.escapedName}'`, + messageDetails: this.extractDeprecatedMessage(symbol) + }); + } + } + + handleCallExpressionUnknownType(nodeType: ts.Type, node: ts.CallExpression) { + const typeString = this.#checker.typeToString(nodeType); + let identifier; + if (ts.isPropertyAccessExpression(node.expression)) { + identifier = node.expression.name; + } + if (typeString === "any" && !ts.isImportDeclaration(node.parent.parent)) { + this.#reporter.addCoverageInfo({ + node, + category: CoverageCategory.CallExpressionUnknownType, + message: + `Unable to analyze this method call because the type of identifier` + + `${identifier ? " \"" + identifier.getText() + "\"" : ""} in "${node.getText()}"" ` + + `could not be determined` + }); + } + } + + analyzePropertyAccessExpression(node: ts.AccessExpression | ts.CallExpression) { + const exprNode = node.expression; + if (ts.isIdentifier(exprNode)) { + // The expression being an identifier indicates that this is the first access + // in a possible chain. E.g. the "sap" in "sap.ui.getCore()" + + let symbol; + + // Get the NodeType in order to check whether this is indirect global access via Window + const nodeType = this.#checker.getTypeAtLocation(exprNode); + if (this.#checker.typeToString(nodeType) === "Window & typeof globalThis") { + // In case of Indirect global access we need to check for + // a global UI5 variable on the right side of the expression instead of left + if (ts.isPropertyAccessExpression(node)) { + symbol = this.#checker.getSymbolAtLocation(node.name); + } else if (ts.isElementAccessExpression(node)) { + symbol = this.#checker.getSymbolAtLocation(node.argumentExpression); + } else { // Identifier + symbol = this.#checker.getSymbolAtLocation(node); + } + } else { + // No access via Window. Check the left side of the expression + symbol = this.#checker.getSymbolAtLocation(exprNode); + } + + // If a symbol could be determined, check whether it is a symbol of a UI5 Type. + // Note: If this is a local variable, the symbol would be different + // In case it is, ensure it is not one of the allowed PropertyAccessExpressions, such as "sap.ui.require" + if (symbol && this.isSymbolOfUi5OrThirdPartyType(symbol) && + !(ts.isPropertyAccessExpression(node) && this.isAllowedPropertyAccess(node))) { + this.#reporter.addMessage({ + node, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-globals-js", + message: + `Access of global variable '${symbol.getName()}' `+ + `(${this.extractNamespace(node)})` + }); + } + } + } + + + isAllowedPropertyAccess(node: ts.PropertyAccessExpression): boolean { + if (!ts.isIdentifier(node.expression)) { + // TODO: Fixme if this happens + throw new Error( + `Unhandled PropertyAccessExpression expression syntax: ${ts.SyntaxKind[node.expression.kind]}`); + } + if (["require", "define", "QUnit", "sinon"].includes(node.expression.getText())) { + return true; + } + + const propAccess = this.extractNamespace(node); + return [ + "sap.ui.define", + "sap.ui.require", + "sap.ui.require.toUrl", + "sap.ui.loader.config" + ].some((allowedAccessString) => { + return propAccess == allowedAccessString || propAccess.startsWith(allowedAccessString + "."); + }); + } + + analyzeImportDeclaration(importDeclarationNode: ts.ImportDeclaration) { + const moduleSpecifierNode = importDeclarationNode.moduleSpecifier; + if (!ts.isStringLiteral(moduleSpecifierNode)) { + // An ImportDeclaration moduleSpecifier is of type Expression, but the docs says: + // "If this is not a StringLiteral it will be a grammar error." + // So we ignore such cases here. + return; + } + const symbol = this.#checker.getSymbolAtLocation(moduleSpecifierNode); + // Only check for the "default" export regardless of what's declared + // as UI5 / AMD only supports importing the default anyways. + // TODO: This needs to be enhanced in future + const defaultExportSymbol = symbol?.exports?.get("default" as ts.__String); + if (defaultExportSymbol && this.isDeprecated(defaultExportSymbol)) { + this.#reporter.addMessage({ + node: moduleSpecifierNode, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-deprecated-api", + message: + `Import of deprecated module ` + + `'${moduleSpecifierNode.text}'`, + messageDetails: this.extractDeprecatedMessage(defaultExportSymbol), + }); + } + } + + isSymbolOfUi5Type(symbol: ts.Symbol) { + if (symbol.name.startsWith("sap/")) { + return true; + } else { + const sourceFile = symbol.valueDeclaration?.getSourceFile(); + if (sourceFile?.fileName.match(/@openui5|@sapui5|@ui5/)) { + return true; + } + } + return false; + } + + isSymbolOfUi5OrThirdPartyType(symbol: ts.Symbol) { + if (symbol.name.startsWith("sap/")) { + return true; + } else { + const sourceFile = symbol.valueDeclaration?.getSourceFile(); + if (sourceFile?.fileName.match(/@openui5|@sapui5|@ui5|@types\/jquery/)) { + return true; + } + } + return false; + } + + findClassOrInterface(node: ts.Node) : ts.Type | undefined { + let nodeType: ts.Type | undefined = this.#checker.getTypeAtLocation(node); + if (nodeType.isClassOrInterface()) { + return nodeType; + } + + // Check child nodes recursively to cover cases such as node being a PropertyAccessExpression + nodeType = ts.forEachChild(node, (childNode) => { + return this.findClassOrInterface(childNode); + }); + + return nodeType; + } +} diff --git a/src/detectors/typeChecker/host.ts b/src/detectors/typeChecker/host.ts new file mode 100644 index 000000000..91678db74 --- /dev/null +++ b/src/detectors/typeChecker/host.ts @@ -0,0 +1,195 @@ +import ts from "typescript"; +import path from "node:path"; +import posixPath from "node:path/posix"; +import {fileURLToPath} from "node:url"; +import fs from "node:fs/promises"; + +function notImplemented(methodName: string) { + throw new Error(`Not implemented: ${methodName}`); +} + +function addPathMappingForPackage(pkgName: string, pathMapping: Map) { + const pkgDir = path.dirname(fileURLToPath(import.meta.resolve(`${pkgName}/package.json`))); + pathMapping.set(pkgName, pkgDir); +} + +async function collectTransitiveDependencies(pkgName: string, deps: Set): Promise> { + const pkgJsonPath = fileURLToPath(import.meta.resolve(`${pkgName}/package.json`)); + const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, "utf8")); + if (pkgJson.dependencies) { + await Promise.all(Object.keys(pkgJson.dependencies).map(async (depName) => { + deps.add(depName); + const depDeps = await collectTransitiveDependencies(depName, deps); + depDeps.forEach((dep) => deps.add(dep)); + })); + } + return deps; +} + +export async function createVirtualCompilerHost( + options: ts.CompilerOptions, files: Map +): Promise { + const typePathMappings = new Map(); + addPathMappingForPackage("typescript", typePathMappings); + + const typePackages = new Set(["@sapui5/types"]); + await collectTransitiveDependencies("@sapui5/types", typePackages); + typePackages.forEach((pkgName) => { + addPathMappingForPackage(pkgName, typePathMappings); + }); + const typePackageDirs = Array.from(typePackages.keys()).map(pkgName => `/types/${pkgName}/`); + + typePackageDirs.push("/types/@ui5/linter/overrides"); + typePathMappings.set("@ui5/linter/overrides", path.dirname( + fileURLToPath(import.meta.resolve("../../../resources/overrides/package.json")) + )); + + options.typeRoots = ["/types"]; + // Request compiler to use all types we found in the dependencies of "@sapui5/types" + options.types = typePackageDirs; + + // Create regex matching all path mapping keys + const pathMappingRegex = new RegExp( + `^\\/types\\/(${Array.from(typePathMappings.keys()).join("|").replaceAll("/", "\\/")})\\/(.*)`); + + if (!options.rootDir) { + throw new Error(`Missing option 'rootDir'`); + } + + function mapToTypePath(fileName: string): string | undefined { + const pkgName = fileName.match(pathMappingRegex); + if (pkgName && pkgName.length === 3) { + const mappedPath = typePathMappings.get(pkgName[1]); + if (mappedPath) { + return path.join(mappedPath, pkgName[2]); + } + } + } + + function getFile(fileName: string) : string | undefined { + // NOTE: This function should be kept in sync with "fileExists" + + if (files.has(fileName)) { + return files.get(fileName); + } + if (fileName.startsWith("/types/")) { + const fsPath = mapToTypePath(fileName); + if (fsPath) { + return ts.sys.readFile(fsPath); + } + } + // console.log("Not found " + fileName); + } + + // Pre-compile list of all directories + const directories = new Set(); + for (const filePath of files.keys()) { + // Add every directory of the file path to the set of directories + let directory = posixPath.dirname(filePath); + while (directory !== "/") { + directories.add(directory); + directory = posixPath.dirname(directory); + } + } + + for (const typePackageDir of typePackageDirs) { + // Add every directory of the type package path to the set of directories + let directory = typePackageDir; + while (directory !== "/") { + directories.add(directory); + directory = posixPath.dirname(directory); + } + } + + const sourceFileCache = new Map(); + return { + directoryExists: (directory) => { + if (directories.has(directory)) { + return true; + } + if (directory.startsWith("/types")) { + // Check whether any mapped directory path begins with the requested directory + // Check within mapped paths by rewriting the requested path + if (!directory.endsWith("/")) { + // Ensure trailing slash to make sure we only match directories, + // because compiler sometimes asks for paths like "[...]/controller/Main.controller". + // Which could match the beginning of a file's path too + directory += "/"; + } + const fsPath = mapToTypePath(directory); + if (fsPath) { + return ts.sys.directoryExists(fsPath); + } + } + return false; + }, + fileExists: (fileName) => { + // NOTE: This function should be kept in sync with "getFile" + + if (files.has(fileName)) { + return true; + } + if (fileName.startsWith("/types/")) { + const fsPath = mapToTypePath(fileName); + if (fsPath) { + return ts.sys.fileExists(fsPath); + } + } + return false; + }, + getCurrentDirectory: () => options.rootDir || "/", + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getDirectories: (directory: string) => { + // This function seems to be called only if the "types" option is not set + // console.log(`getDirectories: ${directory}`); + return []; + }, + readDirectory: ( + dirPath: string, extensions?: readonly string[], + exclude?: readonly string[], include?: readonly string[], + depth?: number + ): string[] => { + // This function doesn't seem to be called during normal operations + // console.log(`readDirectory: ${dirPath}`); + return Array.from(files.keys()).filter((filePath) => { + if (include || exclude || depth || extensions) { + notImplemented("readDirectory: Optional parameters"); + } + return posixPath.dirname(filePath) === dirPath; + }); + }, + getSourceFile: ( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) => { + // console.log(`getSourceFile ${fileName}`); + if (sourceFileCache.has(fileName)) { + return sourceFileCache.get(fileName); + } + const sourceText = getFile(fileName); + if (sourceText === undefined) { + throw new Error(`File not found: ${fileName}`); + } + + const sourceFile = ts.createSourceFile(fileName, sourceText, languageVersion); + sourceFileCache.set(fileName, sourceFile); + return sourceFile; + }, + readFile: (fileName) => { + // console.log(`readFile ${fileName}`); + return getFile(fileName); + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + writeFile: (fileName, contents) => { + // We don't expect this function to be called for our use case so far + notImplemented("write"); + // files.set(fileName, contents); + }, + getCanonicalFileName: fileName => fileName, + getDefaultLibFileName: (defaultLibOptions: ts.CompilerOptions) => { + return ts.getDefaultLibFileName(defaultLibOptions); + }, + getDefaultLibLocation: () => "/types/typescript/lib", + getNewLine: () => "\n", + useCaseSensitiveFileNames: () => true, + }; +} diff --git a/src/detectors/typeChecker/index.ts b/src/detectors/typeChecker/index.ts new file mode 100644 index 000000000..cc1af5ccc --- /dev/null +++ b/src/detectors/typeChecker/index.ts @@ -0,0 +1,329 @@ +import ts from "typescript"; +import path from "node:path"; +import fs from "node:fs"; +import {createAdapter, createResource} from "@ui5/fs/resourceFactory"; +import {createVirtualCompilerHost} from "./host.js"; +import FileLinter from "./FileLinter.js"; +import Reporter from "../Reporter.js"; +import {taskStart} from "../util/perf.js"; +import {amdToEsm} from "../transpilers/amd/transpiler.js"; +import {xmlToJs} from "../transpilers/xml/transpiler.js"; +import {lintManifest} from "../../linter/json/linter.js"; +import { + FileBasedDetector, LintMessage, LintMessageSeverity, LintResult, ProjectBasedDetector +} from "../AbstractDetector.js"; +import {Project} from "@ui5/project"; +import {Resource} from "@ui5/fs"; + +const DEFAULT_OPTIONS: ts.CompilerOptions = { + target: ts.ScriptTarget.ES2022, + module: ts.ModuleKind.ES2022, + moduleResolution: ts.ModuleResolutionKind.NodeNext, + // Skip lib check to speed up linting. Libs should generally be fine, + // we might want to add a unit test doing the check during development + skipLibCheck: true, + // Include standard typescript libraries for ES2022 and DOM support + lib: ["lib.es2022.d.ts", "lib.dom.d.ts"], + // Allow and check JavaScript files since this is everything we'll do here + allowJs: true, + checkJs: true, + strict: true, + noImplicitAny: false, + strictNullChecks: false, + strictPropertyInitialization: false, + rootDir: "/", + // Library modules (e.g. sap/ui/core/library.js) do not have a default export but + // instead have named exports e.g. for enums defined in the module. + // However, in current JavaScript code (UI5 AMD) the whole object is exported, as there are no + // named exports outside of ES Modules / TypeScript. + // This property compensates this gap and tries to all usage of default imports where actually + // no default export is defined. + // NOTE: This setting should not be used when analyzing TypeScript code, as it would allow + // using an default import on library modules, which is not intended. + // A better solution: + // During transpilation, for every library module (where no default export exists), + // an "import * as ABC" instead of a default import is created. + // This logic needs to be in sync with the generator for UI5 TypeScript definitions. + allowSyntheticDefaultImports: true +}; + +export class TsProjectDetector extends ProjectBasedDetector { + compilerOptions: ts.CompilerOptions; + #projectBasePath: string; + + constructor(project: Project) { + super(project); + this.compilerOptions = { ...DEFAULT_OPTIONS }; + + const namespace = project.getNamespace(); + this.#projectBasePath = `/resources/${namespace}/`; + this.compilerOptions.paths = { + [`${namespace}/*`]: [`${this.#projectBasePath}*`] + }; + } + + private async writeTransformedSources(fsBasePath: string, originalResourcePath: string, + source: string, map: string | undefined) { + const transformedWriter = createAdapter({ + fsBasePath, + virBasePath: "/" + }); + + await transformedWriter.write( + createResource({ + path: originalResourcePath + ".ui5lint.transformed.js", + string: source + }) + ); + + if (map) { + await transformedWriter.write( + createResource({ + path: originalResourcePath + ".ui5lint.transformed.js.map", + string: JSON.stringify(JSON.parse(map), null, "\t") + }) + ); + } + } + + private getModuleId(resourcePath: string) { + let resourcePathHeader = "/resources/"; + if (resourcePath.startsWith("/test-resources/")) { + resourcePathHeader = "/test-resources/"; + } + return resourcePath.substring(resourcePathHeader.length); + } + + private async analyzeFiles(all: Resource[], resources: Map, sourceMaps: Map, + resourceMessages: Map, vfsToFsPaths: Map, result: LintResult[]) { + return Promise.all(all.map(async (resource: Resource) => { + const originalResourcePath = resource.getPath(); + const fsPath = resource.getSourceMetadata().fsPath; + + let source: string, map: string | undefined, messages: LintMessage[] | undefined; + let resourcePath = originalResourcePath; + try { + if (resourcePath.endsWith(".xml")) { + resourcePath = resourcePath.replace(/\.xml$/, ".js"); + const resourceContent = await resource.getStream(); + ({ source, map, messages } = + await xmlToJs(path.basename(originalResourcePath), resourceContent)); + } else if (resourcePath.endsWith(".js")) { + const resourceContent = await resource.getString(); + const id = this.getModuleId(resourcePath); + ({ source, map } = amdToEsm(id, resourceContent)); + } else if (resourcePath.endsWith(".json")) { + resourcePath = resourcePath.replace(/\.json$/, ".js"); + const resourceContent = await resource.getString(); + ({ source, messages } = await lintManifest(resourcePath, resourceContent)); + } else { + throw new Error(`Unsupported file type for ${resourcePath}`); + } + } catch (err: unknown) { + const message = err instanceof Error ? err.message : String(err); + const errorLinterReporter = new Reporter(this.project.getRootPath(), fsPath); + errorLinterReporter.addMessage({ + severity: LintMessageSeverity.Error, + message, + ruleId: "ui5-linter-parsing-error", + fatal: true + }); + result.push(errorLinterReporter.getReport()); + return; + } + vfsToFsPaths.set(resourcePath, fsPath); + + resources.set(resourcePath, source); + if (messages && messages.length) { + resourceMessages.set(resourcePath, messages); + } + if (map) { + sourceMaps.set(resourcePath, map); + } + if (process.env.UI5LINT_WRITE_TRANSFORMED_SOURCES) { + await this.writeTransformedSources(process.env.UI5LINT_WRITE_TRANSFORMED_SOURCES, + originalResourcePath, source, map); + } + })); + } + + async createReports(filePaths: string[]) { + const result: LintResult[] = []; + const reader = this.project.getReader({ + style: "buildtime" + }); + + // Read all resources and test-resources and their content since tsc works completely synchronous + const globEnd = taskStart("Locating Resources"); + const fileTypes = "{*.js,*.view.xml,*.fragment.xml,manifest.json}"; + const allResources = await reader.byGlob("/resources/**/" + fileTypes); + const allTestResources = await reader.byGlob("/test-resources/**/" + fileTypes); + globEnd(); + const resources = new Map(); + const sourceMaps = new Map(); + const resourceMessages = new Map(); + const vfsToFsPaths = new Map(); + + const transpileTaskEnd = taskStart("Transpiling Resources", `${allResources.length} Resources`); + await this.analyzeFiles(allResources, resources, sourceMaps, resourceMessages, vfsToFsPaths, result); + transpileTaskEnd(); + + const transpileTestResourcesTaskEnd = taskStart("Transpiling Test-Resources", + `${allTestResources.length} Resources`); + await this.analyzeFiles(allTestResources, resources, sourceMaps, resourceMessages, vfsToFsPaths, result); + transpileTestResourcesTaskEnd(); + + /* Handle filePaths parameter: + + Project path will always be absolute. e.g. '/home/user/projects/com.ui5.troublesome.app/' + + filePaths (if provided) can either be absolute or relative + + Absolute example: + '/home/user/projects/com.ui5.troublesome.app/webapp/model/formatter.js/webapp/controller/BaseController.js' + '/home/user/projects/com.ui5.troublesome.app/webapp/model/formatter.js/webapp/model/formatter.js' + + Check: Absolute paths must be located within projectPath + + Relative example: + 'webapp/controller/BaseController.js' + 'webapp/model/formatter.js' + + Task: Always resolve relative paths to the projectPath + (and check the resulting path is within the projectPath) + */ + let resourcePaths: (string | undefined)[]; + if (filePaths && filePaths.length) { + const absoluteFilePaths = filePaths.map((filePath) => { + if (!path.isAbsolute(filePath)) { + // Resolve relative filePaths + filePath = path.join(this.project.getRootPath(), filePath); + } + // Ensure file path is located within project root + if (!filePath.startsWith(this.project.getRootPath())) { + throw new Error( + `File ${filePath} is not located within project root ${this.project.getRootPath()}`); + } + return filePath; + }); + + // Rewrite fs-paths to virtual paths + resourcePaths = allResources.map((res: Resource) => { + if (absoluteFilePaths.includes(res.getSourceMetadata().fsPath)) { + return res.getPath(); + } + }).filter(($: string | undefined) => $); + } else { + resourcePaths = Array.from(resources.keys()); + } + resourcePaths.sort(); + + const host = await createVirtualCompilerHost(this.compilerOptions, resources); + const program = ts.createProgram(resourcePaths as string[], this.compilerOptions, host); + const checker = program.getTypeChecker(); + + const typeCheckDone = taskStart("Linting all transpiled resources"); + for (const sourceFile of program.getSourceFiles()) { + if (!sourceFile.isDeclarationFile && resourcePaths.includes(sourceFile.fileName)) { + const filePath = vfsToFsPaths.get(sourceFile.fileName); + if (!filePath) { + throw new Error(`Failed to get FS path for ${sourceFile.fileName}`); + } + const linterDone = taskStart("Lint resource", filePath, true); + const linter = new FileLinter( + this.project.getRootPath(), filePath, sourceFile, sourceMaps.get(sourceFile.fileName), checker); + const report = await linter.getReport(); + if (resourceMessages.has(sourceFile.fileName)) { + report.messages.push(...resourceMessages.get(sourceFile.fileName)!); + report.errorCount = report.messages + .filter((message) => message.severity === LintMessageSeverity.Error).length; + report.warningCount = report.messages + .filter((message) => message.severity === LintMessageSeverity.Warning).length; + report.fatalErrorCount = report.messages.filter((message) => message.fatal).length; + } + result.push(report); + linterDone(); + } + } + typeCheckDone(); + return result; + } +} + +export class TsFileDetector extends FileBasedDetector { + async createReports(filePaths: string[]) { + const options: ts.CompilerOptions = { + ...DEFAULT_OPTIONS, + rootDir: this.rootDir + }; + + const resources = new Map(); + const sourceMaps = new Map(); + const resourceMessages = new Map(); + const internalToFsFilePaths = new Map(); + const internalfilePaths = await Promise.all(filePaths.map(async (filePath: string) => { + let transformationResult; + filePath = path.join(this.rootDir, filePath); + let internalfilePath = filePath; + if (filePath.endsWith(".js")) { + const fileContent = ts.sys.readFile(filePath); + if (!fileContent) { + throw new Error(`Failed to read file ${filePath}`); + } + transformationResult = amdToEsm(path.basename(filePath, ".js"), fileContent); + } else if (filePath.endsWith(".xml")) { + const fileStream = fs.createReadStream(filePath); + internalfilePath = filePath.replace(/\.xml$/, ".js"); + transformationResult = await xmlToJs(path.basename(filePath), fileStream); + } else if (filePath.endsWith(".json")) { + const fileContent = ts.sys.readFile(filePath); + if (!fileContent) { + throw new Error(`Failed to read file ${filePath}`); + } + internalfilePath = filePath.replace(/\.json$/, ".js"); + transformationResult = await lintManifest(internalfilePath, fileContent); + } else { + throw new Error(`Unsupported file type for ${filePath}`); + } + const { source, map } = transformationResult; + resources.set(internalfilePath, source); + if (map) { + sourceMaps.set(internalfilePath, map); + } + if (transformationResult.messages && transformationResult.messages.length) { + resourceMessages.set(internalfilePath, transformationResult.messages); + } + + internalToFsFilePaths.set(internalfilePath, filePath); + return internalfilePath; + })); + + const host = await createVirtualCompilerHost(options, resources); + const program = ts.createProgram(internalfilePaths, options, host); + const checker = program.getTypeChecker(); + + const result: LintResult[] = []; + + for (const sourceFile of program.getSourceFiles()) { + if (!sourceFile.isDeclarationFile) { + const filePath = internalToFsFilePaths.get(sourceFile.fileName); + if (!filePath) { + throw new Error(`Failed to get FS path for ${sourceFile.fileName}`); + } + const linter = new FileLinter( + this.rootDir, filePath, sourceFile, sourceMaps.get(sourceFile.fileName), checker); + const report = await linter.getReport(); + if (resourceMessages.has(sourceFile.fileName)) { + report.messages.push(...resourceMessages.get(sourceFile.fileName)!); + report.errorCount = report.messages + .filter((message) => message.severity === LintMessageSeverity.Error).length; + report.warningCount = report.messages + .filter((message) => message.severity === LintMessageSeverity.Warning).length; + report.fatalErrorCount = report.messages.filter((message) => message.fatal).length; + } + result.push(report); + } + } + return result; + } +} diff --git a/src/detectors/util/perf.ts b/src/detectors/util/perf.ts new file mode 100644 index 000000000..6051249b6 --- /dev/null +++ b/src/detectors/util/perf.ts @@ -0,0 +1,40 @@ +import {hrtime} from "node:process"; +import figures from "figures"; +import chalk from "chalk"; +import {isLogLevelEnabled, getLogger} from "@ui5/logger"; +const log = getLogger("Trace"); + +export function taskStart(taskName: string, taskData?: string, singleTask?: boolean): () => void { + const startTime = hrtime.bigint(); + return () => { + const elapsedNs = Number(hrtime.bigint() - startTime); + const elapsedMs = elapsedNs / 1_000_000; + const elapsedSec = elapsedNs / 1_000_000_000; + if (isLogLevelEnabled("perf")) { + let msg = `${taskName} took `; + if (elapsedSec >= 1) { + let format = chalk.bold; + if (singleTask) { + format = format.red; + } + msg += format(`${elapsedSec.toFixed(2)} s`); + if (singleTask) { + msg += format(` ${figures.warning} (slow)`); + } + } else { + let format = chalk; + if (elapsedMs > 1) { + format = chalk.bold; + } + if (elapsedMs > 500) { + format = format.yellow; + } + msg += format(`${elapsedMs.toFixed(2)} ms`); + } + if (taskData) { + msg += ` - ${taskData}`; + } + log.perf(msg); + } + }; +} diff --git a/src/formatter/coverage.ts b/src/formatter/coverage.ts new file mode 100644 index 000000000..a798e6ac6 --- /dev/null +++ b/src/formatter/coverage.ts @@ -0,0 +1,158 @@ +import path from "node:path"; +import { + LintResult, + LintMessageSeverity, + CoverageInfo, + CoverageCategory +} from "../detectors/AbstractDetector.js"; +import {readFile} from "fs/promises"; + +const visualizedSpace = "\u00b7"; +const visualizedTab = "\u00bb"; +const visualizedTabs : string[] = []; + +function formatSeverity(severity: LintMessageSeverity) { + if (severity === LintMessageSeverity.Error) { + return "error"; + } else if (severity === LintMessageSeverity.Warning) { + return "warning"; + } else { + throw new Error(`Unknown severity: ${severity}`); + } +} + +function expandTabs(line: string, tabsize = 4) { + let last = 0; + let length = 0; + return line.replace(/[ \t]/g, function(tab, offset) { + length += offset - last; + if ( tab === "\t" ) { + const n = tabsize - length % tabsize; + length += n; + last++; + return visualizedTabs[n] ?? (visualizedTabs[n] = visualizedTab.padEnd(n, " ")); + } + length++; + last++; + return visualizedSpace; + }); +} + +function escape(str: string) { + return str.replace(/&/g, "&").replace(/ + + + + + UI5Lint Coverage Report ${new Date().toLocaleString()} + + +`); + + for (const {filePath, messages, coverageInfo} of lintResults) { + const fileContent = await readFile(filePath, {encoding: "utf-8"}); + const relativeFilePath = path.relative(process.cwd(), filePath); + + this.#writeln(`
${escape(relativeFilePath)}`); + + fileContent.split("\n").forEach((code, i) => { + const line = i + 1; + this.#renderLine( + expandTabs(code), line, + messages.filter((msg) => msg.line === line), + coverageInfo.filter( + (info) => info.line === line && info.category === CoverageCategory.CallExpressionUnknownType + ) + ); + }); + + this.#writeln(`
`); + } + + this.#writeln( + ` +`); + + return this.#buffer; + } + + #renderLine(code: string, line: number, messages: LintResult["messages"], coverageInfo: CoverageInfo[]) { + const classes = ["codeline"]; + if (messages.length) { + classes.push("has-messages"); + } else if (coverageInfo.length) { + classes.push("no-coverage"); + } + + this.#writeln(`
`); + + this.#writeln(`${line}`); + this.#writeln(`${escape(code)}`); + + if (messages.length) { + this.#writeln(`${escape( + messages.map( + (msg) => `${formatSeverity(msg.severity)} ${msg.message}` + ).join(" & ") + )}`); + } + + this.#writeln(`
`); + } + + #write(str: string) { + this.#buffer += str; + } + #writeln(str: string) { + this.#buffer += str + "\n"; + } + +} diff --git a/src/formatter/json.ts b/src/formatter/json.ts new file mode 100644 index 000000000..9c694eb72 --- /dev/null +++ b/src/formatter/json.ts @@ -0,0 +1,39 @@ +import { LintMessage, LintResult } from "../detectors/AbstractDetector.js"; + +export class Json { + format(lintResults: LintResult[], showDetails: boolean) { + const jsonFormattedResults: Pick< + LintResult, + "filePath" + | "messages" + | "errorCount" + | "warningCount" + | "fatalErrorCount" + //excluded by default: "coverageInfo" + >[] = []; + lintResults.forEach((oLintedFile) => { + let aFileMessages: LintMessage[] = oLintedFile.messages; + + // Ignore files without findings (empty messages) + if (aFileMessages && aFileMessages.length > 0) { + // Exclude messageDetails property if CLI option "details" was not provided + if (!showDetails) { + aFileMessages = aFileMessages.map((message: LintMessage) => { + const {messageDetails: _, ...oModifiedMessage} = message; + return oModifiedMessage; + }); + } + + jsonFormattedResults.push({ + filePath: oLintedFile.filePath, + messages: aFileMessages, + errorCount: oLintedFile.errorCount, + warningCount: oLintedFile.warningCount, + fatalErrorCount: oLintedFile.fatalErrorCount, + }); + } + }); + + return JSON.stringify(jsonFormattedResults); + } +} diff --git a/src/formatter/lib/resolveLinks.ts b/src/formatter/lib/resolveLinks.ts new file mode 100644 index 000000000..233344ede --- /dev/null +++ b/src/formatter/lib/resolveLinks.ts @@ -0,0 +1,280 @@ +// This file is a modified copy of ui5-builder/lib/processors/jsdoc/lib/transformApiJson.cjs +// Its purpose is to try to resolve links in lint messages, derived from JSDoc annotations. + +function JSDocUtil(): + {formatTextBlock: (src: string, linkFormatter: (target: string, text: string) => string) => string} { + + function format(src: string, linkFormatter: (target: string, text: string) => string): string { + /* + * regexp to recognize important places in the text + * + * Capturing groups of the RegExp: + * group 1: begin of a pre block + * group 2: end of a pre block + * group 3: begin of a header, implicitly ends a paragraph + * group 4: end of a header, implicitly starts a new paragraph + * group 5: target portion of an inline @link tag + * group 6: (optional) text portion of an inline link tag + * group 7: an empty line which implicitly starts a new paragraph + * + * [--
 block -] [---- some header ----] [---- an inline [@link ...} tag ----] 
+		 *      [---------- an empty line ---------]
+		 */
+		const r =
+			/(
)|(<\/pre>)|()|(<\/h[\d+]>)|\{@link\s+([^}\s]+)(?:\s+([^}]*))?\}|((?:\r\n|\r|\n)[ \t]*(?:\r\n|\r|\n))/gi;
+		let inpre = false;
+		src = src || "";
+		src = src.replace(r, function (match, pre, endpre, header, endheader, linkTarget, linkText) {
+			if (pre) {
+				inpre = true;
+			} else if (endpre) {
+				inpre = false;
+			}
+			if (linkTarget) {
+				if (!inpre) {
+					return linkFormatter(linkTarget, linkText);
+				}
+			}
+			return match;
+		}
+		);
+		return src;
+	}
+	return {
+		formatTextBlock: format,
+	};
+}
+
+function formatUrlToLink (sTarget: string, sText: string): string {
+	return `${sText} (${sTarget})`;
+}
+
+function createLink({name, type, className, text = name, hrefAppend = "", ui5Url}:
+	Record): string {
+	let sLink;
+	// handling module's
+	if (
+		className !== undefined &&
+		(/^module:/.test(name) || /^module:/.test(className))
+	) {
+		name = name.replace(/^module:/, "");
+	}
+	// Build the link
+	// Replace # with its encoded value "%23", as some browsers might not escape it
+	sLink = type ? `${className}%23${type}/${name}` : name;
+	if (hrefAppend) {
+		sLink += hrefAppend;
+	}
+	return `${text} (${ui5Url}/api/${sLink})`;
+}
+
+function _preProcessLinksInTextBlock (sText: string, ui5Url: string): string {
+	const linkFormatter = function (sTarget: string, sText: string): string {
+		let aMatch;
+		// keep the full target in the fallback text
+		sText = sText || sTarget;
+		
+		if (sTarget === "module" && sText.startsWith(":")) {
+			const textChunks = sText.split(" ");
+			sTarget += textChunks[0]; 
+			sText = textChunks[1] || textChunks[0].substring(1);
+		} else if (sTarget === "topic" && sText.startsWith(":")) {
+			sTarget += sText.split(" ")[0];
+			sText = sText.split(" ").slice(1).join(" ");
+		}
+		
+		// If the link has a protocol, do not modify, but open in a new window
+		if (/:\/\//.test(sTarget)) {
+			return formatUrlToLink(sTarget, sText);
+		}
+		// topic:xxx Topic
+		aMatch = sTarget.match(
+			/^topic:(\w{32}(?:#\w*)?(?:\/\w*)?)$/
+		);
+		if (aMatch) {
+			return formatUrlToLink(`${ui5Url}/topic/${aMatch[1]}`, sText);
+		}
+		// demo:xxx Demo, open the demonstration page in a new window
+		aMatch = sTarget.match(/^demo:([a-zA-Z0-9/.]*)$/);
+		if (aMatch) {
+			return formatUrlToLink(`${ui5Url}/test-resources/${aMatch[1]}`, sText);
+		}
+		// sap.x.Xxx.prototype.xxx - In case of prototype we have a link to method
+		aMatch = sTarget.match(
+			/([a-zA-Z0-9.$_]+?)\.prototype\.([a-zA-Z0-9.$_]+)$/
+		);
+		if (aMatch) {
+			return createLink({
+				name: aMatch[2],
+				type: "methods",
+				className: aMatch[1],
+				text: sText,
+				ui5Url,
+			});
+		}
+		// Heuristics: Extend is always a static method
+		// sap.x.Xxx.extend
+		// module:sap/x/Xxx.extend
+		aMatch = sTarget.match(
+			/^(module:)?([a-zA-Z0-9.$_/]+?)\.extend$/
+		);
+		if (aMatch) {
+			const [, sModule, sClass] = aMatch;
+			return createLink({
+				name: sTarget.replace(/^module:/, ""),
+				type: "methods",
+				className: (sModule ? sModule : "") + sClass,
+				text: sText,
+				ui5Url,
+			});
+		}
+		// Constructor links are handled in special manner by the SDK
+		// sap.x.Xxx.constructor
+		// sap.x.Xxx#constructor
+		// module:sap/x/Xxx.constructor
+		// #constructor
+		aMatch = sTarget.match(
+			/^(module:)?([a-zA-Z0-9.$_/]+?)?[.#]constructor$/i
+		);
+		if (aMatch) {
+			const [, sModule, sClass] = aMatch;
+			let sName = "";
+			if (sClass) {
+				sName = (sModule ? sModule : "") + sClass;
+			}
+			return createLink({
+				name: sName,
+				hrefAppend: "#constructor",
+				text: sText,
+				ui5Url,
+			});
+		}
+		// #.setText - local static method
+		// #setText - local instance method
+		// #.setText.from - local nested method
+		aMatch = sTarget.match(/^#(\.)?([a-zA-Z0-9.$_]+)$/);
+		if (aMatch) {
+			return createLink({
+				name: aMatch[2],
+				type: "methods",
+				className: "",
+				text: sText,
+				ui5Url,
+			});
+		}
+		// #annotation:TextArrangement - local annotation
+		aMatch = sTarget.match(/^#annotation:([a-zA-Z0-9$_]+)$/);
+		if (aMatch) {
+			return createLink({
+				name: aMatch[1],
+				type: "annotations",
+				className: "",
+				text: sText,
+				ui5Url,
+			});
+		}
+		// Annotation links
+		// sap.ui.comp.smartfield.SmartField#annotation:TextArrangement
+		// sap.ui.comp.smartfield.SmartField.annotation:TextArrangement
+		// module:sap/ui/comp/smartfield/SmartField.annotation:TextArrangement
+		// module:sap/ui/comp/smartfield/SmartField#annotation:TextArrangement
+		aMatch = sTarget.match(
+			/^(module:)?([a-zA-Z0-9.$_/]+?)[.#]annotation:([a-zA-Z0-9$_]+)$/
+		);
+		if (aMatch) {
+			const [, sModule, sClass, sAnnotation] = aMatch;
+			return createLink({
+				name: sAnnotation,
+				type: "annotations",
+				className: (sModule ? sModule : "") + sClass,
+				text: sText,
+				ui5Url,
+			});
+		}
+		// #event:press - local event
+		aMatch = sTarget.match(/^#event:([a-zA-Z0-9$_]+)$/);
+		if (aMatch) {
+			return createLink({
+				name: aMatch[1],
+				type: "events",
+				className: "",
+				text: sText,
+				ui5Url,
+			});
+		}
+		// Event links
+		// sap.m.Button#event:press
+		// sap.m.Button.event:press
+		// module:sap/m/Button.event:press
+		// module:sap/m/Button#event:press
+		aMatch = sTarget.match(
+			/^(module:)?([a-zA-Z0-9.$_/]+?)[.#]event:([a-zA-Z0-9$_]+)$/
+		);
+		if (aMatch) {
+			const [, sModule, sClass, sEvent] = aMatch;
+			return createLink({
+				name: sEvent,
+				type: "events",
+				className: (sModule ? sModule : "") + sClass,
+				text: sText,
+				ui5Url,
+			});
+		}
+		// sap.m.Button#setText - instance method
+		// module:sap/m/Button#setText
+		aMatch = sTarget.match(
+			/^(module:)?([a-zA-Z0-9.$_/]+)#([a-zA-Z0-9.$_]+)$/
+		);
+		if (aMatch) {
+			const [, sModule, sClass, sMethod] = aMatch;
+			return createLink({
+				name: sMethod,
+				type: "methods",
+				className: (sModule ? sModule : "") + sClass,
+				text: sText,
+				ui5Url,
+			});
+		}
+		// module:sap/m/Button.setText
+		aMatch = sTarget.match(
+			/^(module:)([a-zA-Z0-9.$_/]+)\.([a-zA-Z0-9.$_]+)$/
+		);
+		if (aMatch) {
+			const [, sModule, sClass, sMethod] = aMatch;
+			return createLink({
+				name: `${sClass}.${sMethod}`,
+				type: "methods",
+				className: (sModule ? sModule : "") + sClass,
+				text: sText,
+				ui5Url,
+			});
+		}
+
+		const aTarget = sTarget.split(".");
+		if (aTarget.length >= 3) {
+			const constructorName = aTarget.find((el) => el.toLowerCase() !== el);
+			let index = aTarget.indexOf(constructorName || "");
+			index = (index === -1) ? aTarget.length : (index + 1);
+			// Lacking of complimentary information for the type, then construct the
+			// link to the class name, so the user could find the information on their own.
+			return createLink({
+				name: aTarget.slice(0, index).join("."),
+				text: sText,
+				ui5Url,
+			});
+		}
+
+		// Possible forward reference - we will treat them as symbol link
+		return createLink({name: sTarget, text: sText, ui5Url});
+	};
+
+	return JSDocUtil().formatTextBlock(sText, linkFormatter);
+}
+
+export function resolveLinks (description?: string, ui5Url: string = "https://ui5.sap.com/1.120/#"): string {
+	if (!description) {
+		return "";
+	}
+
+	return _preProcessLinksInTextBlock(description, ui5Url);
+}
diff --git a/src/formatter/text.ts b/src/formatter/text.ts
new file mode 100644
index 000000000..17960a297
--- /dev/null
+++ b/src/formatter/text.ts
@@ -0,0 +1,125 @@
+import chalk from "chalk";
+import {LintMessageSeverity, LintResult, LintMessage} from "../detectors/AbstractDetector.js";
+
+function formatSeverity(severity: LintMessageSeverity) {
+	if (severity === LintMessageSeverity.Error) {
+		return chalk.red("error");
+	} else if (severity === LintMessageSeverity.Warning) {
+		return chalk.yellow("warning");
+	} else {
+		throw new Error(`Unknown severity: ${severity}`);
+	}
+}
+
+function formatLocation(line: LintMessage["line"], column: LintMessage["column"],
+	lineInfoLength: number, columnInfoLength: number) {
+
+	const lineStr = (line === undefined ? "?" : line.toString()).padStart(lineInfoLength, " ");
+	const columnStr = (column === undefined ? "?" : column.toString()).padEnd(columnInfoLength, " ");
+
+	return chalk.dim(`${lineStr}:${columnStr}`);
+}
+
+export class Text {
+	#buffer: string = "";
+
+	format(lintResults: LintResult[], showDetails: boolean) {
+		this.#writeln("");
+		this.#writeln(`## UI5Lint Report (${new Date().toLocaleString()}) ##`);
+		this.#writeln("");
+		let totalErrorCount = 0;
+		let totalWarningCount = 0;
+		let totalFatalErrorCount = 0;
+		// Sort files alphabetically
+		lintResults.sort((a, b) => {
+			return a.filePath.localeCompare(b.filePath);
+		});
+		lintResults.forEach(({filePath, messages, errorCount, warningCount, fatalErrorCount}) => {
+			if (!errorCount && !warningCount) {
+				return;
+			}
+			totalErrorCount += errorCount;
+			totalWarningCount += warningCount;
+			totalFatalErrorCount += fatalErrorCount;
+
+			this.#writeln(chalk.inverse(filePath));
+
+			// Group messages by rule
+			const rules = new Map();
+			let maxLine = 0; // Needed for formatting
+			let maxColumn = 0; // Needed for formatting
+			messages.forEach((msg) => {
+				const entry = rules.get(msg.ruleId);
+				if (entry) {
+					entry.push(msg);
+				} else {
+					rules.set(msg.ruleId, [msg]);
+				}
+				if (msg.line && msg.line > maxLine) {
+					maxLine = msg.line;
+				}
+				if (msg.column && msg.column > maxColumn) {
+					maxColumn = msg.column;
+				}
+			});
+
+			const lineInfoLength = maxLine.toString().length;
+			const columnInfoLength = maxColumn.toString().length;
+
+			let addNewLineAfterModule = true;
+			// Sort rules alphabetically
+			Array.from(rules.keys()).sort((a, b) => {
+				return a.localeCompare(b);
+			}).forEach((ruleId) => {
+				const messages = rules.get(ruleId);
+				if (messages) {
+					this.#writeln(chalk.bold(`  ${ruleId} (${messages.length})`));
+					messages.forEach((msg) => {
+						const messageDetails = (showDetails && msg.messageDetails) ? 
+							(`\n      ${chalk.white.bold("Details:")}\n      ` +
+							`${chalk.italic(msg.messageDetails.replaceAll("\n", "\n      "))}`) : 
+							"";
+
+						this.#writeln(
+							`    ${formatLocation(msg.line, msg.column, lineInfoLength, columnInfoLength)} ` +
+							`${formatSeverity(msg.severity)} ` +
+							`${msg.message}` + 
+							`${messageDetails}`);
+
+						addNewLineAfterModule = true;
+						if (messageDetails) {
+							this.#writeln("");
+							addNewLineAfterModule = false;
+						}
+					});
+				}
+			});
+
+			if (addNewLineAfterModule) {
+				this.#writeln("");
+			}
+		});
+
+		this.#writeln(
+			`${totalErrorCount + totalWarningCount} problems ` +
+			`(${totalErrorCount} errors, ${totalWarningCount} warnings)`);
+		if (totalFatalErrorCount) {
+			this.#writeln(`${totalFatalErrorCount} fatal errors`);
+		}
+
+		if (!showDetails && (totalErrorCount + totalWarningCount + totalFatalErrorCount) > 0) {
+			this.#writeln("");
+			this.#writeln(chalk.dim.bold("Note: ") +
+				chalk.dim(`Use "ui5lint --details" to show more information about the findings`));
+		}
+		
+		return this.#buffer;
+	}
+
+	#write(str: string) {
+		this.#buffer += str;
+	}
+	#writeln(str: string) {
+		this.#buffer += str + "\n";
+	}
+}
diff --git a/src/linter/json/ManifestLinter.ts b/src/linter/json/ManifestLinter.ts
new file mode 100644
index 000000000..c8e936ca6
--- /dev/null
+++ b/src/linter/json/ManifestLinter.ts
@@ -0,0 +1,109 @@
+import type {
+	SAPJSONSchemaForWebApplicationManifestFile,
+	JSONSchemaForSAPUI5Namespace,
+	JSONSchemaForSAPAPPNamespace,
+	Model as ManifestModel,
+	DataSource as ManifestDataSource
+} from "../../manifest.d.ts";
+import type {LintResult} from "../../detectors/AbstractDetector.js";
+
+import ManifestReporter from "./ManifestReporter.js";
+import {LintMessageSeverity} from "../../detectors/AbstractDetector.js";
+import jsonMap from "json-source-map";
+
+type locType = {
+	line: number,
+	column: number,
+	pos: number,
+}
+
+export type jsonMapPointers = Record;
+
+export type jsonSourceMapType = {
+	data: SAPJSONSchemaForWebApplicationManifestFile,
+	pointers: jsonMapPointers
+}
+
+export default class ManifestLinter {
+	#reporter: ManifestReporter | null;
+	#content: string = "";
+	#path: string = "";
+
+	constructor(content: string, path: string) {
+		this.#reporter = null;
+		this.#content = content;
+		this.#path = path;
+	}
+
+	async getReport(): Promise {
+		const source = this.#parseManifest(this.#content);
+		this.#reporter = new ManifestReporter(this.#path, source);
+		this.#analyzeManifest(source.data);
+
+		const report = this.#reporter.getReport();
+		return report;
+	}
+
+	#parseManifest(manifest: string): jsonSourceMapType {
+		return jsonMap.parse(manifest);
+	}
+
+	#analyzeManifest(manifest: SAPJSONSchemaForWebApplicationManifestFile) {
+		const {resources, models} = manifest["sap.ui5"] ?? {};
+		const {dataSources} = manifest["sap.app"] ?? {};
+
+		if (resources && resources.js) {
+			this.#reporter?.addMessage({
+				node: "/sap.ui5/resources/js",
+				severity: LintMessageSeverity.Error,
+				ruleId: "ui5-linter-no-deprecated-api",
+				message: `Use of deprecated property 'sap.ui5/resources/js'`,
+			});
+		}
+
+		const modelKeys: string[] = (models && Object.keys(models)) || [];
+		modelKeys.forEach((modelKey: string) => {
+			const curModel: ManifestModel = (models && (models[modelKey])) || {};
+
+			if (!curModel.type) {
+				const curDataSource = dataSources && curModel.dataSource &&
+					dataSources[curModel.dataSource];
+
+				if (curDataSource &&
+					/* if not provided dataSource.type="OData" */
+					(curDataSource.type === "OData" || !curDataSource.type)) {
+					curModel.type = curDataSource.settings?.odataVersion === "4.0" ?
+						"sap.ui.model.odata.v4.ODataModel" :
+						"sap.ui.model.odata.v2.ODataModel";
+				}
+				// There are other types that can be found in sap/ui/core/Component, but the one
+				// we actually care here is just the "sap.ui.model.odata.v4.ODataModel"
+			}
+
+			if (curModel.type && [
+				"sap.ui.model.odata.ODataModel",
+				"sap.zen.dsh.widgets.SDKModel"
+			].includes(curModel.type)) {
+				this.#reporter?.addMessage({
+					node: `/sap.ui5/models/${modelKey}/type`,
+					severity: LintMessageSeverity.Error,
+					ruleId: "ui5-linter-no-deprecated-api",
+					message: `Use of deprecated model type ` +
+						`'sap.ui5/models/${modelKey}/type="${curModel.type}"'`
+				});
+			}
+
+			if (curModel.type === "sap.ui.model.odata.v4.ODataModel" &&
+				curModel.settings && "synchronizationMode" in curModel.settings) {
+
+				this.#reporter?.addMessage({
+					node: `/sap.ui5/models/${modelKey}/settings/synchronizationMode`,
+					severity: LintMessageSeverity.Error,
+					ruleId: "ui5-linter-no-deprecated-api",
+					message: `Use of deprecated property ` +
+						`'sap.ui5/models/${modelKey}/settings/synchronizationMode' of sap.ui.model.odata.v4.ODataModel`
+				});
+			}
+		});
+	}
+}
diff --git a/src/linter/json/ManifestReporter.ts b/src/linter/json/ManifestReporter.ts
new file mode 100644
index 000000000..fb71d1ef5
--- /dev/null
+++ b/src/linter/json/ManifestReporter.ts
@@ -0,0 +1,95 @@
+import type {BaseReporter, ReporterMessage, ReporterCoverageInfo, PositionInfo,} from "../../detectors/BaseReporter.js";
+import type {LintMessage} from "../../detectors/AbstractDetector.js";
+import type {jsonSourceMapType, jsonMapPointers} from "./ManifestLinter.js";
+import {LintMessageSeverity, CoverageInfo} from "../../detectors/AbstractDetector.js";
+
+
+export default class ManifestReporter implements BaseReporter {
+	#filePath: string;
+	#pointers: jsonMapPointers;
+	#messages: LintMessage[] = [];
+	#coverageInfo: CoverageInfo[] = [];
+
+	constructor(filePath: string, manifest: jsonSourceMapType) {
+		this.#filePath = filePath;
+		this.#pointers = manifest.pointers;
+	}
+
+	addMessage({node, message, severity, ruleId, fatal = undefined}: ReporterMessage) {
+		if (fatal && severity !== LintMessageSeverity.Error) {
+			throw new Error(`Reports flagged as "fatal" must be of severity "Error"`);
+		}
+
+		const {line, column} = this.#getPosition(node);
+
+		this.#messages.push({
+			ruleId,
+			severity,
+			fatal,
+			line,
+			column,
+			message,
+		});
+	}
+
+	addCoverageInfo({node, message, category}: ReporterCoverageInfo) {
+		const location = this.#getPositionsForNode(node);
+		this.#coverageInfo.push({
+			category,
+			// One-based to be aligned with most IDEs
+			line: location.key.line,
+			column: location.key.column,
+			endLine: location.valueEnd.line,
+			endColumn: location.valueEnd.column,
+			message,
+		});
+	}
+
+	#getPositionsForNode(path: string) {
+		const location = this.#pointers[path];
+
+		return location || {key: 1, keyEnd: 1, value: 1, valueEnd: 1};
+	}
+
+	#getPosition(path: string): PositionInfo {
+		let line = 1;
+		let column = 1;
+
+		const location = this.#pointers[path];
+
+		if (location) {
+			line = location.key.line + 1;
+			column = location.key.column + 1;
+		}
+
+		return {
+			line,
+			column
+		};
+	}
+
+	getReport() {
+		let errorCount = 0;
+		let warningCount = 0;
+		let fatalErrorCount = 0;
+		for (const {severity, fatal} of this.#messages) {
+			if (severity === LintMessageSeverity.Error) {
+				errorCount++;
+				if (fatal) {
+					fatalErrorCount++;
+				}
+			} else {
+				warningCount++;
+			}
+		}
+
+		return {
+			filePath: this.#filePath,
+			messages: this.#messages,
+			coverageInfo: this.#coverageInfo,
+			errorCount,
+			warningCount,
+			fatalErrorCount,
+		};
+	}
+}
diff --git a/src/linter/json/linter.ts b/src/linter/json/linter.ts
new file mode 100644
index 000000000..942072c11
--- /dev/null
+++ b/src/linter/json/linter.ts
@@ -0,0 +1,14 @@
+
+import ManifestLinter from "./ManifestLinter.js";
+import {taskStart} from "../../detectors/util/perf.js";
+
+import type {TranspileResult} from "../../detectors/transpilers/AbstractTranspiler.js";
+
+export async function lintManifest(resourceName: string, content: string): Promise {
+	const taskLintEnd = taskStart("Static lint", resourceName);
+	const linter = new ManifestLinter(content, resourceName);
+	const {messages} = await linter.getReport();
+	taskLintEnd();
+
+	return {messages, source: content, map: ""};
+}
\ No newline at end of file
diff --git a/src/linter/linter.ts b/src/linter/linter.ts
new file mode 100644
index 000000000..4c97829b2
--- /dev/null
+++ b/src/linter/linter.ts
@@ -0,0 +1,101 @@
+import {graphFromObject} from "@ui5/project/graph";
+import {LintResult} from "../detectors/AbstractDetector.js";
+import {TsFileDetector, TsProjectDetector} from "../detectors/typeChecker/index.js";
+import {taskStart} from "../detectors/util/perf.js";
+import path from "node:path";
+import {stat} from "node:fs/promises";
+
+interface LinterOptions {
+	rootDir: string,
+	filePaths: string[]
+}
+
+async function fsStat(fsPath: string) {
+	try {
+		return await stat(fsPath);
+		// eslint-disable-next-line @typescript-eslint/no-explicit-any
+	} catch (err: any) {
+		// "File or directory does not exist"
+		if (err.code === "ENOENT") {
+			return false;
+		} else {
+			throw err;
+		}
+	}
+}
+
+async function dirExists(dirPath: string) {
+	const stats = await fsStat(dirPath);
+	return stats && stats.isDirectory();
+}
+
+async function fileExists(dirPath: string) {
+	const stats = await fsStat(dirPath);
+	return stats && stats.isFile();
+}
+
+async function getProjectGraph(rootDir: string) {
+	let rootConfigPath, rootConfiguration;
+	const ui5YamlPath = path.join(rootDir, "ui5.yaml");
+	if (await fileExists(ui5YamlPath)) {
+		rootConfigPath = ui5YamlPath;
+	} else {
+		const isApp = await dirExists(path.join(rootDir, "webapp"));
+		if (isApp) {
+			rootConfiguration = {
+				specVersion: "3.0",
+				type: "application",
+				metadata: {
+					name: "ui5-linter-target"
+				}
+			};
+		} else {
+			const isLibrary = await dirExists(path.join(rootDir, "src"));
+			if (isLibrary) {
+				rootConfiguration = {
+					specVersion: "3.0",
+					type: "library",
+					metadata: {
+						name: "ui5-linter-target"
+					}
+				};
+			}
+		}
+	}
+
+	if (!rootConfigPath && !rootConfiguration) {
+		throw new Error(
+			`Unable to find a UI5 project at ${rootDir}. \n` +
+			`Please make sure to run "ui5lint" in the root directory of your UI5 project.`
+		);
+	}
+
+	return graphFromObject({
+		dependencyTree: {
+			id: "ui5-linter-target",
+			version: "1.0.0",
+			path: rootDir,
+			dependencies: []
+		},
+		rootConfigPath,
+		rootConfiguration,
+		resolveFrameworkDependencies: false
+	});
+}
+
+export async function lintProject({rootDir, filePaths}: LinterOptions) : Promise {
+	const lintEnd = taskStart("Linting Project");
+	const projectGraphDone = taskStart("Project Graph creation");
+	const graph = await getProjectGraph(rootDir);
+	const project = graph.getRoot();
+	projectGraphDone();
+	const tsDetector = new TsProjectDetector(project);
+	const res = await tsDetector.createReports(filePaths);
+	lintEnd();
+	return res;
+}
+
+export async function lintFile({rootDir, filePaths}: LinterOptions) : Promise {
+	const tsDetector = new TsFileDetector(rootDir);
+	return await tsDetector.createReports(filePaths);
+}
diff --git a/src/manifest.d.ts b/src/manifest.d.ts
new file mode 100644
index 000000000..bf664805d
--- /dev/null
+++ b/src/manifest.d.ts
@@ -0,0 +1,3589 @@
+/* eslint-disable */
+/**
+ * This file was automatically generated by json-schema-to-typescript.
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
+ * and run json-schema-to-typescript to regenerate this file.
+ */
+
+/**
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\-]*$".
+ */
+export type TerminologySetting =
+  | {
+      /**
+       * Represents the alternative for bundleUrl
+       */
+      bundleName: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+    }
+  | {
+      /**
+       * Represents the URL for the resource bundle
+       */
+      bundleUrl: string;
+      /**
+       * Indicates whether url is relative to component (default) or manifest
+       */
+      bundleUrlRelativeTo?: "manifest" | "component";
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+    };
+export type EnhanceWithSetting =
+  | {
+      /**
+       * Represents property url for model enhancement
+       */
+      bundleUrl: string;
+      /**
+       * Indicates whether url is relative to component (default) or manifest
+       */
+      bundleUrlRelativeTo?: "manifest" | "component";
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    }
+  | {
+      /**
+       * Represents the alternative for bundleUrl
+       */
+      bundleName: string;
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    };
+export type EnhanceWithSetting1 =
+  | {
+      /**
+       * Represents property url for model enhancement
+       */
+      bundleUrl: string;
+      /**
+       * Indicates whether url is relative to component (default) or manifest
+       */
+      bundleUrlRelativeTo?: "manifest" | "component";
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    }
+  | {
+      /**
+       * Represents the alternative for bundleUrl
+       */
+      bundleName: string;
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    };
+export type Version = string;
+export type Tag = (string | string)[];
+/**
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]*$".
+ */
+export type DataSource = DataSourceEnum | DataSourceCustom;
+export type ObjectName = string;
+export type ObjectType = "query" | "cdsprojectionview" | "view" | "inamodel";
+/**
+ * Represents sapui5 attributes
+ */
+export type JSONSchemaForSAPUI5Namespace = {
+  /**
+   *  Represents SAPUI5 attributes format version. It is managed by namespace owner
+   */
+  _version?:
+    | "1.1.0"
+    | "1.2.0"
+    | "1.3.0"
+    | "1.4.0"
+    | "1.5.0"
+    | "1.6.0"
+    | "1.7.0"
+    | "1.8.0"
+    | "1.9.0"
+    | "1.10.0"
+    | "1.11.0"
+    | "1.12.0"
+    | "1.13.0"
+    | "1.14.0"
+    | "1.15.0"
+    | "1.16.0"
+    | "1.17.0";
+  resources?: Resource;
+  /**
+   * Represents the explicit usage declaration for UI5 reuse components
+   */
+  componentUsages?: {
+    [k: string]: ComponentUsages;
+  };
+  /**
+   * Represents external dependences such as libraries or components, that will be loaded by UI5 Core in the initialization phase of your Component and can be used after it
+   */
+  dependencies: {
+    /**
+     * Represents the minimum version of SAP UI5 that your component requires
+     */
+    minUI5Version: string;
+    /**
+     * Represents the id (namespace) of the libraries that should be loaded by UI5 Core to be used in your component
+     */
+    libs?: {
+      [k: string]: Lib;
+    };
+    /**
+     * Represents the id (namespace) of the components that should be loaded by UI5 Core to be used in your component
+     */
+    components?: {
+      [k: string]: Component;
+    };
+  };
+  /**
+   * Represents models which should be created/destroyed with the life-cycle of the component
+   */
+  models?: {
+    [k: string]: Model;
+  };
+  /**
+   * Represents relative path to the resource. Only relative path allowed, no '../'
+   */
+  resourceRoots?: {
+    [k: string]: ResourceRoot;
+  };
+  /**
+   * Represents the usage of validation handling by MessageManager for this component (enable/disable)
+   */
+  handleValidation?: boolean;
+  /**
+   * Represents the static configuration for components
+   */
+  config?: {
+    [k: string]: Config;
+  };
+  /**
+   * Represents the extension of an additional component
+   */
+  extends?: {
+    /**
+     * Represents the component name
+     */
+    component?: string;
+    /**
+     * Represents minimal version of the component
+     */
+    minVersion?: string;
+    /**
+     * Represents extensions of the component
+     */
+    extensions?: {
+      [k: string]: unknown;
+    };
+  };
+  /**
+   * Represents object with content density modes the app is supporting. Supported density modes are 'cozy' and 'compact'
+   */
+  contentDensities: {
+    /**
+     * Represents indicator whether compact mode is supported
+     */
+    compact: boolean;
+    /**
+     * Represents indicator whether cozy mode is supported
+     */
+    cozy: boolean;
+  };
+  /**
+   * Represents a name of the UI5 component
+   */
+  componentName?: string;
+  /**
+   * Enables the auto prefixing of IDs of ManagedObjects (e.g. Controls) which are created in context of the Component (e.g. createContent invocation)
+   */
+  autoPrefixId?: boolean;
+  /**
+   * Represents the identifier of an application variant. The value will be calculated and should not be set manually
+   */
+  appVariantId?: string;
+  /**
+   * Represents array of appVariantId hierarchy with origin layer and version, calculated attribute and filled automatically during variant merge
+   */
+  appVariantIdHierarchy?: {
+    /**
+     * Represents origin layer of the app variant id
+     */
+    layer: string;
+    /**
+     * Represents app variant id
+     */
+    appVariantId: string;
+    /**
+     * Represents version of the app variant id
+     */
+    version: string;
+  }[];
+  /**
+   * Represents a list of the services
+   */
+  services?: {
+    [k: string]: Service;
+  };
+  /**
+   * Represents UI5 library specific properties
+   */
+  library?: {
+    /**
+     * Setting to define i18n properties of a library. Can either be a boolean, string or object.
+     */
+    i18n?:
+      | boolean
+      | string
+      | {
+          /**
+           * Represents the URL for the resource bundle
+           */
+          bundleUrl: string;
+          /**
+           * Represents the list of supported locales
+           */
+          supportedLocales?: unknown[];
+          /**
+           * Represents the fallback locale
+           */
+          fallbackLocale?: string;
+          /**
+           * Represents terminologies with additional properties files
+           */
+          terminologies?: {
+            [k: string]: TerminologySetting;
+          };
+          /**
+           * Represents enhancement of UI5 resource bundle with additional properties files
+           */
+          enhanceWith?: EnhanceWithSetting3[];
+        }
+      | {
+          /**
+           * Represents the alternative for bundleUrl
+           */
+          bundleName: string;
+          /**
+           * Represents the fallback locale
+           */
+          fallbackLocale?: string;
+          /**
+           * Represents the list of supported locales
+           */
+          supportedLocales?: unknown[];
+          /**
+           * Represents terminologies with additional properties files
+           */
+          terminologies?: {
+            [k: string]: TerminologySetting;
+          };
+          /**
+           * Represents enhancement of UI5 resource bundle with additional properties files
+           */
+          enhanceWith?: EnhanceWithSetting4[];
+        };
+    /**
+     * Flag whether the library contains a CSS file or not.
+     */
+    css?: boolean | string;
+    /**
+     * Represents the content of a library. Content are controls, elements, types and interfaces.
+     */
+    content?: {
+      [k: string]: unknown;
+    };
+  };
+  /**
+   * Represents a list of UI5 shortcut commands
+   */
+  commands?: {
+    [k: string]: Command;
+  };
+  /**
+   * Represents an indicator whether app variant is flex extension point enabled
+   */
+  flexExtensionPointEnabled?: boolean;
+  /**
+   * Represents an indicator whether app is a cloud developer adaptation, filled automatically during build.
+   */
+  isCloudDevAdaptation?: boolean;
+  [k: string]: unknown;
+} & (
+  | {
+      /**
+       * Represents an Indicator whether an app is flex enabled
+       */
+      flexEnabled: true;
+      routing?: RoutingFlexEnabled;
+      rootView?: RootViewDefFlexEnabled;
+      [k: string]: unknown;
+    }
+  | {
+      /**
+       * Represents an Indicator whether an app is flex enabled
+       */
+      flexEnabled?: false;
+      routing?: Routing;
+      rootView?: RootViewDef;
+      [k: string]: unknown;
+    }
+);
+/**
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "[\s\S]*".
+ */
+export type Config =
+  | Config[]
+  | string
+  | boolean
+  | number
+  | {
+      [k: string]: unknown;
+    };
+export type EnhanceWithSetting2 =
+  | {
+      /**
+       * Represents property url for model enhancement
+       */
+      bundleUrl: string;
+      /**
+       * Indicates whether url is relative to component (default) or manifest
+       */
+      bundleUrlRelativeTo?: "manifest" | "component";
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    }
+  | {
+      /**
+       * Represents the alternative for bundleUrl
+       */
+      bundleName: string;
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    };
+/**
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]*$".
+ */
+export type ResourceRoot = string;
+export type EnhanceWithSetting3 =
+  | {
+      /**
+       * Represents property url for model enhancement
+       */
+      bundleUrl: string;
+      /**
+       * Indicates whether url is relative to component (default) or manifest
+       */
+      bundleUrlRelativeTo?: "manifest" | "component";
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    }
+  | {
+      /**
+       * Represents the alternative for bundleUrl
+       */
+      bundleName: string;
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    };
+export type EnhanceWithSetting4 =
+  | {
+      /**
+       * Represents property url for model enhancement
+       */
+      bundleUrl: string;
+      /**
+       * Indicates whether url is relative to component (default) or manifest
+       */
+      bundleUrlRelativeTo?: "manifest" | "component";
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    }
+  | {
+      /**
+       * Represents the alternative for bundleUrl
+       */
+      bundleName: string;
+      /**
+       * Represents the fallback locale
+       */
+      fallbackLocale?: string;
+      /**
+       * Represents the list of supported locales
+       */
+      supportedLocales?: unknown[];
+      /**
+       * Represents terminologies with additional properties files
+       */
+      terminologies?: {
+        [k: string]: TerminologySetting;
+      };
+    };
+/**
+ * Represents the definition of each route
+ */
+export type Route = RouteWithoutName & {
+  /**
+   * Represents the name of the route
+   */
+  name: string;
+  [k: string]: unknown;
+};
+/**
+ * Represents the root view definition being either the name of the view or the view definition object
+ */
+export type RootViewDef =
+  | string
+  | {
+      /**
+       * Represents the name of the view
+       */
+      viewName: string;
+      /**
+       * Represents the type of the view. Possible Values: XML, JSON, JS, HTML, Template
+       */
+      type?: "XML" | "JSON" | "JS" | "HTML" | "Template";
+      /**
+       * Represents the id of the view
+       */
+      id?: string;
+      /**
+       * Configure the targets for asynchronous loading
+       */
+      async?: boolean;
+      [k: string]: unknown;
+    };
+/**
+ *  Represents a binding string to indicate, how the reuse component should be bound relative to the containing page or absolute
+ */
+export type ComponentBindingDef = string;
+/**
+ * Represents the card default grid size in columns and rows
+ */
+export type DefaultSpanDef =
+  | {
+      /**
+       * Represents the number of the number of grid columns
+       */
+      cols: number;
+      /**
+       * Represents the number of the number of grid rows
+       */
+      rows: number;
+      /**
+       * Represents if user wants to show only header part of card in resizable layout
+       */
+      showOnlyHeader?: boolean;
+      /**
+       * If user wants to show more text in title then he/she can configure no of lines to be shown in title(Maximum allowed 3 lines)
+       */
+      minimumTitleRow?: number;
+      /**
+       * If user wants to show more text in title then he/she can configure no of lines to be shown in sub-title(Maximum allowed 2 lines)
+       */
+      minimumSubTitleRow?: number;
+    }
+  | "auto";
+/**
+ * Plot area is a parent property which defines multiple other properties for smoothness and marker size
+ */
+export type LevelsDef = unknown[];
+/**
+ * Represents general card attributes
+ */
+export type JSONSchemaForSAPCARDNamespace = {
+  [k: string]: unknown;
+};
+/**
+ * The version number of the schema in major.minor.patch format.
+ */
+export type Semanticversion = string;
+/**
+ * Represents SBPA Custom Task UI Attributes
+ */
+export type JSONSchemaForSapBpaTaskNamespace = {
+  [k: string]: unknown;
+};
+
+export interface SAPJSONSchemaForWebApplicationManifestFile {
+  /**
+   * The resource identifier for the JSON schema to be used. The value of this keyword MUST be a URI [RFC3986] (containing a scheme) and this URI MUST be normalized. The current schema MUST be valid against the meta-schema identified by this URI. If this URI identifies a retrievable resource, that resource SHOULD be of media type "application/schema+json".
+   */
+  $schema?: string;
+  /**
+   * Represents Application Descriptor format version. It is managed by schema owner
+   */
+  _version:
+    | "1.1.0"
+    | "1.2.0"
+    | "1.3.0"
+    | "1.4.0"
+    | "1.5.0"
+    | "1.6.0"
+    | "1.7.0"
+    | "1.8.0"
+    | "1.9.0"
+    | "1.10.0"
+    | "1.11.0"
+    | "1.12.0"
+    | "1.13.0"
+    | "1.14.0"
+    | "1.15.0"
+    | "1.16.0"
+    | "1.17.0"
+    | "1.18.0"
+    | "1.19.0"
+    | "1.20.0"
+    | "1.21.0"
+    | "1.22.0"
+    | "1.23.0"
+    | "1.24.0"
+    | "1.25.0"
+    | "1.26.0"
+    | "1.27.0"
+    | "1.28.0"
+    | "1.29.0"
+    | "1.30.0"
+    | "1.31.0"
+    | "1.32.0"
+    | "1.33.0"
+    | "1.34.0"
+    | "1.35.0"
+    | "1.36.0"
+    | "1.37.0"
+    | "1.38.0"
+    | "1.39.0"
+    | "1.40.0"
+    | "1.41.0"
+    | "1.42.0"
+    | "1.43.0"
+    | "1.44.0"
+    | "1.45.0"
+    | "1.46.0"
+    | "1.47.0"
+    | "1.48.0"
+    | "1.49.0"
+    | "1.50.0"
+    | "1.51.0"
+    | "1.52.0"
+    | "1.53.0"
+    | "1.54.0"
+    | "1.55.0"
+    | "1.56.0"
+    | "1.57.0"
+    | "1.58.0"
+    | "1.59.0"
+    | "1.60.0";
+  /**
+   * Represents the URL that the developer would prefer the user agent load when the user launches the web application
+   */
+  start_url?: string;
+  "sap.app": JSONSchemaForSAPAPPNamespace;
+  "sap.ui": JSONSchemaForSAPUINamespace;
+  "sap.ui5"?: JSONSchemaForSAPUI5Namespace;
+  "sap.platform.abap"?: JSONSchemaForSAPPLATFORMABAPNamespace;
+  "sap.platform.hcp"?: JSONSchemaForSAPPLATFORMHCPNamespace;
+  "sap.platform.cf"?: JSONSchemaForSAPPLATFORMCFNamespace;
+  "sap.platform.mobilecards"?: JSONSchemaForSAPPLATFORMMOBILECARDSNamespace;
+  "sap.fiori"?: JSONSchemaForSAPFIORINamespace;
+  "sap.ui.generic.app"?: JSONSchemaForSAPUIGENERICAPPNamespace;
+  "sap.fe"?: JSONSchemaForSAPFENamespace;
+  "sap.flp"?: JSONSchemaForSAPFLPNamespace;
+  "sap.ovp"?: JSONSchemaForSAPOVPNamespace;
+  "sap.insights"?: JSONSchemaForSAPInsightsNamespace;
+  "sap.wda"?: JSONSchemaForSAPWDANamespace;
+  "sap.apf"?: JSONSchemaForSAPAPFNamespace;
+  "sap.cloud.portal"?: JSONSchemaForSAPCLOUDPORTALNamespace;
+  "sap.gui"?: JSONSchemaForSAPGUINamespace;
+  "sap.integration"?: JSONSchemaForSAPINTEGRATIONNamespace;
+  "sap.wcf"?: JSONSchemaForSAPWCFNamespace;
+  "sap.ui.smartbusiness.app"?: JSONSchemaForSAPUISMARTBUSINESSAPPNamespace;
+  "sap.mobile"?: JSONSchemaForSAPMOBILENamespace;
+  "sap.copilot"?: JSONSchemaForSAPCOPILOTNamespace;
+  "sap.map"?: JSONSchemaForSAPMAPNamespace;
+  "sap.url"?: JSONSchemaForSAPURLNamespace;
+  "sap.platform.sfsf"?: JSONSchemaForSAPPLATFORMSFSFNamespace;
+  "sap.cloud"?: JSONSchemaForSAPCLOUDNamespace;
+  "sap.card"?: JSONSchemaForSAPCARDNamespace;
+  "sap.package"?: JSONSchemaForSAPPACKAGENamespace;
+  "sap.artifact"?: JSONSchemaForSAPARTIFACTNamespace;
+  "sap.bpa.task"?: JSONSchemaForSapBpaTaskNamespace;
+}
+/**
+ * Represents general application attributes
+ */
+export interface JSONSchemaForSAPAPPNamespace {
+  /**
+   * Application attributes format version. It is managed by namespace owner
+   */
+  _version?:
+    | "1.1.0"
+    | "1.2.0"
+    | "1.3.0"
+    | "1.4.0"
+    | "1.5.0"
+    | "1.6.0"
+    | "1.7.0"
+    | "1.8.0"
+    | "1.9.0"
+    | "1.10.0"
+    | "1.11.0"
+    | "1.12.0"
+    | "1.13.0"
+    | "1.14.0"
+    | "1.15.0"
+    | "1.16.0"
+    | "1.17.0"
+    | "1.18.0"
+    | "1.19.0"
+    | "1.20.0";
+  /**
+   * Represents the template from which the app was generated
+   */
+  sourceTemplate?: {
+    /**
+     * Represents id of the template from which the app was generated
+     */
+    id: string;
+    /**
+     * Represents the version of the template from which the app was generated
+     */
+    version: string;
+    /**
+     * Represents an Id generated by SAP Fiori tools
+     */
+    toolsId?: string;
+    [k: string]: unknown;
+  };
+  /**
+   * Represents mandatory unique app identifier which must correspond to component 'id/namespace'
+   */
+  id: string;
+  /**
+   * Represents type of an application and can be application or component or library
+   */
+  type: "application" | "component" | "library" | "card";
+  /**
+   * Represents path inside the app to the properties file containing text symbols for the Descriptor or properties file specific settings (including supportedLocales, fallbackLocale, terminologies and enhanceWith)
+   */
+  i18n?:
+    | string
+    | {
+        /**
+         * Represents the alternative for bundleUrl
+         */
+        bundleName: string;
+        /**
+         * Represents the fallback locale
+         */
+        fallbackLocale?: string;
+        /**
+         * Represents the list of supported locales
+         */
+        supportedLocales?: unknown[];
+        /**
+         * Represents terminologies with additional properties files
+         */
+        terminologies?: {
+          [k: string]: TerminologySetting;
+        };
+        /**
+         * Represents enhancement of UI5 resource model with additional properties files
+         */
+        enhanceWith?: EnhanceWithSetting[];
+      }
+    | {
+        /**
+         * Represents the URL for the resource bundle
+         */
+        bundleUrl: string;
+        /**
+         * Indicates whether url is relative to component (default) or manifest
+         */
+        bundleUrlRelativeTo?: "manifest" | "component";
+        /**
+         * Represents the list of supported locales
+         */
+        supportedLocales?: unknown[];
+        /**
+         * Represents the fallback locale
+         */
+        fallbackLocale?: string;
+        /**
+         * Represents terminologies with additional properties files
+         */
+        terminologies?: {
+          [k: string]: TerminologySetting;
+        };
+        /**
+         * Represents enhancement of UI5 resource model with additional properties files
+         */
+        enhanceWith?: EnhanceWithSetting1[];
+      };
+  /**
+   * Represents mandatory version of the app
+   */
+  applicationVersion: {
+    version: Version;
+    [k: string]: unknown;
+  };
+  /**
+   * Represents array of relative paths to the nested manifest.json's (mandatory if it contains nested 'manifest.json')
+   */
+  embeds?: string[];
+  /**
+   * Represents relative path back to the manifest.json of an embedding component or library (mandatory for nested 'manifest.json')
+   */
+  embeddedBy?: string;
+  /**
+   * Represents a title (mandatory); to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  title: string;
+  /**
+   * Represents a subtitle to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  subTitle?: string;
+  /**
+   * Represents a shorter version of the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  shortTitle?: string;
+  /**
+   * Represents additional information to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  info?: string;
+  /**
+   * Represents a description; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  description?: string;
+  /**
+   * Represents array of keywords
+   */
+  tags?: {
+    keywords: Tag;
+    technicalAttributes?: string[];
+    [k: string]: unknown;
+  };
+  /**
+   * Represents application component hierarchy
+   */
+  ach?: string;
+  /**
+   * Represents used data sources with a unique key/alias
+   */
+  dataSources?: {
+    [k: string]: DataSource;
+  };
+  /**
+   * Represents array of directly used CDS views, which only to be added if directly used via INA protocol and not if used via OData service
+   */
+  cdsViews?: string[];
+  /**
+   * Represents reference to a file (naming convention is resources.json) which contains list with all resources which the app needs
+   */
+  resources?: "resources.json";
+  /**
+   * Represents a system alias
+   */
+  destination?: {
+    /**
+     * Represents an alias for the system
+     */
+    name: string;
+  };
+  /**
+   * Represents a collection of directly used open source libs (not when used via UI5 capsulation)
+   */
+  openSourceComponents?: OpenSource[];
+  /**
+   * Represents the name of the provider which owns the application
+   */
+  provider?: "sfsf";
+  /**
+   * Represents indicator whether the app is running offline. Possible values are true or false (default)
+   */
+  offline?: boolean;
+  /**
+   * Represents cross navigation for inbound and outbound targets
+   */
+  crossNavigation?: {
+    /**
+     * Represents scopes of a site
+     */
+    scopes?: {
+      /**
+       * Represents unique id of the site
+       *
+       * This interface was referenced by `undefined`'s JSON-Schema definition
+       * via the `patternProperty` "^[a-zA-Z0-9_\.\-]+$".
+       */
+      [k: string]: {
+        value: string;
+        [k: string]: unknown;
+      };
+    };
+    inbounds: Inbound;
+    outbounds?: Outbound;
+    [k: string]: unknown;
+  };
+}
+export interface DataSourceEnum {
+  /**
+   * Represents uri of the data source
+   */
+  uri: string;
+  /**
+   * Represents type of the data source. The supported types are OData, ODataAnnotation, INA, XML, JSON, FHIR, WebSocket, http
+   */
+  type?: "OData" | "ODataAnnotation" | "INA" | "XML" | "JSON" | "FHIR" | "WebSocket" | "http";
+  settings?: Setting;
+  customType?: false;
+}
+/**
+ * Represents data source type specific attributes (key, value pairs)
+ */
+export interface Setting {
+  /**
+   * Represents version of OData: 2.0 is default
+   */
+  odataVersion?: "2.0" | "4.0";
+  /**
+   * Represents path to local meta data document or annotation uri
+   */
+  localUri?: string;
+  /**
+   * Represents  array of annotation which references an existing data source of type ODataAnnotation
+   */
+  annotations?: string[];
+  /**
+   * Indicates that the client is unwilling to accept a response whose age is greater than the number of seconds specified in this field
+   */
+  maxAge?: number;
+  /**
+   * Dictionary of (catalog) objects offered by the datasource
+   */
+  objects?: {
+    /**
+     * A (catalog) object of an InA DataSource
+     */
+    [k: string]: {
+      objectName: ObjectName;
+      objectType: ObjectType;
+      packageName?: string;
+      schemaName?: string;
+    };
+  };
+  /**
+   * Indicates whether annotations from metadata should be ignored
+   */
+  ignoreAnnotationsFromMetadata?: boolean;
+  [k: string]: unknown;
+}
+export interface DataSourceCustom {
+  /**
+   * Represents the uri of the data source, should always be given in lower case
+   */
+  uri: string;
+  /**
+   * Represents type of the data source. The supported types are OData, ODataAnnotation, INA, XML, JSON, FHIR, WebSocket, http
+   */
+  type?: string;
+  settings?: Setting1;
+  /**
+   * Represents a custom data source type flag. So the type can be any string if its true, and only enum values if false
+   */
+  customType: true;
+}
+/**
+ * Represents data source type specific attributes (key, value pairs)
+ */
+export interface Setting1 {
+  /**
+   * Represents version of OData: 2.0 is default
+   */
+  odataVersion?: "2.0" | "4.0";
+  /**
+   * Represents path to local meta data document or annotation uri
+   */
+  localUri?: string;
+  /**
+   * Represents  array of annotation which references an existing data source of type ODataAnnotation
+   */
+  annotations?: string[];
+  /**
+   * Indicates that the client is unwilling to accept a response whose age is greater than the number of seconds specified in this field
+   */
+  maxAge?: number;
+  /**
+   * Dictionary of (catalog) objects offered by the datasource
+   */
+  objects?: {
+    /**
+     * A (catalog) object of an InA DataSource
+     */
+    [k: string]: {
+      objectName: ObjectName;
+      objectType: ObjectType;
+      packageName?: string;
+      schemaName?: string;
+    };
+  };
+  /**
+   * Indicates whether annotations from metadata should be ignored
+   */
+  ignoreAnnotationsFromMetadata?: boolean;
+  [k: string]: unknown;
+}
+export interface OpenSource {
+  /**
+   * Represents a name of the open source as appears on the web
+   */
+  name: string;
+  /**
+   * Represents a version of the open source (if part of app, version must be specified, if part of UI5 dist layer, version is empty)
+   */
+  version?: string;
+  /**
+   * Indicates, whether it is part of the app or not
+   */
+  packagedWithMySelf?: boolean;
+}
+/**
+ * Represents cross navigation for inbound target
+ */
+export interface Inbound {
+  /**
+   * This interface was referenced by `Inbound`'s JSON-Schema definition
+   * via the `patternProperty` "^[\w\.\-]+$".
+   */
+  [k: string]: {
+    /**
+     * Represents semantic object
+     */
+    semanticObject: string;
+    /**
+     * Represents action an the semantic object
+     */
+    action: string;
+    /**
+     * Indicates to not expose this inbound as a tile or link
+     */
+    hideLauncher?: boolean;
+    /**
+     * Represents icon
+     */
+    icon?: string;
+    /**
+     * Represents a title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+     */
+    title?: string;
+    /**
+     * Represents a subtitle; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+     */
+    subTitle?: string;
+    /**
+     * Represents a shorter version of the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+     */
+    shortTitle?: string;
+    /**
+     * Represents additional information to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+     */
+    info?: string;
+    /**
+     * Represents the display mode of the tile
+     */
+    displayMode?: "ContentMode" | "HeaderMode";
+    /**
+     * Represents data source
+     */
+    indicatorDataSource?: {
+      dataSource: string;
+      path: string;
+      /**
+       * Represents refresh interval
+       */
+      refresh?: number;
+      [k: string]: unknown;
+    };
+    deviceTypes?: DeviceType;
+    signature?: SignatureDef;
+  };
+}
+/**
+ * Represents device types for which application is developed
+ */
+export interface DeviceType {
+  /**
+   * Represents indicator whether desktop device is supported
+   */
+  desktop?: boolean;
+  /**
+   * Represents indicator whether tablet device is supported
+   */
+  tablet?: boolean;
+  /**
+   * Represents indicator whether phone device is supported
+   */
+  phone?: boolean;
+}
+/**
+ * Represents signature for inbound targets
+ */
+export interface SignatureDef {
+  parameters: {
+    /**
+     * This interface was referenced by `undefined`'s JSON-Schema definition
+     * via the `patternProperty` "^[\w\.\-\/]+$".
+     */
+    [k: string]: {
+      /**
+       *  Represents a default Value
+       */
+      defaultValue?:
+        | {
+            format?: "plain";
+            value?: string;
+            [k: string]: unknown;
+          }
+        | {
+            format?: "reference";
+            value?: string;
+            [k: string]: unknown;
+          }
+        | {
+            format?: null;
+            value?: string;
+            [k: string]: unknown;
+          };
+      /**
+       * Represents a filter , only if input parameter matches filter
+       */
+      filter?: {
+        /**
+         * Represents a depending on format either a verbatim filter value, a regular expression or a reference
+         */
+        value: string;
+        /**
+         * Indicates how 'value' is to be interpreted: ('plain': the actual value must match the 'value' property directly| 'regexp': the 'value' represents a regexp which must be present in the actual value| 'reference' : the 'value' represents a reference to e.g. a UserDefault parameter (e.g. 'UserDefault.CostCenter'), the resolved parameter value is then directly compared with the actual value)
+         */
+        format?: "plain" | "regexp" | "reference";
+      };
+      /**
+       *  Represents a value to be used when creating a tile intent for this inbound
+       */
+      launcherValue?: {
+        value?: string | string[];
+        /**
+         * Indicates how 'value' is to be interpreted: 'plain': the 'value' is taken as a literal string value | 'array': the 'value' is an array of strings
+         */
+        format?: "plain" | "array";
+        /**
+         * DEPRECATED - Indicates the administrator should be prompted to supply a value when creating a tile
+         */
+        prompt?: boolean;
+      };
+      required?: boolean;
+      /**
+       * Represents the parameter name in legacy ABAP application, e.g. 'RF05L-BUKRS' for parameter 'CompanyCode'
+       */
+      renameTo?: string;
+    };
+  };
+  /**
+   * Indicates how additional parameters to the declared signature are treated: ('ignored': parameters are not passed on to application | 'allowed': parameters are passed on to application | 'notallowed': additional parameters are not allowed)
+   */
+  additionalParameters: "ignored" | "allowed" | "notallowed";
+}
+/**
+ * Describes intents that can be triggered from the application to navigate
+ */
+export interface Outbound {
+  /**
+   * This interface was referenced by `Outbound`'s JSON-Schema definition
+   * via the `patternProperty` "^[\w\.\-]+$".
+   */
+  [k: string]: {
+    /**
+     * Represents a business entity (e.g., 'Employee')
+     */
+    semanticObject: string;
+    /**
+     * Represents the action to perform on the business entity (e.g., 'display')
+     */
+    action: string;
+    /**
+     * Indicates whether the intent can contain additional context parameters that are not described in the outbound: ('notallowed': the intent must contain only the specified parameters | 'allowed': additional parameters might appear in the navigation intent)| 'ignored': technical meta-parameters for framework usage are added to the intent, these parameters should be ignored by target applications
+     */
+    additionalParameters?: "notallowed" | "ignored" | "allowed";
+    /**
+     * Represents parameters of navigation intents
+     */
+    parameters?: {
+      /**
+       * This interface was referenced by `undefined`'s JSON-Schema definition
+       * via the `patternProperty` "^[\w\.\-\/]+$".
+       */
+      [k: string]: {
+        /**
+         * Describes parameters of navigation intents generated or triggered by the application
+         */
+        value?: {
+          /**
+           * Represents a verbatim value (when 'plain' format is used), a pattern (when 'regexp' format is used), a value coming from a UI5 model (when 'binding' format is used), or a User Default reference (when 'reference' format is used)
+           */
+          value?: string;
+          /**
+           * Indicates how 'value' is to be interpreted: 'plain': the 'value' is taken as a literal string value | 'reference': the 'value' is a reference to a parameter maintained in the Fiori Launchpad (e.g. 'UserDefault.CostCenter'); the parameter value is used on the outbound intent parameter| 'regexp': the 'value' matches the specified pattern| 'binding': the 'value' is a binding path; the value from the model at the specified binding path will be used on the outbound intent parameter
+           */
+          format?: "plain" | "regexp" | "reference" | "binding";
+        };
+        required?: boolean;
+      };
+    };
+  };
+}
+/**
+ * Represents general ui attributes
+ */
+export interface JSONSchemaForSAPUINamespace {
+  /**
+   * Represents UI attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0" | "1.3.0" | "1.4.0" | "1.5.0";
+  /**
+   * Represents UI technology. The possible values are UI5 (default), WDA, NWBC, GUI, URL and WCF
+   */
+  technology: "UI5" | "WDA" | "NWBC" | "GUI" | "URL" | "WCF";
+  /**
+   * Represents icons which used in application
+   */
+  icons?: {
+    /**
+     * Represents icon of the app
+     */
+    icon?: string;
+    /**
+     * Represents ICO file to be used inside the browser and for desktop shortcuts
+     */
+    favIcon?: string;
+    /**
+     * Represents 57x57 pixel version for non-retina iPhones
+     */
+    phone?: string;
+    /**
+     * Represents 114x114 pixel version for non-retina iPhones
+     */
+    "phone@2"?: string;
+    /**
+     * Represents 72x72 pixel version for non-retina iPads
+     */
+    tablet?: string;
+    /**
+     * Represents 144x144 pixel version for non-retina iPads
+     */
+    "tablet@2"?: string;
+  };
+  /**
+   * Represents device types on which application is running. Supported device types are desktop, tablet and phone
+   */
+  deviceTypes: DeviceType1 & {
+    [k: string]: unknown;
+  };
+  /**
+   * The property is Deprecated. Represents array of supported SAP themes such as sap_hcb, sap_bluecrystal
+   */
+  supportedThemes?: string[];
+  /**
+   * Indicates whether app should run in full screen mode: possible values: true or false
+   */
+  fullWidth?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents device types on which the app is running
+ */
+export interface DeviceType1 {
+  /**
+   * Represents indicator whether desktop device is supported
+   */
+  desktop?: boolean;
+  /**
+   * Represents indicator whether tablet device is supported
+   */
+  tablet?: boolean;
+  /**
+   * Represents indicator whether phone device is supported
+   */
+  phone?: boolean;
+}
+/**
+ * Represents paths to JavaScript/CSS resources that your app needs (app internal), formerly called '.includes'
+ */
+export interface Resource {
+  js?: {
+    uri: string;
+    [k: string]: unknown;
+  }[];
+  css?: {
+    uri: string;
+    id?: string;
+    [k: string]: unknown;
+  }[];
+  [k: string]: unknown;
+}
+/**
+ * Represents component name for usage
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.]*$".
+ */
+export interface ComponentUsages {
+  /**
+   * Represents name of reuse component
+   */
+  name: string;
+  /**
+   * Represents component data for the Component
+   */
+  componentData?:
+    | Config[]
+    | string
+    | boolean
+    | number
+    | {
+        [k: string]: unknown;
+      };
+  /**
+   * Represents settings for the Component
+   */
+  settings?:
+    | Config[]
+    | string
+    | boolean
+    | number
+    | {
+        [k: string]: unknown;
+      };
+  /**
+   * Represents Indicator to lazy loading component usage, default true
+   */
+  lazy?: boolean;
+}
+/**
+ * Represents sapui5 library name
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^([a-z][a-z0-9]{0,39})(\.[a-z][a-z0-9]{0,39})*$".
+ */
+export interface Lib {
+  /**
+   * Represents minimal version of ui5 library
+   */
+  minVersion?: string;
+  /**
+   * Represents Indicator to lazy loading lib
+   */
+  lazy?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents sapui5 component name
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^([a-zA-Z_$][a-zA-Z0-9_$]{0,39}\.)*([a-zA-Z_$][a-zA-Z0-9_$]{0,39})$".
+ */
+export interface Component {
+  /**
+   * Represents minimal version of ui5 component
+   */
+  minVersion?: string;
+  /**
+   * Represents Indicator to lazy loading component
+   */
+  lazy?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents sapui5 model name
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-\|@]*$".
+ */
+export interface Model {
+  /**
+   * Represents model class name
+   */
+  type?: string;
+  /**
+   * Represents string of key/alias from sap.app dataSources to reference an existing data source
+   */
+  dataSource?: string;
+  /**
+   * Represents URI for the model
+   */
+  uri?: string;
+  /**
+   * Indicates that the model will be immediately created after the manifest is loaded by Component Factory and before the Component instance is created
+   */
+  preload?: boolean;
+  settings?: Ui5Setting;
+}
+export interface Ui5Setting {
+  /**
+   * Represents default binding mode and must be a string value from sap.ui.model.BindingMode. Possible values: Default, OneTime, OneWay, TwoWay
+   */
+  defaultBindingMode?: "Default" | "OneTime" | "OneWay" | "TwoWay";
+  /**
+   * Represents the alternative for bundleUrl
+   */
+  bundleName?: string;
+  /**
+   * Represents the URL for the resource bundle
+   */
+  bundleUrl?: string;
+  /**
+   * Indicates whether url is relative to component (default) or manifest
+   */
+  bundleUrlRelativeTo?: "manifest" | "component";
+  /**
+   * Represents the fallback locale
+   */
+  fallbackLocale?: string;
+  /**
+   * Represents the list of supported locales
+   */
+  supportedLocales?: unknown[];
+  /**
+   * Represents terminologies with additional properties files
+   */
+  terminologies?: {
+    [k: string]: unknown;
+  };
+  /**
+   * Represents enhancement of UI5 resource model with additional properties files
+   */
+  enhanceWith?: EnhanceWithSetting2[];
+  [k: string]: unknown;
+}
+/**
+ * Represents the definition of each service
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "[\s\S]*".
+ */
+export interface Service {
+  /**
+   * Represents the name of the service factory
+   */
+  factoryName: string;
+  /**
+   * Indicates whether the service optional or not
+   */
+  optional?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents a UI5 shortcut command.
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[A-Za-z_][A-Za-z0-9_\-\|@]+$".
+ */
+export interface Command {
+  /**
+   * A string describing a shortcut key combination that, when used by the user, will trigger the command.
+   */
+  shortcut?: string;
+}
+/**
+ * Represents the configuration of routing
+ */
+export interface RoutingFlexEnabled {
+  /**
+   * Represents the default properties defined for route and target
+   */
+  config?: {
+    /**
+     * Represents the router class
+     */
+    routerClass?: string;
+    /**
+     * Indicates whether the Views in routing are loaded asyncly
+     */
+    async?: boolean;
+    /**
+     * Represents information about targets to display when no route is matched
+     */
+    bypassed?: {
+      /**
+       * Represents one or multiple names of targets that are displayed when no route is matched
+       */
+      target: [] | [string | RouteTargetObject] | string | RouteTargetObject;
+    };
+    /**
+     * Represents a prefix that is prepended in front of the viewName
+     */
+    viewPath?: string;
+    [k: string]: unknown;
+  } & Target;
+  routes?:
+    | Route[]
+    | {
+        [k: string]: RouteWithoutName;
+      };
+  /**
+   * Represents the definition of targets
+   */
+  targets?: {
+    /**
+     * This interface was referenced by `undefined`'s JSON-Schema definition
+     * via the `patternProperty` "[\s\S]*".
+     */
+    [k: string]:
+      | (Target & {
+          /**
+           * Represents the name of a view that will be created
+           */
+          viewName: string;
+          /**
+           * Represents the id of the created view
+           */
+          viewId: string;
+          /**
+           * Represents a prefix that is prepended in front of the viewName
+           */
+          viewPath?: string;
+          [k: string]: unknown;
+        })
+      | (Target &
+          (
+            | {
+                /**
+                 * Represents the name of a view or component that will be created
+                 */
+                name: string;
+                /**
+                 * Represents the id of the created view or component
+                 */
+                id: string;
+                /**
+                 * Represents a prefix that is prepended in front of the view or component name
+                 */
+                path?: string;
+                /**
+                 * Represents the type of the type View or Component
+                 */
+                type?: "View" | "Component";
+                [k: string]: unknown;
+              }
+            | {
+                /**
+                 * Represents the componentUsage of the component that will be created
+                 */
+                usage: string;
+                /**
+                 * Represents the id of the created view or component
+                 */
+                id: string;
+                /**
+                 * Represents the type of the type Component
+                 */
+                type: "Component";
+                [k: string]: unknown;
+              }
+          ));
+  };
+  [k: string]: unknown;
+}
+/**
+ * Represents the definition of a target of a route as object.
+ */
+export interface RouteTargetObject {
+  /**
+   * Represents the name of the routing target
+   */
+  name?: string;
+  /**
+   * The prefix of the routing target
+   */
+  prefix?: string;
+  /**
+   * Indicates whether this 'Component' target should propagate it's title to this component or not
+   */
+  propagateTitle?: boolean & string;
+  [k: string]: unknown;
+}
+/**
+ * Represents the definition of each target
+ */
+export interface Target {
+  /**
+   * Represents the information which is included as a parameter of the 'titleChanged' event fired on Router when this target is displayed. The title can be set with static text and can also be set with a valid property binding syntax which will be resolved under the scope of the view in the target where the title property is defined.
+   */
+  title?: string;
+  /**
+   * Represents the type of view that is going to be created
+   */
+  viewType?: "XML" | "JSON" | "JS" | "HTML" | "Template";
+  /**
+   * Represents the id of the view that contains the control specified by the 'controlId'
+   */
+  targetParent?: string;
+  /**
+   * Represents the id of the control where you want to place the view created by the target
+   */
+  controlId?: string;
+  /**
+   * Represents the name of an aggregation of the controlId that contains the views
+   */
+  controlAggregation?: string;
+  /**
+   * Whether the aggregation of the control should be cleared before adding the view
+   */
+  clearControlAggregation?: boolean;
+  /**
+   * Represents the name of another target which will also be displayed once this target is displayed
+   */
+  parent?: string;
+  /**
+   * Represents the level of the current view which is used to define the transition direction when navigate to this view
+   */
+  viewLevel?: number;
+  /**
+   * Represents the type of transition when navigating from previous view to this view
+   */
+  transition?: string | ("slide" | "flip" | "fade" | "show");
+  /**
+   * Represents the transition parameters that are passed to the event handlers
+   */
+  transitionParameters?: {
+    [k: string]: unknown;
+  };
+  [k: string]: unknown;
+}
+/**
+ * Represents the definition of route without the option 'name'. This is used when routes are defined in an object.
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "[\s\S]*".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "[\s\S]*".
+ */
+export interface RouteWithoutName {
+  /**
+   * Represents the url pattern that the route is matched against
+   */
+  pattern?: string;
+  /**
+   * Whether the route should be matched when another route is already matched
+   */
+  greedy?: boolean;
+  /**
+   * Represents one or multiple names of targets which are displayed when the route is matched
+   */
+  target?: [] | [string | RouteTargetObject] | string | RouteTargetObject;
+  /**
+   * Represents the name of the target where the 'title' information should be taken
+   */
+  titleTarget?: string;
+  [k: string]: unknown;
+}
+/**
+ * Represents the root view definition when flex is enabled (requires a view id)
+ */
+export interface RootViewDefFlexEnabled {
+  /**
+   * Represents the name of the view
+   */
+  viewName: string;
+  /**
+   * Represents the type of the view. Possible Values: XML, JSON, JS, HTML, Template
+   */
+  type?: "XML" | "JSON" | "JS" | "HTML" | "Template";
+  /**
+   * Represents the id of the view
+   */
+  id: string;
+  /**
+   * Configure the targets for asynchronous loading
+   */
+  async?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents the configuration of routing
+ */
+export interface Routing {
+  /**
+   * Represents the default properties defined for route and target
+   */
+  config?: {
+    /**
+     * Represents the router class
+     */
+    routerClass?: string;
+    /**
+     * Indicates whether the Views in routing are loaded asyncly
+     */
+    async?: boolean;
+    /**
+     * Indicates whether the targets which have type 'Component' should propagate their title to this component or not
+     */
+    propagateTitle?: boolean;
+    /**
+     * Represents information about targets to display when no route is matched
+     */
+    bypassed?: {
+      /**
+       * Represents one or multiple names of targets that are displayed when no route is matched
+       */
+      target: [] | [string | RouteTargetObject] | string | RouteTargetObject;
+    };
+    /**
+     * Represents a prefix that is prepended in front of the viewName
+     */
+    viewPath?: string;
+    [k: string]: unknown;
+  } & Target;
+  routes?:
+    | Route[]
+    | {
+        [k: string]: RouteWithoutName;
+      };
+  /**
+   * Represents the definition of targets
+   */
+  targets?: {
+    /**
+     * This interface was referenced by `undefined`'s JSON-Schema definition
+     * via the `patternProperty` "[\s\S]*".
+     */
+    [k: string]:
+      | (Target & {
+          /**
+           * Represents the name of a view that will be created
+           */
+          viewName: string;
+          /**
+           * Represents the id of the created view
+           */
+          viewId?: string;
+          /**
+           * Represents a prefix that is prepended in front of the viewName
+           */
+          viewPath?: string;
+          [k: string]: unknown;
+        })
+      | (Target &
+          (
+            | {
+                /**
+                 * Represents the name of a view or component that will be created
+                 */
+                name: string;
+                /**
+                 * Represents the id of the created view or component
+                 */
+                id?: string;
+                /**
+                 * Represents a prefix that is prepended in front of the view or component name
+                 */
+                path?: string;
+                /**
+                 * Represents the type of the type View or Component
+                 */
+                type?: "View" | "Component";
+                [k: string]: unknown;
+              }
+            | {
+                /**
+                 * Represents the componentUsage of the component that will be created
+                 */
+                usage: string;
+                /**
+                 * Represents the id of the created view or component
+                 */
+                id?: string;
+                /**
+                 * Represents the type of the type Component
+                 */
+                type: "Component";
+                [k: string]: unknown;
+              }
+          ));
+  };
+  [k: string]: unknown;
+}
+/**
+ * Represents ABAP platform specific attributes
+ */
+export interface JSONSchemaForSAPPLATFORMABAPNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0";
+  /**
+   * Represents the uri of the app in the ABAP system
+   */
+  uri?: string;
+  /**
+   * Represents the alternative uri of the app in the ABAP system for starting the application
+   */
+  uriNwbc?: string;
+}
+/**
+ * Represents HANA Cloud Platform platform specific attributes
+ */
+export interface JSONSchemaForSAPPLATFORMHCPNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0" | "1.3.0";
+  /**
+   * Represents the uri of the app in the HANA Cloud Platform
+   */
+  uri?: string;
+  /**
+   * Represents the alternative uri of the app in the ABAP system for starting the application
+   */
+  uriNwbc?: string;
+  /**
+   * Represents the provider account of the HTML5 application
+   */
+  providerAccount?: string;
+  /**
+   * Represents the HTML5 application name
+   */
+  appName?: string;
+  /**
+   * Represents the version of the HTML5 application
+   */
+  appVersion?: string;
+  /**
+   * Indicates that HCP application is multi-version enabled
+   */
+  multiVersionApp?: boolean;
+}
+/**
+ * Represents CF(Cloud Foundry) platform specific attributes
+ */
+export interface JSONSchemaForSAPPLATFORMCFNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0";
+  /**
+   * Represents the authorization scope of the application
+   */
+  oAuthScopes?: string[];
+  [k: string]: unknown;
+}
+/**
+ * Represents Mobile Cards platform specific attributes
+ */
+export interface JSONSchemaForSAPPLATFORMMOBILECARDSNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0";
+  /**
+   * Represents the compatibility of this app with the Mobile Cards platform.
+   */
+  compatible?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents SAP Fiori  specific attributes
+ */
+export interface JSONSchemaForSAPFIORINamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0" | "1.3.0";
+  /**
+   * Represents array of registration ids, i.e. for Fiori apps fiori id(s)
+   */
+  registrationIds: string[];
+  /**
+   * Represents architecture type of an application. The supported types are transactional or analytical or factsheet or reusecomponent or fpmwebdynpro or designstudio
+   */
+  archeType: "transactional" | "analytical" | "factsheet" | "reusecomponent" | "fpmwebdynpro" | "designstudio";
+  /**
+   * Indicator that app is an abstract (generic) app which may not be used directly, but needs to be specialized in the SAP Fiori launchpad content
+   */
+  abstract?: boolean;
+  /**
+   * Represents the release status for the developer adaptation in the cloud (relevant for SAP internal only). The supported types are released, deprecated, obsolete, no value means not released
+   */
+  cloudDevAdaptationStatus?: "released" | "deprecated" | "obsolete";
+}
+/**
+ * Represents GENERIC APP specific attributes
+ */
+export interface JSONSchemaForSAPUIGENERICAPPNamespace {
+  _version?: "1.1.0" | "1.2.0" | "1.3.0" | "1.4.0" | "1.5.0" | "1.6.0";
+  settings?: SettingDef;
+  /**
+   * Represents one ore more pages of an application. UI5 routing is created from the definitions in this section
+   */
+  pages?:
+    | PagesArray[]
+    | {
+        [k: string]: PagesMap;
+      };
+}
+/**
+ * Represents global settings for the application controller
+ */
+export interface SettingDef {
+  [k: string]: unknown;
+}
+export interface PagesArray {
+  /**
+   * Represents the navigation property that leads to this page. The navigation links of the previous page (the page that calls this one) are determined through this property
+   */
+  navigationProperty?: string;
+  /**
+   * Represents the entity set that defines either the aggregation or the root object of the component
+   */
+  entitySet?: string;
+  component: ComponentDef;
+  navigation?: NavigationDef;
+  embeddedComponents?: EmbeddedComponent;
+  routingSpec?: RoutingSpecDef;
+  /**
+   * Represents the component to be loaded inside the canvas if sap.suite.ui.generic.template.Canvas is used as component name, and its settings
+   */
+  implementingComponent?:
+    | {
+        /**
+         * Represents the name of the component to be loaded inside the canvas
+         */
+        componentName: string;
+        binding?: ComponentBindingDef;
+        settings?: ComponentSettingDef;
+        pages?: ComponentPagesDef;
+      }
+    | {
+        /**
+         * Represents the reference to the name of the componentUsages defined in sap.ui5/componentUsages for the component to be loaded inside the canvas
+         */
+        componentUsage: string;
+        binding?: ComponentBindingDef;
+        settings?: ComponentSettingDef;
+        pages?: ComponentPagesDef;
+      };
+  /**
+   * Default layout used to open the corresponding page in FlexibleColumnLayout
+   */
+  defaultLayoutType?: string;
+  /**
+   * Default layout used to open the corresponding page in FlexibleColumnLayout when reached via external navigation
+   */
+  defaultLayoutTypeIfExternalNavigation?: string;
+  pages?: PagesArray[];
+}
+/**
+ * Represents the component and its settings that makes the page
+ */
+export interface ComponentDef {
+  /**
+   * The name of the component
+   */
+  name: string;
+  /**
+   * Switch to create a route for a list (aggregation) if true and routing for an entity if not set or false
+   */
+  list?: boolean;
+  settings?: ComponentSettingDef;
+}
+/**
+ * Represents the settings specific to one component
+ */
+export interface ComponentSettingDef {
+  [k: string]: unknown;
+}
+/**
+ * Represents the different navigation targets
+ */
+export interface NavigationDef {
+  display?: ActionPropDef;
+  create?: ActionPropDef1;
+  edit?: ActionPropDef2;
+}
+/**
+ * Represents an action triggered by the user on UI: the navigation to display an object
+ */
+export interface ActionPropDef {
+  /**
+   * Represents the path in the manifest to the target to which the navigation is bound
+   */
+  path: string;
+  /**
+   * Represents the pointer to a semantic object
+   */
+  target: string;
+  refreshStrategyOnAppRestore?: RefreshStrategiesPropDef;
+}
+/**
+ * Represents the refresh strategies configured for external display navigation while coming back to the source app
+ */
+export interface RefreshStrategiesPropDef {
+  /**
+   * Represents the map of entity sets configured for refresh strategies
+   */
+  entitySets?: {
+    [k: string]: unknown;
+  };
+}
+/**
+ * Represents an action triggered by the user on UI: the navigation to create an object
+ */
+export interface ActionPropDef1 {
+  /**
+   * Represents the path in the manifest to the target to which the navigation is bound
+   */
+  path: string;
+  /**
+   * Represents the pointer to a semantic object
+   */
+  target: string;
+  refreshStrategyOnAppRestore?: RefreshStrategiesPropDef;
+}
+/**
+ * Represents an action triggered by the user on UI: the navigation to edit an object
+ */
+export interface ActionPropDef2 {
+  /**
+   * Represents the path in the manifest to the target to which the navigation is bound
+   */
+  path: string;
+  /**
+   * Represents the pointer to a semantic object
+   */
+  target: string;
+  refreshStrategyOnAppRestore?: RefreshStrategiesPropDef;
+}
+/**
+ * Represent reuse components that should be appended at the end of the template component
+ */
+export interface EmbeddedComponent {
+  /**
+   * This interface was referenced by `EmbeddedComponent`'s JSON-Schema definition
+   * via the `patternProperty` "^[a-zA-Z0-9_.:-]+$".
+   *
+   * This interface was referenced by `EmbeddedComponent2`'s JSON-Schema definition
+   * via the `patternProperty` "^[a-zA-Z0-9_.:-]+$".
+   */
+  [k: string]: {
+    /**
+     * Represents an unique id for the instance of the reuse component inside of the object page
+     */
+    id: string;
+    /**
+     * Represents the title for the content of the reuse component
+     */
+    title: string;
+    /**
+     * Represents an optional element binding  for the ComponentContainer that hosts the reuse component
+     */
+    binding?: string;
+    /**
+     * Represents a map to populate the API of the reuse component
+     */
+    settings?: {
+      [k: string]: unknown;
+    };
+    /**
+     * Flag, whether the embedded component should be hidden by default
+     */
+    hiddenByDefault?: {
+      [k: string]: unknown;
+    };
+    /**
+     * Represents group title of reuse components
+     */
+    groupTitle?: string;
+    /**
+     * Represents a section that behaves a leading section for the group
+     */
+    leadingSectionIdOrPath?: string;
+    [k: string]: unknown;
+  } & (
+    | {
+        /**
+         * Represents the name of the reuse component
+         */
+        componentName: string;
+        [k: string]: unknown;
+      }
+    | {
+        /**
+         * Represents the reference to the name of the componentUsages defined in sap.ui5/componentUsages
+         */
+        componentUsage: string;
+        [k: string]: unknown;
+      }
+    | {
+        embeddedComponents: EmbeddedComponent1;
+        [k: string]: unknown;
+      }
+  );
+}
+export interface EmbeddedComponent1 {
+  /**
+   * This interface was referenced by `EmbeddedComponent`'s JSON-Schema definition
+   * via the `patternProperty` "^[a-zA-Z0-9_.:-]+$".
+   *
+   * This interface was referenced by `EmbeddedComponent2`'s JSON-Schema definition
+   * via the `patternProperty` "^[a-zA-Z0-9_.:-]+$".
+   */
+  [k: string]: {
+    /**
+     * Represents an unique id for the instance of the reuse component inside of the object page
+     */
+    id: string;
+    /**
+     * Represents the title for the content of the reuse component
+     */
+    title: string;
+    /**
+     * Represents an optional element binding  for the ComponentContainer that hosts the reuse component
+     */
+    binding?: string;
+    /**
+     * Represents a map to populate the API of the reuse component
+     */
+    settings?: {
+      [k: string]: unknown;
+    };
+    /**
+     * Flag, whether the embedded component should be hidden by default
+     */
+    hiddenByDefault?: {
+      [k: string]: unknown;
+    };
+    /**
+     * Represents group title of reuse components
+     */
+    groupTitle?: string;
+    /**
+     * Represents a section that behaves a leading section for the group
+     */
+    leadingSectionIdOrPath?: string;
+    [k: string]: unknown;
+  } & (
+    | {
+        /**
+         * Represents the name of the reuse component
+         */
+        componentName: string;
+        [k: string]: unknown;
+      }
+    | {
+        /**
+         * Represents the reference to the name of the componentUsages defined in sap.ui5/componentUsages
+         */
+        componentUsage: string;
+        [k: string]: unknown;
+      }
+    | {
+        embeddedComponents: EmbeddedComponent1;
+        [k: string]: unknown;
+      }
+  );
+}
+/**
+ * Represents the routing specification
+ */
+export interface RoutingSpecDef {
+  /**
+   * Represents the name of the route
+   */
+  routeName: string;
+  /**
+   * Represents the switch to indicate, that this route is not related to the OData service
+   */
+  noOData?: boolean;
+  /**
+   * Represents the binding string to indicate, how the page should be bound relative to the predecessor page or absolute
+   */
+  binding?: string;
+  /**
+   * Represents the the title to be shown on the page
+   */
+  headerTitle?: string;
+  /**
+   * Represents the URL pointing to an icon, that will be shown in the navigation menu additional to the title to represent the page
+   */
+  typeImageUrl?: string;
+  /**
+   * Represents the switch to indicate, whether this route is reached via a 1:1 navigation or a 1:n navigation
+   */
+  noKey?: boolean;
+  /**
+   * Name of a semantic key field which can be used to identify an instance of this page. Only relevant if nKey is false.
+   */
+  semanticKey?: string;
+}
+export interface ComponentPagesDef {
+  [k: string]: PagesMap;
+}
+/**
+ * This interface was referenced by `ComponentPagesDef`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]+[\|]?[a-zA-Z0-9_\.\-]+$".
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]+[\|]?[a-zA-Z0-9_\.\-]+$".
+ */
+export interface PagesMap {
+  /**
+   * Represents the navigation property that leads to this page. The navigation links of the previous page (the page that calls this one) are determined through this property
+   */
+  navigationProperty?: string;
+  /**
+   * Represents the entity set that defines either the aggregation or the root object of the component
+   */
+  entitySet?: string;
+  component: ComponentDef1;
+  navigation?: NavigationDef1;
+  embeddedComponents?: EmbeddedComponent2;
+  routingSpec?: RoutingSpecDef1;
+  /**
+   * Represents the component to be loaded inside the canvas if sap.suite.ui.generic.template.Canvas is used as component name, and its settings
+   */
+  implementingComponent?:
+    | {
+        /**
+         * Represents the name of the component to be loaded inside the canvas
+         */
+        componentName: string;
+        binding?: ComponentBindingDef;
+        settings?: ComponentSettingDef;
+        pages?: ComponentPagesDef;
+      }
+    | {
+        /**
+         * Represents the reference to the name of the componentUsages defined in sap.ui5/componentUsages for the component to be loaded inside the canvas
+         */
+        componentUsage: string;
+        binding?: ComponentBindingDef;
+        settings?: ComponentSettingDef;
+        pages?: ComponentPagesDef;
+      };
+  /**
+   * Default layout used to open the corresponding page in FlexibleColumnLayout
+   */
+  defaultLayoutType?: string;
+  /**
+   * Default layout used to open the corresponding page in FlexibleColumnLayout when reached via external navigation
+   */
+  defaultLayoutTypeIfExternalNavigation?: string;
+  pages?: {
+    [k: string]: PagesMap;
+  };
+}
+/**
+ * Represents the component and its settings that makes the page
+ */
+export interface ComponentDef1 {
+  /**
+   * The name of the component
+   */
+  name: string;
+  /**
+   * Switch to create a route for a list (aggregation) if true and routing for an entity if not set or false
+   */
+  list?: boolean;
+  settings?: ComponentSettingDef;
+}
+/**
+ * Represents the different navigation targets
+ */
+export interface NavigationDef1 {
+  display?: ActionPropDef;
+  create?: ActionPropDef1;
+  edit?: ActionPropDef2;
+}
+/**
+ * Represent reuse components that should be appended at the end of the template component
+ */
+export interface EmbeddedComponent2 {
+  /**
+   * This interface was referenced by `EmbeddedComponent`'s JSON-Schema definition
+   * via the `patternProperty` "^[a-zA-Z0-9_.:-]+$".
+   *
+   * This interface was referenced by `EmbeddedComponent2`'s JSON-Schema definition
+   * via the `patternProperty` "^[a-zA-Z0-9_.:-]+$".
+   */
+  [k: string]: {
+    /**
+     * Represents an unique id for the instance of the reuse component inside of the object page
+     */
+    id: string;
+    /**
+     * Represents the title for the content of the reuse component
+     */
+    title: string;
+    /**
+     * Represents an optional element binding  for the ComponentContainer that hosts the reuse component
+     */
+    binding?: string;
+    /**
+     * Represents a map to populate the API of the reuse component
+     */
+    settings?: {
+      [k: string]: unknown;
+    };
+    /**
+     * Flag, whether the embedded component should be hidden by default
+     */
+    hiddenByDefault?: {
+      [k: string]: unknown;
+    };
+    /**
+     * Represents group title of reuse components
+     */
+    groupTitle?: string;
+    /**
+     * Represents a section that behaves a leading section for the group
+     */
+    leadingSectionIdOrPath?: string;
+    [k: string]: unknown;
+  } & (
+    | {
+        /**
+         * Represents the name of the reuse component
+         */
+        componentName: string;
+        [k: string]: unknown;
+      }
+    | {
+        /**
+         * Represents the reference to the name of the componentUsages defined in sap.ui5/componentUsages
+         */
+        componentUsage: string;
+        [k: string]: unknown;
+      }
+    | {
+        embeddedComponents: EmbeddedComponent1;
+        [k: string]: unknown;
+      }
+  );
+}
+/**
+ * Represents the routing specification
+ */
+export interface RoutingSpecDef1 {
+  /**
+   * Represents the name of the route
+   */
+  routeName: string;
+  /**
+   * Represents the switch to indicate, that this route is not related to the OData service
+   */
+  noOData?: boolean;
+  /**
+   * Represents the binding string to indicate, how the page should be bound relative to the predecessor page or absolute
+   */
+  binding?: string;
+  /**
+   * Represents the the title to be shown on the page
+   */
+  headerTitle?: string;
+  /**
+   * Represents the URL pointing to an icon, that will be shown in the navigation menu additional to the title to represent the page
+   */
+  typeImageUrl?: string;
+  /**
+   * Represents the switch to indicate, whether this route is reached via a 1:1 navigation or a 1:n navigation
+   */
+  noKey?: boolean;
+  /**
+   * Name of a semantic key field which can be used to identify an instance of this page. Only relevant if nKey is false.
+   */
+  semanticKey?: string;
+}
+/**
+ * Represents specific attributes for Fiori Elements
+ */
+export interface JSONSchemaForSAPFENamespace {
+  [k: string]: unknown;
+}
+/**
+ * Represents FLP specific attributes
+ */
+export interface JSONSchemaForSAPFLPNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0" | "1.3.0";
+  /**
+   * Represents size of the tile
+   */
+  tileSize?: "1x1" | "1x2";
+  /**
+   * Represents the type of FLP entry. It must be 'application' or 'tile' or 'plugin'
+   */
+  type: "application" | "tile" | "plugin";
+  /**
+   * Represents configuration parameters of the FLP entry
+   */
+  config?: {
+    /**
+     * Represents the configuration key and values
+     *
+     * This interface was referenced by `undefined`'s JSON-Schema definition
+     * via the `patternProperty` "^[a-zA-Z0-9\_\.\-]*$".
+     */
+    [k: string]: {
+      [k: string]: unknown;
+    };
+  };
+  /**
+   * Represents the original tile and target mapping which resulted in this app
+   */
+  origin?: {
+    /**
+     * Represents the original tile which resulted in this app
+     */
+    tileId?: string;
+    /**
+     * Represents the original target mapping which resulted in this app
+     */
+    targetMappingId?: string;
+  };
+}
+/**
+ * Represents OVP specific attributes
+ */
+export interface JSONSchemaForSAPOVPNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0" | "1.3.0" | "1.4.0" | "1.5.0" | "1.6.0" | "1.7.0" | "1.8.0" | "1.9.0" | "1.10.0";
+  /**
+   * Represents the name of global filter OData model, which  contains entities definition that are relevant for global filters
+   */
+  globalFilterModel?: string;
+  /**
+   * Represents the entity to use as global filter in the smart filter bar control
+   */
+  globalFilterEntityType?: string;
+  /**
+   * Represents the entity set to use as global filter in the smart filter bar control
+   */
+  globalFilterEntitySet?: string;
+  /**
+   * Represents a switch to include basic search in the global filters
+   */
+  showBasicSearch?: boolean;
+  /**
+   * Represents a switch to disable the error page shown on load of overview page when no data is retreived from the backend
+   */
+  disableErrorPage?: boolean;
+  /**
+   * Represents a switch to activate smart variant management in the global filters
+   */
+  smartVariantRequired?: boolean;
+  /**
+   * Represents a switch to show smart filter bar in expanded or collapsed mode
+   */
+  bHeaderExpanded?: boolean;
+  /**
+   * Represents the layout of the card container
+   */
+  containerLayout?: "fixed" | "resizable";
+  /**
+   * Represents a switch to Enable or disable Relative or Normal date formating in ovp application
+   */
+  showDateInRelativeFormat?: boolean;
+  /**
+   * Represents a switch to Enable or Disable the Flexibility of Table cards
+   */
+  disableTableCardFlexibility?: boolean;
+  /**
+   * Represents the switch to activate live update in the global filters, else manual update will be required
+   */
+  enableLiveFilter?: boolean;
+  /**
+   * Enable loading of cards when they enter viewport
+   */
+  enableLazyRendering?: boolean;
+  refreshStrategyOnAppRestore?: RefreshStrategiesPropDef1;
+  /**
+   * Flag to enable/disable analytical parameter support for Smart filter bar
+   */
+  considerAnalyticalParameters?: boolean;
+  /**
+   * Time interval in minutes to auto refresh the card models
+   */
+  refreshIntervalInMinutes?: number;
+  /**
+   * Flag to enable/disable semantic date range control for Smart filter bar
+   */
+  useDateRangeType?: boolean;
+  /**
+   * Represents the object to store analytical chart settings
+   */
+  chartSettings?: {
+    /**
+     * Flag to enable data labels on analytical charts
+     */
+    showDataLabel?: boolean;
+    [k: string]: unknown;
+  };
+  /**
+   * Represents the object to store filter bar configuration
+   */
+  filterSettings?: {
+    /**
+     * Represents the object to store date type filter fields configuration
+     */
+    dateSettings?: {
+      /**
+       * Flag to enable DateTimeRange setting for date type filter fields with filter restriction interval
+       */
+      useDateRange?: boolean;
+      /**
+       * Represents the semantic date values selected for the date filter field
+       */
+      selectedValues?: string;
+      /**
+       * Flag to exclude values from the date picker
+       */
+      exclude?: boolean;
+      /**
+       * Represents the filter field definition for each field
+       */
+      fields?: {
+        [k: string]: FilterFieldName;
+      };
+      [k: string]: unknown;
+    };
+    [k: string]: unknown;
+  };
+  /**
+   * Represents the object to define data loading behaviour for an overview page application
+   */
+  dataLoadSettings?: {
+    /**
+     * Data load behaviour options on application launch
+     */
+    loadDataOnAppLaunch?: "always" | "never" | "ifAnyFilterExist";
+    [k: string]: unknown;
+  };
+  cards: {
+    [k: string]: Card;
+  };
+  resizableLayout?: {
+    [k: string]: ResizableLayoutVariant;
+  };
+}
+/**
+ * Represents the refresh strategies configured for OVP while coming back to the source app
+ */
+export interface RefreshStrategiesPropDef1 {
+  /**
+   * Represents the map of entity sets configured for refresh strategies
+   */
+  entitySets?: {
+    [k: string]: unknown;
+  };
+}
+/**
+ * Represents the configuration object for each date filter field
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]*$".
+ */
+export interface FilterFieldName {
+  /**
+   * Represents the configuration for setting default value for the date filter field
+   */
+  defaultValue?: {
+    /**
+     * Represents the default semantic date value to be set on the filter field
+     */
+    operation?: string;
+    [k: string]: unknown;
+  };
+  /**
+   * Represents the semantic date values selected for the date filter field
+   */
+  selectedValues?: string;
+  /**
+   * Represents the custom implementation for semantic date filter field
+   */
+  customDateRangeImplementation?: string;
+  /**
+   * Flag to exclude values from the date picker
+   */
+  exclude?: boolean;
+  [k: string]: unknown;
+}
+/**
+ * Represents the card attributes
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]+$".
+ */
+export interface Card {
+  /**
+   * Represents the position of the card in the sequence
+   */
+  sequencePos?: number;
+  /**
+   * Represents the model for the card
+   */
+  model?: string;
+  /**
+   * Represents the card component path to use for this card
+   */
+  template: string;
+  settings?: CardSetting;
+  /**
+   * Represents the card with view switch control
+   *
+   * @minItems 1
+   */
+  tabs?: [TabSetting, ...TabSetting[]];
+}
+/**
+ * Represents the card specific properties - properties that are passed to the card
+ */
+export interface CardSetting {
+  /**
+   * Represents the category of the card- used in the card header
+   */
+  category?: string;
+  /**
+   * Represents the user defined string in placeholder card
+   */
+  itemText?: string;
+  /**
+   * Represents language-dependent title of the card - used in the card header
+   */
+  title: string;
+  /**
+   * Represents language-dependent subtitle of the card - used in the card header
+   */
+  subTitle?: string;
+  /**
+   * Represents things like people, number of items
+   */
+  valueSelectionInfo?: string;
+  /**
+   * Represents the entity set that will be displayed in this card
+   */
+  entitySet?: string;
+  /**
+   * Represents the static content that will be displayed in this card
+   */
+  staticContent?: {
+    [k: string]: unknown;
+  }[];
+  /**
+   * Represents the flavor of the list to use in this card. The flavor can be bar chart, carousel or standard
+   */
+  listFlavor?: "standard" | "bar" | "carousel";
+  /**
+   * Represents the type of list to use for this card. The list can be extended to display more information or condensed to take up less space on the card
+   */
+  listType?: "extended" | "condensed";
+  /**
+   * Represents the sort key for the entity set
+   */
+  sortBy?: string;
+  /**
+   * Represents the sort order for the entity set
+   */
+  sortOrder?: "ascending" | "descending";
+  /**
+   * Represents the annotation path
+   */
+  annotationPath?: string;
+  /**
+   * Represents the selection annotation path
+   */
+  selectionAnnotationPath?: string;
+  /**
+   * Represents the chart annotation path
+   */
+  chartAnnotationPath?: string;
+  /**
+   * Represents the presentation annotation path
+   */
+  presentationAnnotationPath?: string;
+  /**
+   * Represents the data point annotation path
+   */
+  dataPointAnnotationPath?: string;
+  /**
+   * Represents the identification annotation path
+   */
+  identificationAnnotationPath?: string;
+  /**
+   * Represents the KPI annotation path
+   */
+  kpiAnnotationPath?: string;
+  /**
+   * Represents the selection presentation annotation path
+   */
+  selectionPresentationAnnotationPath?: string;
+  /**
+   * Represents the dynamic subtitle annotation path
+   */
+  dynamicSubtitleAnnotationPath?: string;
+  /**
+   * Represents the flag to indicate priority of number formatting over sap text
+   */
+  ignoreSapText?: boolean;
+  /**
+   * Represents the flag to enable/disable individual card's functionality to add them to insight
+   */
+  enableAddToInsights?: boolean;
+  /**
+   * Represents the flag to show/hide individual card's functionality to refresh the card
+   */
+  showRefresh?: boolean;
+  defaultSpan?: DefaultSpanDef;
+  /**
+   * Represents the cards for which authorization is required
+   */
+  requireAppAuthorization?: string;
+  objectStreamCardsSettings?: ObjectStreamCardsSettingsDef;
+  /**
+   * Represents the flag to indicate the use of object number/smart field
+   */
+  enableLocaleCurrencyFormatting?: boolean;
+  /**
+   * Represents the configuration to alter the navigation mode in OVP Analytical Cards
+   */
+  navigation?: "dataPointNav" | "chartNav" | "headerNav" | "noHeaderNav";
+  /**
+   * Represents a switch to Show or Hide Filters in Cards Headers in OVP application
+   */
+  showFilterInHeader?: boolean;
+  /**
+   * Represents a switch to Show or Hide Sorting in Cards Headers in OVP application
+   */
+  showSortingInHeader?: boolean;
+  /**
+   * Flag for enabling images in a condensed list card
+   */
+  imageSupported?: boolean;
+  /**
+   * Flag for show line item detail in list and table card
+   */
+  showLineItemDetail?: boolean;
+  /**
+   * This property is responsible for showing and hiding text labels on the geo spots
+   */
+  showLabelText?: boolean;
+  /**
+   * This property is responsible for passing custom parameters present in the entity set to the navigating application
+   */
+  customParams?: string;
+  /**
+   * This property is responsible for setting specific chart settings
+   */
+  chartProperties?: {
+    plotArea?: PlotAreaDef;
+    timeAxis?: TimeAxisDef;
+  };
+  /**
+   * Represents the configuration to customize the column stacked chart
+   */
+  colorPalette?:
+    | {
+        [k: string]: unknown;
+      }[]
+    | {
+        [k: string]: unknown;
+      };
+  [k: string]: unknown;
+}
+/**
+ * Represents the Object Stream properties - properties that are passed to the Object Stream cards
+ */
+export interface ObjectStreamCardsSettingsDef {
+  /**
+   * Represents the flag to show first action in footer of the Quickview cards
+   */
+  showFirstActionInFooter?: boolean;
+  /**
+   * Represents the custom actions in the Quick View Cards
+   *
+   * @minItems 1
+   */
+  customActions?: [CustomActionsSetting, ...CustomActionsSetting[]];
+  [k: string]: unknown;
+}
+/**
+ * Represents the properties for the custom actions in the Quick View Cards
+ */
+export interface CustomActionsSetting {
+  /**
+   * Text displayed for extended actions in Quick View
+   */
+  text?: string;
+  /**
+   * Name of the press handler for extended actions in Quick View
+   */
+  press?: string;
+  /**
+   * Position of extended actions in Quick View
+   */
+  position?: number;
+  [k: string]: unknown;
+}
+/**
+ * Plot area is a parent property which defines multiple other properties for smoothness and marker size
+ */
+export interface PlotAreaDef {
+  /**
+   * Represents whether smoother curves are required or not
+   */
+  isSmoothed?: boolean;
+  /**
+   * Represents the size of the markers in scatter plots
+   */
+  markerSize?: number;
+  /**
+   * dataLabel is a parent property that defines other properties for type
+   */
+  dataLabel?: {
+    /**
+     * Defines whether to display percentage values or actual counts in the donut chart
+     */
+    type?: "value" | "percentage";
+  };
+}
+/**
+ * Represents the configuration to customize the time axis
+ */
+export interface TimeAxisDef {
+  levels?: LevelsDef;
+  [k: string]: unknown;
+}
+/**
+ * Represents the tab specific properties - properties that are passed to a particular tab in a card
+ */
+export interface TabSetting {
+  /**
+   * Represents the annotation path
+   */
+  annotationPath?: string;
+  /**
+   * Represents the selection annotation path
+   */
+  selectionAnnotationPath?: string;
+  /**
+   * Represents the chart annotation path
+   */
+  chartAnnotationPath?: string;
+  /**
+   * Represents the presentation annotation path
+   */
+  presentationAnnotationPath?: string;
+  /**
+   * Represents the data point annotation path
+   */
+  dataPointAnnotationPath?: string;
+  /**
+   * Represents the identification annotation path
+   */
+  identificationAnnotationPath?: string;
+  /**
+   * Represents the dynamic subtitle annotation path
+   */
+  dynamicSubtitleAnnotationPath?: string;
+  /**
+   * Represents the drop down value to be shown
+   */
+  value?: string;
+  /**
+   * This property is responsible for setting specific chart settings
+   */
+  chartProperties?: {
+    plotArea?: PlotAreaDef;
+    timeAxis?: TimeAxisDef;
+  };
+  /**
+   * Represents the configuration to customize the column stacked chart
+   */
+  colorPalette?:
+    | {
+        [k: string]: unknown;
+      }[]
+    | {
+        [k: string]: unknown;
+      };
+  [k: string]: unknown;
+}
+/**
+ * Represents the resizable layout variant
+ *
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^cols_[0-9]+$".
+ */
+export interface ResizableLayoutVariant {
+  [k: string]: ResizableLayoutVariantCardProperties;
+}
+/**
+ * Represents the card properties is a layout variant
+ *
+ * This interface was referenced by `ResizableLayoutVariant`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]+$".
+ */
+export interface ResizableLayoutVariantCardProperties {
+  /**
+   * Represents the grid column
+   */
+  col: number;
+  /**
+   * Represents the grid row
+   */
+  row: number;
+  /**
+   * Represents the column span
+   */
+  colSpan: number;
+  /**
+   * Represents the row span
+   */
+  rowSpan: number;
+  /**
+   * Represents the visibility of the card
+   */
+  visible?: boolean;
+}
+/**
+ * Represents Insights attributes
+ */
+export interface JSONSchemaForSAPInsightsNamespace {
+  _version?: "1.0.0" | "1.1.0" | "1.2.0" | "1.3.0" | "1.4.0" | "1.5.0";
+  /**
+   * Represents mandatory unique app identifier of the app containing self manifest.
+   */
+  parentAppId: string;
+  /**
+   * Represents the entity to use as global filter in the filter bar control
+   */
+  filterEntitySet?: string;
+  /**
+   * Represents the template name, from where manifest is generated
+   */
+  templateName?: string;
+  /**
+   * Represents the environment type of Insights card
+   */
+  cardType: "DT" | "RT";
+  /**
+   * Represents the state of original or copied card
+   */
+  isDtCardCopy?: boolean;
+  /**
+   * Represents the deleted state for a user
+   */
+  isDeletedForUser?: boolean;
+  /**
+   * Represents the visibility type of Insights card
+   */
+  visible?: boolean;
+  /**
+   * Deprecated: Represents the display order of Insights card
+   */
+  rank?: number;
+  /**
+   * Represents UI5 and card generator middleware version.
+   */
+  versions?: {
+    /**
+     * Represents the version of UI5 used to generate the card.
+     */
+    ui5?: string;
+    /**
+     * Represents the version of design time card generator
+     */
+    dtMiddleware?: string;
+    [k: string]: unknown;
+  };
+  /**
+   * New property representing the display order of Insights card
+   */
+  ranking?: string;
+  /**
+   * Array of all supported chart type allowed for transformation.
+   */
+  allowedChartTypes?: (
+    | "bar"
+    | "column"
+    | "line"
+    | "bullet"
+    | "vertical_bullet"
+    | "100_stacked_bar"
+    | "100_stacked_column"
+    | "waterfall"
+    | "horizontal_waterfall"
+    | "area"
+    | "radar"
+    | "combination"
+    | "stacked_bar"
+    | "stacked_column"
+    | "stacked_combination"
+    | "horizontal_stacked_combination"
+    | "pie"
+    | "donut"
+    | "dual_bar"
+    | "dual_column"
+    | "dual_line"
+    | "dual_stacked_bar"
+    | "dual_stacked_column"
+    | "dual_combination"
+    | "dual_horizontal_combination"
+    | "dual_stacked_combination"
+    | "dual_horizontal_stacked_combination"
+    | "100_dual_stacked_bar"
+    | "100_dual_stacked_column"
+    | "scatter"
+    | "heatmap"
+    | "timeseries_column"
+    | "timeseries_line"
+    | "timeseries_scatter"
+    | "timeseries_stacked_column"
+    | "timeseries_100_stacked_column"
+    | "timeseries_bullet"
+    | "timeseries_waterfall"
+    | "timeseries_stacked_combination"
+  )[];
+}
+/**
+ * Represents WDA specific attributes
+ */
+export interface JSONSchemaForSAPWDANamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0";
+  /**
+   * Represents ID of an application
+   */
+  applicationId: string;
+  /**
+   * Represents ID of an application configuration
+   */
+  configId?: string;
+  /**
+   * Represents SAP Screen Personas Flavor ID
+   */
+  flavorId?: string;
+  /**
+   * Indicates that WebDynpro Application requires Compatibility Mode, while uses legacy shell services. Possible values are true or false (default)
+   */
+  compatibilityMode?: boolean;
+}
+/**
+ * Represents APF specific attributes
+ */
+export interface JSONSchemaForSAPAPFNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0";
+  /**
+   * Represents a switch to activate filter reduction so that filters in OData requests can be represented as ABAP select options
+   */
+  activateFilterReduction?: boolean;
+  /**
+   * Represents a switch to activate LREP as the persistence for configurations and texts
+   */
+  activateLrep?: boolean;
+  /**
+   * Represents a switch to use HEAD-Requests instead of GET-Requests when fetching the XSRF-Security-Token
+   */
+  useHeadRequestForXsrfToken?: boolean;
+}
+/**
+ * Represents Cloud Portal specific attributes
+ */
+export interface JSONSchemaForSAPCLOUDPORTALNamespace {
+  [k: string]: unknown;
+}
+/**
+ * Represents GUI specific attributes
+ */
+export interface JSONSchemaForSAPGUINamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0" | "1.2.0";
+  /**
+   * Represents transaction of an application
+   */
+  transaction: string;
+  /**
+   * Represents SAP Screen Personas Flavor ID
+   */
+  flavorId?: string;
+}
+/**
+ * Represents Application Integration specific attributes
+ */
+export interface JSONSchemaForSAPINTEGRATIONNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0";
+  /**
+   * Reference to the desired URL Template
+   */
+  urlTemplateId: string;
+  /**
+   * Represents configuration parameters which will be used by Template Engine to compile URL Template
+   */
+  parameters: {
+    /**
+     * Represents the name of the desired parameter
+     */
+    key: string;
+    /**
+     * Represents the actual value of the desired parameter
+     */
+    value: string;
+    [k: string]: unknown;
+  }[];
+  [k: string]: unknown;
+}
+/**
+ * Represents WCF Application specific attributes
+ */
+export interface JSONSchemaForSAPWCFNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0";
+  /**
+   * Represents the target technical id for a WCF Application
+   */
+  "wcf-target-id": string;
+}
+/**
+ * Represents specific attributes for Smart Business
+ */
+export interface JSONSchemaForSAPUISMARTBUSINESSAPPNamespace {
+  [k: string]: unknown;
+}
+/**
+ * Represents mobile specific attributes
+ */
+export interface JSONSchemaForSAPMOBILENamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.1.0";
+  /**
+   * Represents mobile specific attributes
+   */
+  definingRequests: {
+    [k: string]: DefiningRequest;
+  };
+  [k: string]: unknown;
+}
+/**
+ * This interface was referenced by `undefined`'s JSON-Schema definition
+ * via the `patternProperty` "^[a-zA-Z0-9_\.\-]*".
+ */
+export interface DefiningRequest {
+  /**
+   * Represents reference to dataSource under sap.app
+   */
+  dataSource: string;
+  /**
+   * Represents path to the title collection
+   */
+  path: string;
+  /**
+   * Represents indicator whether streams should be retrieved
+   */
+  retrieveStreams?: boolean;
+}
+/**
+ * Represents specific attributes for SAP CoPilot
+ */
+export interface JSONSchemaForSAPCOPILOTNamespace {
+  /**
+   * Represents SAP.COPILOT attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0" | "1.1.0";
+  /**
+   * Settings for the context analysis features of SAP CoPilot
+   */
+  contextAnalysis?: {
+    /**
+     * Enable/Disable the ability for SAP CoPilot to analyze your Application Screens and add the found objects to a Collection
+     */
+    allowAddingObjectsFromAppScreenToCollection?: boolean;
+    /**
+     * A list of the whitelisted EntityTypes, prefixed with their namespace, that SAP CoPilot can display. The empty list is ignored, thus allowing all EntityTypes by default.
+     */
+    whitelistedEntityTypes?: string[];
+    [k: string]: unknown;
+  };
+  /**
+   * Settings for the Digital Assistant features of SAP CoPilot
+   */
+  digitalAssistant?: {
+    /**
+     * A list of Intent
+     */
+    intentDefinition?: {
+      /**
+       * This interface was referenced by `undefined`'s JSON-Schema definition
+       * via the `patternProperty` "^[a-zA-Z0-9_\.\-]*$".
+       */
+      [k: string]: {
+        /**
+         * Represents the uri of the intent
+         */
+        uri?: string;
+        /**
+         * A list of the sap.app.dataSources used by the intent
+         */
+        dataSources?: string[];
+        /**
+         * Represents the uri of the translation file
+         */
+        i18n?: string;
+        [k: string]: unknown;
+      };
+    };
+    [k: string]: unknown;
+  };
+  [k: string]: unknown;
+}
+/**
+ * Represents specific attributes for SAP.MAP
+ */
+export interface JSONSchemaForSAPMAPNamespace {
+  [k: string]: unknown;
+}
+/**
+ * Represents specific attributes for SAP URL
+ */
+export interface JSONSchemaForSAPURLNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0";
+  /**
+   * Represents URI of an application
+   */
+  uri: string;
+}
+/**
+ * Represents SFSF platform specific attributes
+ */
+export interface JSONSchemaForSAPPLATFORMSFSFNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0";
+  /**
+   * Represents the uri inside the SFSF app
+   */
+  uri?: string;
+  /**
+   * Represents the SFSF application name
+   */
+  appName: string;
+  /**
+   * Represents the version of the SFSF application
+   */
+  appVersion?: string;
+}
+/**
+ * Represents cloud platform specific attributes
+ */
+export interface JSONSchemaForSAPCLOUDNamespace {
+  /**
+   * Represents attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0" | "1.1.0" | "1.2.0";
+  /**
+   * Unique Business Service Identifier
+   */
+  service?: string;
+  /**
+   * Specify if the UI can be accessed from a different space than origin development space
+   */
+  public?: boolean;
+}
+/**
+ * Represents general package attributes. Experimental, will be detailed in the future
+ */
+export interface JSONSchemaForSAPPACKAGENamespace {
+  /**
+   * Represents SAP.PACKAGE attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0" | "1.1.0" | "1.2.0";
+  /**
+   * Represents mandatory unique package identifier
+   */
+  id: string;
+  /**
+   * Represents path inside the package to the properties file containing text symbols for the packages texts
+   */
+  i18n?: string;
+  /**
+   * Represents mandatory semantic version of the package information and optional the upgrade notification
+   */
+  packageVersion: {
+    /**
+     * Represents mandatory semantic version of the package
+     */
+    version: string;
+    /**
+     * Represents optional upgrade notification once the package is available. none - no notification, package will be installed automatically for any version. major - notification before a new major version is installed. major.minor - notification before a major and minor version is installed. all - notification before any new version is installed, including patches
+     */
+    upgradeNotification?: "none" | "major" | "major.minor" | "all";
+    [k: string]: unknown;
+  };
+  /**
+   * Represents type of an package and can be card, workflow, workspace-template
+   */
+  type?: "card" | "workflow" | "workspace-template";
+  /**
+   * Represents a title (mandatory); to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  title: string;
+  /**
+   * Represents a subtitle to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  subTitle?: string;
+  /**
+   * Represents a shorter version of the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  shortTitle?: string;
+  /**
+   * Represents additional information to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  info?: string;
+  /**
+   * Represents a description; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  description: string;
+  /**
+   * Represents icon name or source URL for the package
+   */
+  icon?: string;
+  /**
+   * Represents array of keywords used to find the package
+   */
+  tags?: {
+    keywords: Tag;
+    technicalAttributes?: string[];
+    [k: string]: unknown;
+  };
+  vendor: Vendor;
+  homepage?: Infolink;
+  support: Infolink1;
+  documentation?: Infolink2;
+  contents?: Contentitem[];
+  /**
+   * Represents list of product ids that are allowed to consume this package. if not defined all products that are capable of installing this package are allowed
+   */
+  consumption?: string[];
+  /**
+   * Represents the products and service that the pacakge depends on
+   */
+  dependencies?: {
+    /**
+     * List of products that this package depends on
+     */
+    products?: string[];
+    /**
+     * List of services that this package depends on
+     */
+    services?: string[];
+    [k: string]: unknown;
+  };
+  [k: string]: unknown;
+}
+/**
+ * Represents the support information
+ */
+export interface Vendor {
+  /**
+   * Represents the vendor id
+   */
+  id: string;
+  /**
+   * Represents the vendor name
+   */
+  name: string;
+  /**
+   * Represents the vendor line of business within the vendors organization if any
+   */
+  lineOfBusiness?: string;
+  /**
+   * Represents a target url
+   */
+  url: string;
+  [k: string]: unknown;
+}
+/**
+ * Represents the homepage information
+ */
+export interface Infolink {
+  /**
+   * Represents a target url
+   */
+  url: string;
+  /**
+   * Represents a descriptive text for the target
+   */
+  text: string;
+  [k: string]: unknown;
+}
+/**
+ * Represents the support information
+ */
+export interface Infolink1 {
+  /**
+   * Represents a target url
+   */
+  url: string;
+  /**
+   * Represents a descriptive text for the target
+   */
+  text: string;
+  [k: string]: unknown;
+}
+/**
+ * Represents the documentation information
+ */
+export interface Infolink2 {
+  /**
+   * Represents a target url
+   */
+  url: string;
+  /**
+   * Represents a descriptive text for the target
+   */
+  text: string;
+  [k: string]: unknown;
+}
+/**
+ * Represents the artifacts contained in the package
+ */
+export interface Contentitem {
+  /**
+   * Relative url to the artifact within the folder in this package
+   */
+  baseURL?: string;
+  /**
+   * Wraps the child manifest
+   */
+  manifest?: {
+    /**
+     * The artifacts manifest
+     */
+    "sap.artifact"?: {
+      [k: string]: unknown;
+    };
+    [k: string]: unknown;
+  };
+  [k: string]: unknown;
+}
+/**
+ * Represents general artifact attributes.
+ */
+export interface JSONSchemaForSAPARTIFACTNamespace {
+  /**
+   * Represents SAP.ARTIFACT attributes format version. It is managed by namespace owner
+   */
+  _version?: "1.0.0" | "1.1.0" | "1.2.0";
+  /**
+   * Represents mandatory unique artifact identifier
+   */
+  id: string;
+  /**
+   * Represents path inside the artifact to the properties file containing text symbols for the artifacts texts
+   */
+  i18n?: string;
+  /**
+   * Represents mandatory semantic version of the artifact
+   */
+  artifactVersion: {
+    version: Semanticversion;
+    [k: string]: unknown;
+  };
+  /**
+   * Represents type of an artifact and can be card, workflow, workspace-template
+   */
+  type: "card" | "workflow" | "workspace-template";
+  /**
+   * Represents a title (mandatory); to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  title: string;
+  /**
+   * Represents a subtitle to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  subTitle?: string;
+  /**
+   * Represents a shorter version of the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  shortTitle?: string;
+  /**
+   * Represents additional information to the title; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  info?: string;
+  /**
+   * Represents a description; to make this property language dependent (recommended), use a key in double curly brackets '{{key}}'
+   */
+  description: string;
+  /**
+   * Represents icon name or source URL for the artifact
+   */
+  icon?: string;
+  /**
+   * Represents array of keywords used to find the artifact
+   */
+  tags?: {
+    keywords: Tag;
+    technicalAttributes?: string[];
+    [k: string]: unknown;
+  };
+  [k: string]: unknown;
+}
diff --git a/src/untyped.d.ts b/src/untyped.d.ts
new file mode 100644
index 000000000..28f7ca57c
--- /dev/null
+++ b/src/untyped.d.ts
@@ -0,0 +1,129 @@
+declare module "@ui5/to-esm" {
+	interface Result {
+		source: string,
+		map: string
+	}
+	export default function ui5ToESM(content: string, options: object): Result;
+}
+
+declare module "@ui5/project" {
+	import {AbstractReader} from "@ui5/fs";
+
+	type ProjectNamespace = string;
+	interface Project {
+		getNamespace: () => ProjectNamespace,
+		getReader: (options: ReaderOptions) => AbstractReader,
+		getRootPath: () => string,
+	}
+	interface ProjectGraph {
+		getRoot: () => Project
+	}
+	interface DependencyTreeNode {
+		id: string,
+		version: string,
+		path: string,
+		configuration?: object | object[],
+		configPath?: string,
+		dependencies: DependencyTreeNode[]
+	}
+}
+
+declare module "@ui5/project/ui5Framework/maven/CacheMode" {
+	enum CacheMode {
+		Default = "Default",
+		Force = "Force",
+		Off = "Off"
+	}
+	export default CacheMode;
+}
+
+declare module "@ui5/project/graph" {
+	import type CacheMode from "@ui5/project/ui5Framework/maven/CacheMode";
+
+	interface GraphFromObjectOptions {
+		dependencyTree: DependencyTreeNode,
+		cwd?: string,
+		rootConfiguration?: object,
+		rootConfigPath?: string,
+		versionOverride?: string,
+		cacheMode?: CacheMode,
+		resolveFrameworkDependencies?: boolean,
+	}
+	export function graphFromObject(options: GraphFromObjectOptions): Promise
+
+	interface GraphFromPackageDependenciesOptions {
+		cwd?: string,
+		rootConfiguration?: object,
+		rootConfigPath?: string,
+		versionOverride?: string,
+		cacheMode?: CacheMode,
+		resolveFrameworkDependencies?: boolean,
+		workspaceName?: string,
+		workspaceConfiguration?: object,
+		workspaceConfigPath?: string
+	}
+	export function graphFromPackageDependencies(options?: GraphFromPackageDependenciesOptions): Promise
+}
+
+declare module "@ui5/fs" {
+	type ResourcePath = string;
+	interface ResourceSourceMetadata {
+		fsPath: string
+	}
+	interface Resource {
+		getBuffer: () => Promise,
+		getString: () => Promise,
+		getStream: () => stream.Readable,
+		getName: () => string,
+		getPath: () => ResourcePath,
+		getProject: () => Project,
+		getSourceMetadata: () => ResourceSourceMetadata
+	}
+	enum ReaderStyles {
+		buildtime = "buildtime",
+		dist = "dist",
+		runtime = "runtime",
+		flat = "flat"
+	}
+	interface ReaderOptions {
+		style: ReaderStyles
+	}
+	interface GlobOptions {
+		nodir?: boolean
+	}
+	interface AbstractReader {
+		byGlob: (virPattern: string | string[], options?: GlobOptions) => Promise
+	}
+	interface AbstractAdapter extends AbstractReader {
+
+	}
+}
+declare module "@ui5/fs/resourceFactory" {
+	export function createAdapter({fsBasePath: string, virBasePath: string}): AbstractAdapter
+	export function createResource({path: string, string: string}): Resource
+}
+
+declare module "@ui5/logger" {
+	interface Logger {
+		silly: (message: string) => void,
+		verbose: (message: string) => void,
+		perf: (message: string) => void,
+		info: (message: string) => void,
+		warn: (message: string) => void,
+		error: (message: string) => void,
+		isLevelEnabled: (level: string) => boolean,
+	}
+
+	export function isLogLevelEnabled(logLevel: string): boolean
+	export function setLogLevel(logLevel: string): void
+	export function getLogLevel(logLevel: string): string
+	export function getLogger(moduleName: string): Logger
+}
+
+declare module "@ui5/logger/writers/Console" {
+	export function stop(): void
+	export function init(): void
+}
+
+// There are no TS Types for json-source-map
+declare module "json-source-map";
diff --git a/test/fixtures/linter/general/Coverage.js b/test/fixtures/linter/general/Coverage.js
new file mode 100644
index 000000000..86e500e94
--- /dev/null
+++ b/test/fixtures/linter/general/Coverage.js
@@ -0,0 +1,28 @@
+sap.ui.define(function () {
+	return function(aFlexObjects, sReference) {
+		const oVariantManagementState = oVariantManagementMapDataSelector.get({ reference: sReference });
+		const aHiddenVariants = [];
+		Object.values(oVariantManagementState).forEach((oVariantManagement) => {
+			oVariantManagement.variants.forEach((oVariant) => {
+				if (oVariant.visible === false) {
+					aHiddenVariants.push(oVariant.key);
+				}
+			});
+		});
+		return aFlexObjects.filter((oFilteredFlexObject) => {
+			// The following block should produce a coverage message:
+			// 	"Unable to analyze this method call because the type of identifier"
+			// However, the following line will be transformed to "[...] = ({ [...]" with
+			// no source map entry for the added brackets (since it does not exist in source).
+			// This poses a challenge for Reporter.ts to map to the correct location in the source file
+			const sVariantReference = {
+				// eslint-disable-next-line camelcase
+				ctrl_variant: () => (oFilteredFlexObject.getVariantId()),
+				// eslint-disable-next-line camelcase
+				ctrl_variant_change: () => (oFilteredFlexObject.getSelector().id),
+				change: () => (oFilteredFlexObject.getVariantReference())
+			}[oFilteredFlexObject.getFileType()]?.();
+			return !aHiddenVariants.includes(sVariantReference);
+		});
+	};
+});
diff --git a/test/fixtures/linter/general/JSDoc.js b/test/fixtures/linter/general/JSDoc.js
new file mode 100644
index 000000000..4e79e4cee
--- /dev/null
+++ b/test/fixtures/linter/general/JSDoc.js
@@ -0,0 +1,23 @@
+sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/core/UIComponent", "sap/ui/core/routing/History", "sap/m/Button"],
+	/**
+	 * @param {typeof import('sap/ui/core/mvc/Controller').default} Controller
+	 * @param {typeof import('sap/ui/core/UIComponent').default} UIComponent
+	 * @param {typeof import('sap/ui/core/routing/History').default} History
+	 * @param {typeof import('sap/m/Button').default} Button
+	 */
+	function (Controller, UIComponent, History, Button) {
+	"use strict";
+
+	return Controller.extend("com.ui5.troublesome.app.controller.BaseController", {
+
+		createButton: function() {
+			var btn = new Button({
+				blocked: true
+			});
+			btn.attachTap(function() {
+				console.log("Tapped");
+			});
+			return btn;
+		},
+	});
+});
diff --git a/test/fixtures/linter/general/PlainJS.js b/test/fixtures/linter/general/PlainJS.js
new file mode 100644
index 000000000..5d7c5a1f1
--- /dev/null
+++ b/test/fixtures/linter/general/PlainJS.js
@@ -0,0 +1,22 @@
+import Controller from "sap/ui/core/mvc/Controller";
+import Button from "sap/m/Button";
+export default class BaseController extends Controller {
+	createButton1() {
+		var btn = this.getNewButton();
+		btn.attachTap(function () {
+			console.log("Tapped");
+		});
+		return btn;
+	}
+	createButton2() {
+		this.getNewButton().attachTap(function () {
+			console.log("Tapped");
+		});
+	}
+	getNewButton() {
+		const newButton = new Button({
+			blocked: true
+		});
+		return newButton;
+	}
+}
diff --git a/test/fixtures/linter/general/Raw.js b/test/fixtures/linter/general/Raw.js
new file mode 100644
index 000000000..ac413c6eb
--- /dev/null
+++ b/test/fixtures/linter/general/Raw.js
@@ -0,0 +1,17 @@
+sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/core/UIComponent", "sap/ui/core/routing/History", "sap/m/Button"],
+	function (Controller, UIComponent, History, Button) {
+	"use strict";
+
+	return Controller.extend("com.ui5.troublesome.app.controller.BaseController", {
+
+		createButton: function() {
+			var btn = new Button({
+				blocked: true
+			});
+			btn.attachTap(function() {
+				console.log("Tapped");
+			});
+			return btn;
+		},
+	});
+});
diff --git a/test/fixtures/linter/general/TSLike.js b/test/fixtures/linter/general/TSLike.js
new file mode 100644
index 000000000..66d7ea105
--- /dev/null
+++ b/test/fixtures/linter/general/TSLike.js
@@ -0,0 +1,19 @@
+import Controller from "sap/ui/core/mvc/Controller";
+import Button from "sap/m/Button";
+
+export default function () {
+	"use strict";
+
+	return Controller.extend("com.ui5.troublesome.app.controller.BaseController", {
+
+		createButton: function() {
+			var btn = new Button({
+				blocked: true
+			});
+			btn.attachTap(function() {
+				console.log("Tapped");
+			});
+			return btn;
+		},
+	});
+}
diff --git a/test/fixtures/linter/general/TypeScript.ts b/test/fixtures/linter/general/TypeScript.ts
new file mode 100644
index 000000000..3063f424b
--- /dev/null
+++ b/test/fixtures/linter/general/TypeScript.ts
@@ -0,0 +1,22 @@
+import Button from "sap/m/Button";
+import UIComponent from "sap/ui/core/UIComponent";
+import Controller from "sap/ui/core/mvc/Controller";
+import History from "sap/ui/core/routing/History";
+
+sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/core/UIComponent", "sap/ui/core/routing/History", "sap/m/Button"],
+	function (Controller: Controller, UIComponent: UIComponent, History: History, Button: Button) {
+	"use strict";
+
+	return Controller.extend("com.ui5.troublesome.app.controller.BaseController", {
+
+		createButton: function() {
+			var btn = new Button({
+				blocked: true
+			});
+			btn.attachTap(function() {
+				console.log("Tapped");
+			});
+			return btn;
+		},
+	});
+});
diff --git a/test/fixtures/linter/general/Undetected.js b/test/fixtures/linter/general/Undetected.js
new file mode 100644
index 000000000..2b1bcc46f
--- /dev/null
+++ b/test/fixtures/linter/general/Undetected.js
@@ -0,0 +1,9 @@
+import Controller from "sap/ui/core/mvc/Controller";
+export default class BaseController extends Controller {
+	attachButtonTap() {
+		var btn = this.getView().byId("button-control");
+		btn.attachTap(function () {
+			console.log("Tapped");
+		});
+	}
+}
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/Component.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/Component.js
new file mode 100644
index 000000000..ad514a8ab
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/Component.js
@@ -0,0 +1,40 @@
+sap.ui.define(["sap/ui/core/UIComponent", "sap/ui/Device", "./model/models"], function (UIComponent, Device, models) {
+	"use strict";
+
+	return UIComponent.extend("com.ui5.troublesome.app.Component", {
+		metadata: {
+			manifest: "json"
+		},
+		init: function () {
+			// call the base component's init function
+			UIComponent.prototype.init.call(this); // create the views based on the url/hash
+
+			// create the device model
+			this.setModel(models.createDeviceModel(), "device");
+
+			// create the views based on the url/hash
+			this.getRouter().initialize();
+		},
+		/**
+		 * This method can be called to determine whether the sapUiSizeCompact or sapUiSizeCozy
+		 * design mode class should be set, which influences the size appearance of some controls.
+		 * @public
+		 * @returns {string} css class, either 'sapUiSizeCompact' or 'sapUiSizeCozy' - or an empty string if no css class should be set
+		 */
+		getContentDensityClass: function () {
+			if (this.contentDensityClass === undefined) {
+				// check whether FLP has already set the content density class; do nothing in this case
+				if (document.body.classList.contains("sapUiSizeCozy") || document.body.classList.contains("sapUiSizeCompact")) {
+					this.contentDensityClass = "";
+				} else if (!Device.support.touch) {
+					// apply "compact" mode if touch is not supported
+					this.contentDensityClass = "sapUiSizeCompact";
+				} else {
+					// "cozy" in case of touch support; default for most sap.m controls, but needed for desktop-first controls like sap.ui.table.Table
+					this.contentDensityClass = "sapUiSizeCozy";
+				}
+			}
+			return this.contentDensityClass;
+		}
+	});
+});
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/App.controller.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/App.controller.js
new file mode 100644
index 000000000..4b7e552c0
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/App.controller.js
@@ -0,0 +1,15 @@
+sap.ui.define(["./BaseController"],
+	function (BaseController) {
+	"use strict";
+
+	return BaseController.extend("com.ui5.troublesome.app.controller.App", {
+		onInit: function () {
+			// apply content density mode to root view
+			this.getView().addStyleClass(this.getOwnerComponent().getContentDensityClass());
+
+			this.createButton().attachTap(function() {
+				console.log("Tapped");
+			});
+		}
+	});
+});
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/BaseController.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/BaseController.js
new file mode 100644
index 000000000..6e27fefd9
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/BaseController.js
@@ -0,0 +1,87 @@
+sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/core/UIComponent", "sap/ui/core/routing/History", "sap/m/Button"],
+	function (Controller, UIComponent, History, Button) {
+	"use strict";
+
+	return Controller.extend("com.ui5.troublesome.app.controller.BaseController", {
+
+		createButton: function() {
+			var btn = new Button({
+				blocked: true
+			});
+			btn.attachTap(function() {
+				console.log("Tapped");
+			});
+			return btn;
+		},
+
+		/**
+		 * Convenience method for accessing the component of the controller's view.
+		 * @returns {sap.ui.core.Component} The component of the controller's view
+		 */
+		getOwnerComponent: function () {
+			return Controller.prototype.getOwnerComponent.call(this);
+		},
+
+		/**
+		 * Convenience method to get the components' router instance.
+		 * @returns {import('sap/m/routing/Router').default} The router instance
+		 */
+		getRouter: function () {
+			return /** @type {import('sap/m/routing/Router').default} */ (UIComponent.getRouterFor(this));
+		},
+
+		/**
+		 * Convenience method for getting the i18n resource bundle of the component.
+		 * @returns {sap.base.i18n.ResourceBundle} The i18n resource bundle of the component
+		 */
+		getResourceBundle: function () {
+			var oModel = this.getOwnerComponent().getModel("i18n");
+			return oModel.getResourceBundle();
+		},
+
+		/**
+		 * Convenience method for getting the view model by name in every controller of the application.
+		 * @param {string} [sName] The model name
+		 * @returns {sap.ui.model.Model} The model instance
+		 */
+		getModel: function (sName) {
+			return this.getView().getModel(sName);
+		},
+
+		/**
+		 * Convenience method for setting the view model in every controller of the application.
+		 * @param {sap.ui.model.Model} oModel The model instance
+		 * @param {string} [sName] The model name
+		 * @returns {sap.ui.core.mvc.Controller} The current base controller instance
+		 */
+		setModel: function (oModel, sName) {
+			this.getView().setModel(oModel, sName);
+			return this;
+		},
+
+		/**
+		 * Convenience method for triggering the navigation to a specific target.
+		 * @public
+		 * @param {string} sName Target name
+		 * @param {object} [oParameters] Navigation parameters
+		 * @param {boolean} [bReplace] Defines if the hash should be replaced (no browser history entry) or set (browser history entry)
+		 */
+		navTo: function (sName, oParameters, bReplace) {
+			this.getRouter().navTo(sName, oParameters, undefined, bReplace);
+		},
+
+		/**
+		 * Convenience event handler for navigating back.
+		 * It there is a history entry we go one step back in the browser history
+		 * If not, it will replace the current entry of the browser history with the main route.
+		 */
+		onNavBack: function () {
+			var sPreviousHash = History.getInstance().getPreviousHash();
+			if (sPreviousHash !== undefined) {
+				window.history.go(-1);
+			} else {
+				this.getRouter().navTo("main", {}, undefined, true);
+			}
+		}
+	});
+});
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/Main.controller.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/Main.controller.js
new file mode 100644
index 000000000..c112e1155
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/controller/Main.controller.js
@@ -0,0 +1,9 @@
+sap.ui.define(["./BaseController", "sap/m/MessageBox"], function (BaseController, MessageBox) {
+	"use strict";
+
+	return BaseController.extend("com.ui5.troublesome.app.controller.Main", {
+		sayHello: function () {
+			MessageBox.show("Hello World!");
+		}
+	});
+});
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/emptyFile.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/emptyFile.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/helpers/ES6Class.helper.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/helpers/ES6Class.helper.js
new file mode 100644
index 000000000..d29dae855
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/helpers/ES6Class.helper.js
@@ -0,0 +1,18 @@
+/*!
+ * ${copyright}
+ */
+
+sap.ui.define([], function () {
+	"use strict";
+
+	class ES6Class {
+		toString() {
+			return this.#join("", "");
+		}
+		#join() {
+			// A private method
+		}
+	}
+
+	return ES6Class;
+});
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n.properties b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n.properties
new file mode 100644
index 000000000..0bdad0ed0
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n.properties
@@ -0,0 +1,3 @@
+appTitle=com.ui5.troublesome.app
+appDescription=UI5 Application com.ui5.troublesome.app
+btnText=Say Hello
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n_de.properties b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n_de.properties
new file mode 100644
index 000000000..f4fbf1085
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n_de.properties
@@ -0,0 +1,3 @@
+appTitle=com.ui5.troublesome.app
+appDescription=UI5 Application com.ui5.troublesome.app
+btnText=Sag Hallo
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n_en.properties b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n_en.properties
new file mode 100644
index 000000000..0bdad0ed0
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/i18n/i18n_en.properties
@@ -0,0 +1,3 @@
+appTitle=com.ui5.troublesome.app
+appDescription=UI5 Application com.ui5.troublesome.app
+btnText=Say Hello
diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/index-cdn.html b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/index-cdn.html
new file mode 100644
index 000000000..b566304fb
--- /dev/null
+++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/index-cdn.html
@@ -0,0 +1,31 @@
+
+
+	
+		
+		
+		
+
+		
+		
+		UI5 Application: com.ui5.troublesome.app
+
+		
+	
+
+	
+		
+ + diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/index.html b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/index.html new file mode 100644 index 000000000..3754d2b54 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/index.html @@ -0,0 +1,30 @@ + + + + + + + + + UI5 Application: com.ui5.troublesome.app + + + + + +
+ + diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/manifest.json b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/manifest.json new file mode 100644 index 000000000..f9e2f51d9 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/manifest.json @@ -0,0 +1,112 @@ +{ + "_version": "1.12.0", + + "sap.app": { + "id": "com.ui5.troublesome.app", + "type": "application", + "i18n": "i18n/i18n.properties", + "title": "{{appTitle}}", + "description": "{{appDescription}}", + "applicationVersion": { + "version": "1.0.0" + }, + "dataSources": { + "v4": { + "uri": "/api/odata-4/", + "type": "OData", + "settings": { + "odataVersion": "4.0" + } + } + } + }, + + "sap.ui": { + "technology": "UI5", + "icons": {}, + "deviceTypes": { + "desktop": true, + "tablet": true, + "phone": true + } + }, + + "sap.ui5": { + "rootView": { + "viewName": "com.ui5.troublesome.app.view.App", + "type": "XML", + "async": true, + "id": "app" + }, + + "dependencies": { + "minUI5Version": "1.119.0", + "libs": { + "sap.ui.core": {}, + "sap.m": {} + } + }, + + "handleValidation": true, + + "contentDensities": { + "compact": true, + "cozy": true + }, + + "resources": { + "js": [{ "uri": "path/to/thirdparty.js" }] + }, + + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "com.ui5.troublesome.app.i18n.i18n" + } + }, + "odata-v4": { + "type": "sap.ui.model.odata.v4.ODataModel", + "settings": { + "synchronizationMode": "None" + } + }, + "odata-v4-via-dataSource": { + "dataSource": "v4", + "settings": { + "synchronizationMode": "None" + } + }, + "odata": { + "type": "sap.ui.model.odata.ODataModel", + "settings": { + "serviceUrl": "/api/odata" + } + } + }, + + "routing": { + "config": { + "routerClass": "sap.m.routing.Router", + "viewType": "XML", + "viewPath": "com.ui5.troublesome.app.view", + "controlId": "app", + "controlAggregation": "pages", + "async": true + }, + "routes": [ + { + "pattern": "", + "name": "main", + "target": "main" + } + ], + "targets": { + "main": { + "viewId": "main", + "viewName": "Main" + } + } + } + } +} diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/model/formatter.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/model/formatter.js new file mode 100644 index 000000000..e6696b237 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/model/formatter.js @@ -0,0 +1,9 @@ +sap.ui.define(function () { + "use strict"; + + return { + formatValue: function (value) { + return value && value.toUpperCase(); + } + }; +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/model/models.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/model/models.js new file mode 100644 index 000000000..557fb72ef --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/model/models.js @@ -0,0 +1,11 @@ +sap.ui.define(["sap/ui/model/json/JSONModel", "sap/ui/model/BindingMode", "sap/ui/Device"], function (JSONModel, BindingMode, Device) { + "use strict"; + + return { + createDeviceModel: function () { + var oModel = new JSONModel(Device); + oModel.setDefaultBindingMode(BindingMode.OneWay); + return oModel; + } + }; +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/HelloJourney.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/HelloJourney.js new file mode 100644 index 000000000..7cb10720f --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/HelloJourney.js @@ -0,0 +1,48 @@ +sap.ui.define(["sap/ui/test/opaQunit", "./pages/Main"], function () { + "use strict"; + + QUnit.module("Sample Hello Journey"); + + opaTest("Should open the Hello dialog", function (Given, When, Then) { + // Arrangements + Given.iStartMyUIComponent({ + componentConfig: { + name: "com.ui5.troublesome.app" + } + }); + + // Actions + When.onTheMainPage.iPressTheSayHelloButton(); + + // Assertions + Then.onTheMainPage.iShouldSeeTheHelloDialog(); + + // Actions + When.onTheMainPage.iPressTheOkButtonInTheDialog(); + + // Assertions + Then.onTheMainPage.iShouldNotSeeTheHelloDialog(); + + // Cleanup + Then.iTeardownMyApp(); + }); + + opaTest("Should close the Hello dialog", function (Given, When, Then) { + // Arrangements + Given.iStartMyUIComponent({ + componentConfig: { + name: "com.ui5.troublesome.app" + } + }); + + // Actions + When.onTheMainPage.iPressTheSayHelloButton(); + When.onTheMainPage.iPressTheOkButtonInTheDialog(); + + // Assertions + Then.onTheMainPage.iShouldNotSeeTheHelloDialog(); + + // Cleanup + Then.iTeardownMyApp(); + }); +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/opaTests.qunit.html b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/opaTests.qunit.html new file mode 100644 index 000000000..95c08eabd --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/opaTests.qunit.html @@ -0,0 +1,31 @@ + + + + + + + + Integration tests for the UI5 Application: com.ui5.troublesome.app + + + + + + + +
+
+ + diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/opaTests.qunit.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/opaTests.qunit.js new file mode 100644 index 000000000..738414493 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/opaTests.qunit.js @@ -0,0 +1,10 @@ +// https://api.qunitjs.com/config/autostart/ +QUnit.config.autostart = false; + +sap.ui.getCore().attachInit(function () { + "use strict"; + + sap.ui.require(["integration/HelloJourney"], function () { + QUnit.start(); + }); +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/pages/Main.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/pages/Main.js new file mode 100644 index 000000000..08b06ed39 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/integration/pages/Main.js @@ -0,0 +1,53 @@ +sap.ui.define(["sap/ui/test/Opa5", "sap/ui/test/actions/Press"], function (Opa5, Press) { + "use strict"; + + Opa5.createPageObjects({ + onTheMainPage: { + actions: { + iPressTheSayHelloButton: function () { + return this.waitFor({ + id: "helloButton", + viewName: "com.ui5.troublesome.app.view.Main", + actions: new Press(), + errorMessage: "Did not find the 'Say Hello With Dialog' button on the App view" + }); + }, + + iPressTheOkButtonInTheDialog: function () { + return this.waitFor({ + controlType: "sap.m.Button", + searchOpenDialogs: true, + viewName: "com.ui5.troublesome.app.view.Main", + actions: new Press(), + errorMessage: "Did not find the 'OK' button in the Dialog" + }); + } + }, + + assertions: { + iShouldSeeTheHelloDialog: function () { + return this.waitFor({ + controlType: "sap.m.Dialog", + success: function () { + // we set the view busy, so we need to query the parent of the app + Opa5.assert.ok(true, "The dialog is open"); + }, + errorMessage: "Did not find the dialog control" + }); + }, + + iShouldNotSeeTheHelloDialog: function () { + return this.waitFor({ + controlType: "sap.m.App", // dummy, I just want a check function, where I can search the DOM. Probably there is a better way for a NEGATIVE test (NO dialog). + check: function () { + return document.querySelectorAll(".sapMDialog").length === 0; + }, + success: function () { + Opa5.assert.ok(true, "No dialog is open"); + } + }); + } + } + } + }); +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/testsuite.qunit.html b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/testsuite.qunit.html new file mode 100644 index 000000000..97f8b3954 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/testsuite.qunit.html @@ -0,0 +1,13 @@ + + + + + + + + QUnit test suite for the UI5 Application: com.ui5.troublesome.app + + + + + diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/testsuite.qunit.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/testsuite.qunit.js new file mode 100644 index 000000000..7e47bf5c1 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/testsuite.qunit.js @@ -0,0 +1,9 @@ +/* eslint-disable */ +window.suite = function () { + var suite = new parent.jsUnitTestSuite(); + var aParts = location.pathname.match(/(.*\/)(?:[^/]+)/); + var sContextPath = aParts && aParts[1]; + suite.addTestPage(sContextPath + "unit/unitTests.qunit.html"); + suite.addTestPage(sContextPath + "integration/opaTests.qunit.html"); + return suite; +}; diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/controller/App.qunit.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/controller/App.qunit.js new file mode 100644 index 000000000..ca9096482 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/controller/App.qunit.js @@ -0,0 +1,10 @@ +sap.ui.define(["com/ui5/troublesome/app/controller/Main.controller"], function (MainController) { + "use strict"; + + QUnit.module("Sample App controller test"); + + QUnit.test("The AppController class has a sayHello method", function (assert) { + // as a very basic test example just check the presence of the "sayHello" method + assert.strictEqual(typeof MainController.prototype.sayHello, "function"); + }); +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/unitTests.qunit.html b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/unitTests.qunit.html new file mode 100644 index 000000000..b3834df83 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/unitTests.qunit.html @@ -0,0 +1,30 @@ + + + + + + + + Unit tests for the UI5 Application: com.ui5.troublesome.app + + + + + + + + + +
+
+ + diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/unitTests.qunit.js b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/unitTests.qunit.js new file mode 100644 index 000000000..25b8d916e --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/test/unit/unitTests.qunit.js @@ -0,0 +1,12 @@ +/* global QUnit */ + +// https://api.qunitjs.com/config/autostart/ +QUnit.config.autostart = false; + +sap.ui.getCore().attachInit(function () { + "use strict"; + + sap.ui.require(["unit/controller/App.qunit"], function () { + QUnit.start(); + }); +}); diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/App.view.xml b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/App.view.xml new file mode 100644 index 000000000..728971e27 --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/App.view.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/Main.view.xml b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/Main.view.xml new file mode 100644 index 000000000..4aad890ac --- /dev/null +++ b/test/fixtures/linter/projects/com.ui5.troublesome.app/webapp/view/Main.view.xml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/test/fixtures/transpiler/xml/CustomData_FESR.fragment.xml b/test/fixtures/transpiler/xml/CustomData_FESR.fragment.xml new file mode 100644 index 000000000..70347f20d --- /dev/null +++ b/test/fixtures/transpiler/xml/CustomData_FESR.fragment.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/test/fixtures/transpiler/xml/DuplicateAggregations.view.xml b/test/fixtures/transpiler/xml/DuplicateAggregations.view.xml new file mode 100644 index 000000000..71c99e8d7 --- /dev/null +++ b/test/fixtures/transpiler/xml/DuplicateAggregations.view.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/fixtures/transpiler/xml/IgnoredNamespaces.fragment.xml b/test/fixtures/transpiler/xml/IgnoredNamespaces.fragment.xml new file mode 100644 index 000000000..d6a58f6e6 --- /dev/null +++ b/test/fixtures/transpiler/xml/IgnoredNamespaces.fragment.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/test/fixtures/transpiler/xml/UnknownAttrNamespace.fragment.xml b/test/fixtures/transpiler/xml/UnknownAttrNamespace.fragment.xml new file mode 100644 index 000000000..585ec4223 --- /dev/null +++ b/test/fixtures/transpiler/xml/UnknownAttrNamespace.fragment.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/test/fixtures/transpiler/xml/_XMLFragmentEmbeddedNoNamespace.fragment.xml b/test/fixtures/transpiler/xml/_XMLFragmentEmbeddedNoNamespace.fragment.xml new file mode 100644 index 000000000..4b8a13080 --- /dev/null +++ b/test/fixtures/transpiler/xml/_XMLFragmentEmbeddedNoNamespace.fragment.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/test/lib/cli.ts b/test/lib/cli.ts new file mode 100644 index 000000000..9dbc370d8 --- /dev/null +++ b/test/lib/cli.ts @@ -0,0 +1,121 @@ +import anyTest, { TestFn } from "ava"; +import sinon, { SinonStub } from "sinon"; +import yargs from "yargs"; +import esmock, { MockFunction } from "esmock"; +import {fileURLToPath} from "node:url"; +import {readFileSync} from "node:fs"; + +const test = anyTest as TestFn<{ + argvGetter: SinonStub, + yargsInstance: yargs.Argv & { + parserConfiguration: SinonStub, + version: SinonStub, + scriptName: SinonStub, + command: SinonStub, + terminalWidth: SinonStub, + wrap: SinonStub, + argv: () => unknown + }, + yargs: SinonStub, + setVersion: SinonStub, + cliBase: SinonStub, + readdir: SinonStub, + cli: MockFunction +}>; + +const pkgJsonPath = new URL("../../package.json", import.meta.url); +const pkg = JSON.parse(readFileSync(pkgJsonPath)); + +test.beforeEach(async (t) => { + t.context.argvGetter = sinon.stub(); + t.context.yargsInstance = { + parserConfiguration: sinon.stub(), + version: sinon.stub(), + scriptName: sinon.stub(), + command: sinon.stub(), + terminalWidth: sinon.stub().returns(123), + wrap: sinon.stub(), + get argv() { + t.context.argvGetter(); + return undefined; + } + }; + + t.context.yargs = sinon.stub().returns(t.context.yargsInstance).named("yargs"); + + t.context.setVersion = sinon.stub().named("setVersion"); + t.context.cliBase = sinon.stub().named("cliBase"); + + t.context.cli = await esmock.p("../../src/cli.js", { + "yargs": t.context.yargs, + "../../src/cli/version.js": { + setVersion: t.context.setVersion + }, + "../../src/cli/base.js": t.context.cliBase, + "module": { + createRequire: sinon.stub().callsFake(() => sinon.stub().returns(pkg)) + }, + }); +}); + +test.afterEach.always((t) => { + sinon.restore(); + esmock.purge(t.context.cli); + // process.env.NODE_ENV = t.context.originalNodeEnv; +}); + +test.serial("CLI", async (t) => { + const { + cli, argvGetter, yargsInstance, yargs, + setVersion, cliBase + } = t.context; + + await cli(); + + t.is(yargs.callCount, 1); + t.deepEqual(yargs.getCall(0).args, [[]]); + + t.is(yargsInstance.parserConfiguration.callCount, 1); + t.deepEqual(yargsInstance.parserConfiguration.getCall(0).args, [{ + "parse-numbers": false + }]); + + t.is(setVersion.callCount, 1); + t.deepEqual(setVersion.getCall(0).args, [ + `${pkg.version} (from ${fileURLToPath(new URL("../../bin/ui5lint.js", import.meta.url))})` + ]); + + t.is(yargsInstance.version.callCount, 1); + t.deepEqual(yargsInstance.version.getCall(0).args, [ + `${pkg.version} (from ${fileURLToPath(new URL("../../bin/ui5lint.js", import.meta.url))})` + ]); + + t.is(yargsInstance.scriptName.callCount, 1); + t.deepEqual(yargsInstance.scriptName.getCall(0).args, ["ui5lint"]); + + t.is(cliBase.callCount, 1); + t.deepEqual(cliBase.getCall(0).args, [yargsInstance]); + + t.is(yargsInstance.command.callCount, 0); + + t.is(yargsInstance.terminalWidth.callCount, 1); + t.deepEqual(yargsInstance.terminalWidth.getCall(0).args, []); + + t.is(yargsInstance.wrap.callCount, 1); + t.deepEqual(yargsInstance.wrap.getCall(0).args, [123]); + + t.is(argvGetter.callCount, 1); + t.deepEqual(argvGetter.getCall(0).args, []); + + sinon.assert.callOrder( + yargs, + yargsInstance.parserConfiguration, + setVersion, + yargsInstance.version, + yargsInstance.scriptName, + cliBase, + yargsInstance.terminalWidth, + yargsInstance.wrap, + argvGetter + ); +}); \ No newline at end of file diff --git a/test/lib/cli/base.integration.ts b/test/lib/cli/base.integration.ts new file mode 100644 index 000000000..ef1941302 --- /dev/null +++ b/test/lib/cli/base.integration.ts @@ -0,0 +1,47 @@ +import anyTest, { TestFn } from "ava"; +import sinon, { SinonStub } from "sinon"; +import yargs from "yargs"; +import path from "node:path"; +import cliBase from "../../../src/cli/base.js"; +import { fileURLToPath } from "node:url"; +import { LintResult } from "../../../src/detectors/AbstractDetector.js"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const sampleProjectPath = path.join(__dirname, "..", "..", "fixtures", "linter", "projects", "com.ui5.troublesome.app"); + +const test = anyTest as TestFn<{ + consoleLogStub: SinonStub, + processCwdStub: SinonStub, + processStdoutWriteStub: SinonStub, + cli: yargs.Argv, +}>; + +test.beforeEach(async (t) => { + t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.processCwdStub = sinon.stub(process, "cwd").returns(sampleProjectPath); + t.context.processStdoutWriteStub = sinon.stub(process.stdout, "write").returns(true); + t.context.cli = yargs(); + cliBase(t.context.cli); +}); + +test.afterEach.always(() => { + sinon.restore(); +}); + +// Test if standard output is parsable JSON +test.serial("ui5lint --format json", async (t) => { + const { cli } = t.context; + + await cli.parseAsync(["--format", "json"]); + + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); + t.true(t.context.processCwdStub.callCount > 0, "process.cwd was called"); + t.is(t.context.processStdoutWriteStub.callCount, 1, "process.stdout.write is only used once"); + + const resultProcessStdout = t.context.processStdoutWriteStub.firstCall.firstArg; + let parsedJson: LintResult[]; + + t.notThrows(() => parsedJson = JSON.parse(resultProcessStdout), "Output of process.stdout.write is JSON-formatted"); + t.true(Array.isArray(parsedJson!), "The parsed JSON output is a LintResult array"); + t.true(parsedJson!.length > 0, "The parsed JSON output contains at least one result"); +}); diff --git a/test/lib/cli/base.ts b/test/lib/cli/base.ts new file mode 100644 index 000000000..294e1c5e1 --- /dev/null +++ b/test/lib/cli/base.ts @@ -0,0 +1,368 @@ +import anyTest, { TestFn } from "ava"; +import sinon, { SinonStub } from "sinon"; +import esmock from "esmock"; +import chalk from "chalk"; +import yargs from "yargs"; +import path from "node:path"; +import type { LintResult } from "../../../src/detectors/AbstractDetector.js"; +import type Base from "../../../src/cli/base.js"; + +const test = anyTest as TestFn<{ + lintProject: SinonStub, + writeFile: SinonStub, + consoleLogStub: SinonStub, + processStdErrWriteStub: SinonStub, + isLogLevelEnabledStub: SinonStub, + consoleWriterStopStub: SinonStub, + processErrWrite: SinonStub, + formatText: SinonStub, + formatJson: SinonStub, + cli: yargs.Argv, + base: typeof Base +}>; + +test.beforeEach(async (t) => { + const lintResult: LintResult = { + filePath: "", + messages: [], + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + warningCount: 0, + }; + + t.context.consoleLogStub = sinon.stub(console, "log"); + t.context.processStdErrWriteStub = sinon.stub(process.stderr, "write").returns(true); + + t.context.isLogLevelEnabledStub = sinon.stub(); + t.context.isLogLevelEnabledStub.withArgs("error").returns(true); + t.context.isLogLevelEnabledStub.withArgs("verbose").returns(false); + t.context.consoleWriterStopStub = sinon.stub(); + + t.context.lintProject = sinon.stub().resolves([lintResult]); + t.context.writeFile = sinon.stub().resolves(); + t.context.cli = yargs(); + + t.context.formatText = sinon.stub().returns(""); + t.context.formatJson = sinon.stub().returns(""); + + t.context.base = await esmock.p("../../../src/cli/base.js", { + "../../../src/linter/linter.js": { + lintProject: t.context.lintProject + }, + "../../../src/formatter/coverage.js": { + Coverage: sinon.stub().callsFake(() => { + return { format: sinon.stub().returns(null) }; + }) + }, + "../../../src/formatter/text.js": { + Text: sinon.stub().callsFake(() => { + return { format: t.context.formatText }; + }) + }, + "../../../src/formatter/json.js": { + Json: sinon.stub().callsFake(() => { + return { format: t.context.formatJson }; + }) + }, + "node:fs/promises": { + writeFile: t.context.writeFile + }, + "@ui5/logger": { + isLogLevelEnabled: t.context.isLogLevelEnabledStub + }, + "@ui5/logger/writers/Console": { + stop: t.context.consoleWriterStopStub + } + }); + + t.context.base(t.context.cli); +}); + +test.afterEach.always((t) => { + esmock.purge(t.context.base); + sinon.restore(); +}); + +test.serial("ui5lint (default) ", async (t) => { + const { cli, lintProject, writeFile } = t.context; + + await cli.parseAsync([]); + + t.true(lintProject.calledOnce, "Linter is called"); + t.is(writeFile.callCount, 0, "Coverage was not called"); + t.deepEqual(lintProject.getCall(0).args[0], { rootDir: path.join(process.cwd()), filePaths: undefined }); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("ui5lint --file-paths ", async (t) => { + const { cli, lintProject } = t.context; + const filePaths = [ + path.resolve(process.cwd(), "path/to/resource"), + path.resolve(process.cwd(), "another/path/to/resource") + ]; + + await cli.parseAsync(["--file-paths", filePaths[0], "--file-paths", filePaths[1]]); + + t.true(lintProject.calledOnce, "Linter is called"); + t.deepEqual(lintProject.getCall(0).args[0], { rootDir: path.join(process.cwd()), filePaths }); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("ui5lint --coverage ", async (t) => { + const { cli, lintProject, writeFile } = t.context; + + await cli.parseAsync(["--coverage"]); + + t.true(lintProject.calledOnce, "Linter is called"); + t.is(writeFile.callCount, 1, "Coverage was called"); + t.deepEqual(lintProject.getCall(0).args[0], { rootDir: path.join(process.cwd()), filePaths: undefined }); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("ui5lint --details ", async (t) => { + const { cli, lintProject, formatText } = t.context; + + await cli.parseAsync(["--details"]); + + t.true(lintProject.calledOnce, "Linter is called"); + t.true(formatText.getCall(0).args[1], "linter is called with 'details=true' flag"); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("ui5lint --format json ", async (t) => { + const { cli, lintProject, formatJson } = t.context; + + await cli.parseAsync(["--format", "json"]); + + t.true(lintProject.calledOnce, "Linter is called"); + t.true(formatJson.calledOnce, "JSON formatter has been called"); +}); + +test.serial("Yargs error handling", async (t) => { + const {processStdErrWriteStub, consoleWriterStopStub, cli} = t.context; + + const processExit = new Promise((resolve) => { + const processExitStub = sinon.stub(process, "exit"); + // @ts-expect-error callsFake definition returns never, instead of void which is not that correct. + processExitStub.callsFake((errorCode) => { + processExitStub.restore(); + resolve(errorCode); + }); + }); + + cli.command({ + command: "foo", + describe: "This is a task", + handler: async function() {} + }); + + await cli.parseAsync(["invalid"]); + + const errorCode = await processExit; + + t.is(errorCode, 1, "Should exit with error code 1"); + t.is(consoleWriterStopStub.callCount, 0, "ConsoleWriter.stop did not get called"); + t.is(processStdErrWriteStub.callCount, 5); + t.deepEqual(processStdErrWriteStub.getCall(0).args, [ + chalk.bold.yellow("Command Failed:") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(1).args, ["Unknown argument: invalid\n"], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(2).args, ["\n"], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(3).args, [ + chalk.dim(`See 'ui5lint --help'`) + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(4).args, [""], + "Note: This is a call from handleLint as yargs doesn't really stop when process.exit is stubbed. " + + "The command handler is still executed in this case."); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("Exception error handling", async (t) => { + const {cli, processStdErrWriteStub, consoleWriterStopStub} = t.context; + + const processExit = new Promise((resolve) => { + const processExitStub = sinon.stub(process, "exit"); + // @ts-expect-error callsFake definition returns never, instead of void which is not that correct. + processExitStub.callsFake((errorCode) => { + processExitStub.restore(); + resolve(errorCode); + }); + }); + + const error = new Error("Some error from foo command"); + + cli.command({ + command: "foo", + describe: "This task fails with an error", + handler: async function() { + throw error; + } + }); + + await t.throwsAsync(cli.parseAsync(["foo"]), { + is: error + }); + + const errorCode = await processExit; + + t.is(errorCode, 1, "Should exit with error code 1"); + t.is(consoleWriterStopStub.callCount, 1, "ConsoleWriter.stop got called once"); + t.is(processStdErrWriteStub.callCount, 7); + t.deepEqual(processStdErrWriteStub.getCall(1).args, [ + chalk.bold.red("⚠️ Process Failed With Error") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(3).args, [ + chalk.underline("Error Message:") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(4).args, + ["Some error from foo command\n"], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(6).args, [chalk.dim( + `For details, execute the same command again with an additional '--verbose' parameter`) + + "\n" + ], "Correct error log"); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("Exception error handling without logging (silent)", async (t) => { + const {cli, processStdErrWriteStub, isLogLevelEnabledStub, consoleWriterStopStub} = t.context; + + isLogLevelEnabledStub.withArgs("error").returns(false); + + const processExit = new Promise((resolve) => { + const processExitStub = sinon.stub(process, "exit"); + // @ts-expect-error callsFake definition returns never, instead of void which is not that correct. + processExitStub.callsFake((errorCode) => { + processExitStub.restore(); + resolve(errorCode); + }); + }); + + const error = new Error("Some error from foo command"); + + cli.command({ + command: "foo", + describe: "This task fails with an error", + handler: async function() { + throw error; + } + }); + + await t.throwsAsync(cli.parseAsync(["foo"]), { + is: error + }); + + const errorCode = await processExit; + + t.is(errorCode, 1, "Should exit with error code 1"); + t.is(consoleWriterStopStub.callCount, 1, "ConsoleWriter.stop got called once"); + t.is(processStdErrWriteStub.callCount, 0); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("Exception error handling with verbose logging", async (t) => { + const {cli, processStdErrWriteStub, isLogLevelEnabledStub} = t.context; + + isLogLevelEnabledStub.withArgs("verbose").returns(true); + + const processExit = new Promise((resolve) => { + const processExitStub = sinon.stub(process, "exit"); + // @ts-expect-error callsFake definition returns never, instead of void which is not that correct. + processExitStub.callsFake((errorCode) => { + processExitStub.restore(); + resolve(errorCode); + }); + }); + + const error = new Error("Some error from foo command"); + + cli.command({ + command: "foo", + describe: "This task fails with an error", + handler: async function() { + throw error; + } + }); + + await t.throwsAsync(cli.parseAsync(["foo"]), { + is: error + }); + + const errorCode = await processExit; + + t.is(errorCode, 1, "Should exit with error code 1"); + t.is(processStdErrWriteStub.callCount, 10); + t.deepEqual(processStdErrWriteStub.getCall(1).args, [ + chalk.bold.red("⚠️ Process Failed With Error") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(3).args, [ + chalk.underline("Error Message:") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(4).args, + ["Some error from foo command\n"], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(6).args, [chalk.underline("Stack Trace:") + "\n"], "Correct error log"); + t.is(processStdErrWriteStub.getCall(7).args.length, 1); + t.true(processStdErrWriteStub.getCall(7).args[0] + .startsWith("Error: Some error from foo command"), "Correct error log"); + + t.deepEqual(processStdErrWriteStub.getCall(processStdErrWriteStub.callCount - 1).args, + [chalk.dim( + `If you think this is an issue of the ui5-linter, you might report it using the ` + + `following URL: `) + + chalk.dim.bold.underline(`https://github.com/SAP/ui5-linter/issues/new/choose`) + "\n"], + "Correct last log line"); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); + +test.serial("Unexpected error handling", async (t) => { + const {processStdErrWriteStub, consoleWriterStopStub, cli} = t.context; + + const processExit = new Promise((resolve) => { + const processExitStub = sinon.stub(process, "exit"); + // @ts-expect-error callsFake definition returns never, instead of void which is not that correct. + processExitStub.callsFake((errorCode) => { + processExitStub.restore(); + resolve(errorCode); + }); + }); + + const typeError = new TypeError("Cannot do this"); + + cli.command({ + command: "foo", + describe: "This task fails with a TypeError", + handler: async function() { + throw typeError; + } + }); + + await t.throwsAsync(cli.parseAsync(["foo"]), { + is: typeError + }); + + const errorCode = await processExit; + + t.is(errorCode, 1, "Should exit with error code 1"); + t.is(consoleWriterStopStub.callCount, 1, "ConsoleWriter.stop got called once"); + t.is(processStdErrWriteStub.callCount, 10); + t.deepEqual(processStdErrWriteStub.getCall(1).args, [ + chalk.bold.red("⚠️ Process Failed With Error") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(3).args, [ + chalk.underline("Error Message:") + "\n" + ], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(4).args, + ["Cannot do this\n"], "Correct error log"); + t.deepEqual(processStdErrWriteStub.getCall(6).args, [chalk.underline("Stack Trace:") + "\n"], "Correct error log"); + t.is(processStdErrWriteStub.getCall(7).args.length, 1); + t.true(processStdErrWriteStub.getCall(7).args[0] + .startsWith("TypeError: Cannot do this"), "Correct error log"); + + t.deepEqual(processStdErrWriteStub.getCall(processStdErrWriteStub.callCount - 1).args, + [chalk.dim( + `If you think this is an issue of the ui5-linter, you might report it using the ` + + `following URL: `) + + chalk.dim.bold.underline(`https://github.com/SAP/ui5-linter/issues/new/choose`) + "\n"], + "Correct last log line"); + t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used"); +}); diff --git a/test/lib/cli/middlewares/base.ts b/test/lib/cli/middlewares/base.ts new file mode 100644 index 000000000..cd371d3cb --- /dev/null +++ b/test/lib/cli/middlewares/base.ts @@ -0,0 +1,27 @@ +import anyTest, {TestFn} from "ava"; +import sinon, { SinonStub } from "sinon"; +import esmock from "esmock"; + +const test = anyTest as TestFn<{ + initLogger: SinonStub, + baseMiddleware: (args: { loglevel: number }) => void +}>; + +test.beforeEach(async (t) => { + t.context.initLogger = sinon.stub(); + t.context.baseMiddleware = await esmock("../../../../src/cli/middlewares/base.js", { + "../../../../src/cli/middlewares/logger.js": { + initLogger: t.context.initLogger + } + }); +}); + +test.afterEach("Stubs Cleanup", () => { + sinon.restore(); +}); + +test.serial("uses default middleware", (t) => { + const {baseMiddleware, initLogger} = t.context; + baseMiddleware({loglevel: 1}); + t.is(initLogger.called, true, "Logger middleware initialized"); +}); diff --git a/test/lib/cli/middlewares/logger.ts b/test/lib/cli/middlewares/logger.ts new file mode 100644 index 000000000..03b4310bb --- /dev/null +++ b/test/lib/cli/middlewares/logger.ts @@ -0,0 +1,100 @@ +import anyTest, { TestFn } from "ava"; +import sinon, {SinonStub} from "sinon"; +import esmock, { MockFunction } from "esmock"; + +const test = anyTest as TestFn<{ + verboseLogStub: SinonStub, + setLogLevelStub: SinonStub, + isLogLevelEnabledStub: SinonStub, + getVersionStub: SinonStub, + logger: MockFunction & { + initLogger: (args: + { loglevel?: string, verbose?: boolean, perf?: boolean, silent?: boolean }) => Promise | void + } +}>; + +test.beforeEach(async (t) => { + t.context.verboseLogStub = sinon.stub(); + t.context.setLogLevelStub = sinon.stub(); + t.context.isLogLevelEnabledStub = sinon.stub().returns(true); + t.context.getVersionStub = sinon.stub().returns("1.0.0"); + t.context.logger = await esmock("../../../../src/cli/middlewares/logger.js", { + "../../../../src/cli/version.js": { + getVersion: t.context.getVersionStub + }, + "@ui5/logger": { + getLogger: () => ({ + verbose: t.context.verboseLogStub, + }), + setLogLevel: t.context.setLogLevelStub, + isLogLevelEnabled: t.context.isLogLevelEnabledStub, + } + }); +}); + +test.serial("init logger", async (t) => { + const { logger, setLogLevelStub, isLogLevelEnabledStub, verboseLogStub, getVersionStub } = t.context; + await logger.initLogger({}); + t.is(setLogLevelStub.callCount, 0, "setLevel has not been called"); + t.is(isLogLevelEnabledStub.callCount, 1, "isLogLevelEnabled has been called once"); + t.is(isLogLevelEnabledStub.firstCall.firstArg, "verbose", + "isLogLevelEnabled has been called with expected argument"); + t.is(getVersionStub.callCount, 1, "getVersion has been called once"); + t.is(verboseLogStub.callCount, 2, "log.verbose has been called twice"); + t.is(verboseLogStub.firstCall.firstArg, "using ui5lint version 1.0.0", + "log.verbose has been called with expected argument on first call"); + t.is(verboseLogStub.secondCall.firstArg, `using node version ${process.version}`, + "log.verbose has been called with expected argument on second call"); +}); + +test.serial("With log-level flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ loglevel: "silly" }); + t.is(setLogLevelStub.callCount, 1, "setLevel has been called once"); + t.is(setLogLevelStub.getCall(0).args[0], "silly", "sets log level to silly"); +}); + +test.serial("With default log-level flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ loglevel: "info" }); + t.is(setLogLevelStub.callCount, 0, "setLevel has not been called"); +}); + +test.serial("With verbose flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ verbose: true }); + t.is(setLogLevelStub.callCount, 1, "setLevel has been called once"); + t.is(setLogLevelStub.getCall(0).args[0], "verbose", "sets log level to verbose"); +}); + +test.serial("With perf flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ perf: true }); + t.is(setLogLevelStub.callCount, 1, "setLevel has been called once"); + t.is(setLogLevelStub.getCall(0).args[0], "perf", "sets log level to perf"); +}); + +test.serial("With silent flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ silent: true }); + t.is(setLogLevelStub.callCount, 1, "setLevel has been called once"); + t.is(setLogLevelStub.getCall(0).args[0], "silent", "sets log level to silent"); +}); + +test.serial("With log-level and verbose flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ loglevel: "silly", verbose: true }); + t.is(setLogLevelStub.callCount, 2, "setLevel has been called twice"); + t.is(setLogLevelStub.getCall(0).args[0], "verbose", "sets log level to verbose"); + t.is(setLogLevelStub.getCall(1).args[0], "silly", "sets log level to verbose"); +}); + +test.serial("With log-level, verbose, perf and silent flag", async (t) => { + const { logger, setLogLevelStub } = t.context; + await logger.initLogger({ loglevel: "silly", verbose: true, perf: true, silent: true }); + t.is(setLogLevelStub.callCount, 4, "setLevel has been called four times"); + t.is(setLogLevelStub.getCall(0).args[0], "silent", "sets log level to silent"); + t.is(setLogLevelStub.getCall(1).args[0], "perf", "sets log level to perf"); + t.is(setLogLevelStub.getCall(2).args[0], "verbose", "Third sets log level to verbose"); + t.is(setLogLevelStub.getCall(3).args[0], "silly", "sets log level to verbose"); +}); diff --git a/test/lib/cli/version.ts b/test/lib/cli/version.ts new file mode 100644 index 000000000..0a5c723cc --- /dev/null +++ b/test/lib/cli/version.ts @@ -0,0 +1,12 @@ +import test from "ava"; +import {setVersion, getVersion} from "../../../src/cli/version.js"; + +test("Set and get version", (t) => { + t.is(getVersion(), ""); + + setVersion("1.2.3"); + t.is(getVersion(), "1.2.3"); + + setVersion("4.5.6-foo.bar"); + t.is(getVersion(), "4.5.6-foo.bar"); +}); diff --git a/test/lib/detectors/transpilers/amd/_helper.ts b/test/lib/detectors/transpilers/amd/_helper.ts new file mode 100644 index 000000000..d60690484 --- /dev/null +++ b/test/lib/detectors/transpilers/amd/_helper.ts @@ -0,0 +1,56 @@ +import anyTest, {TestFn} from "ava"; +import sinonGlobal from "sinon"; +import path from "node:path"; +import util from "util"; +import {readdirSync} from "node:fs"; +import fs from "node:fs/promises"; +import {amdToEsm} from "../../../../../src/detectors/transpilers/amd/transpiler.js"; + +util.inspect.defaultOptions.depth = 4; // Increase AVA's printing depth since coverageInfo objects are on level 4 + +const test = anyTest as TestFn<{ + sinon: sinonGlobal.SinonSandbox, +}>; + +// Helper function to create linting tests for all files in a directory +export function createTestsForFixtures(fixturesPath: string) { + try { + const testFiles = readdirSync(fixturesPath); + if (!testFiles.length) { + throw new Error(`Failed to find any fixtures in directory ${fixturesPath}`); + } + for (const fileName of testFiles) { + if (!fileName.endsWith(".js")) { + // Ignore non-JavaScript files + continue; + } + + let testName = fileName; + let defineTest = test.serial; + if (fileName.startsWith("_")) { + // Skip tests for files starting with underscore + defineTest = defineTest.skip as typeof test; + testName = fileName.slice(1); + } else if (fileName.startsWith("only_")) { + // Only run test when file starts with only_ + defineTest = defineTest.only as typeof test; + testName = fileName.slice(5); + } + // Executing linting in parallel might lead to OOM errors in the CI + // Therefore always use serial + defineTest(`Transpile ${testName}`, async (t) => { + const filePath = path.join(fixturesPath, fileName); + const fileContent = await fs.readFile(filePath); + const {source, map} = amdToEsm(testName, fileContent.toString(), true); + t.snapshot(source); + t.snapshot(map && JSON.parse(map)); + }); + } + } catch (err) { + if (err instanceof Error) { + throw new Error( + `Failed to list files of directory ${fixturesPath}: ${err.message}`); + } + throw err; + } +} diff --git a/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts b/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts new file mode 100644 index 000000000..89d0794a5 --- /dev/null +++ b/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts @@ -0,0 +1,220 @@ +import anyTest, {TestFn} from "ava"; +import ts from "typescript"; +import {ModuleDeclaration, DefineCallArgument, _matchArgumentsToParameters} from + "../../../../../src/detectors/transpilers/amd/parseModuleDeclaration.js"; +const {SyntaxKind} = ts; + +const test = anyTest as TestFn; + +test("All parameters provided directly", async (t) => { + const args = [{ + kind: SyntaxKind.StringLiteral + }, { + kind: SyntaxKind.ArrayLiteralExpression + }, { + kind: SyntaxKind.FunctionExpression + }, { + kind: SyntaxKind.TrueKeyword + }] as DefineCallArgument[]; + + t.deepEqual(_matchArgumentsToParameters(args), { + dependencies: { + kind: SyntaxKind.ArrayLiteralExpression, + }, + export: { + kind: SyntaxKind.TrueKeyword, + }, + factory: { + kind: SyntaxKind.FunctionExpression, + }, + moduleName: { + kind: SyntaxKind.StringLiteral, + }, + }, "Matched parameters correctly"); +}); + +test("Factory provided", async (t) => { + const args = [{ + kind: SyntaxKind.FunctionExpression + }] as DefineCallArgument[]; + + + t.deepEqual(_matchArgumentsToParameters(args), { + factory: { + kind: SyntaxKind.FunctionExpression, + }, + }, "Matched parameters correctly"); +}); + +test("Dependencies and Factory provided", async (t) => { + const args = [{ + kind: SyntaxKind.ArrayLiteralExpression + }, { + kind: SyntaxKind.FunctionExpression + }] as DefineCallArgument[]; + + + t.deepEqual(_matchArgumentsToParameters(args), { + dependencies: { + kind: SyntaxKind.ArrayLiteralExpression, + }, + factory: { + kind: SyntaxKind.FunctionExpression, + }, + }, "Matched parameters correctly"); +}); + +test("Module Name, Dependencies and Factory provided", async (t) => { + const args = [{ + kind: SyntaxKind.StringLiteral + }, { + kind: SyntaxKind.ArrayLiteralExpression + }, { + kind: SyntaxKind.FunctionExpression + }] as DefineCallArgument[]; + + + t.deepEqual(_matchArgumentsToParameters(args), { + moduleName: { + kind: SyntaxKind.StringLiteral, + }, + dependencies: { + kind: SyntaxKind.ArrayLiteralExpression, + }, + factory: { + kind: SyntaxKind.FunctionExpression, + }, + }, "Matched parameters correctly"); +}); + +test("Dependencies, Factory and Export provided", async (t) => { + const args = [{ + kind: SyntaxKind.ArrayLiteralExpression + }, { + kind: SyntaxKind.FunctionExpression + }, { + kind: SyntaxKind.TrueKeyword + }] as DefineCallArgument[]; + + t.deepEqual(_matchArgumentsToParameters(args), { + dependencies: { + kind: SyntaxKind.ArrayLiteralExpression, + }, + factory: { + kind: SyntaxKind.FunctionExpression, + }, + export: { + kind: SyntaxKind.TrueKeyword, + }, + }, "Matched parameters correctly"); +}); + +interface TestArguments { + args: DefineCallArgument[], + expected: ModuleDeclaration, +} +function generateArguments(possibleParameterTypes) { + const permutations: Array = []; + for (const moduleNameKind of possibleParameterTypes.moduleName) { + for (const dependenciesKind of possibleParameterTypes.dependencies) { + for (const factoryKind of possibleParameterTypes.factory) { + for (const exportKind of possibleParameterTypes.export) { + const moduleName = { + kind: moduleNameKind, + } as ModuleDeclaration["moduleName"]; + const dependencies = { + kind: dependenciesKind, + } as ModuleDeclaration["dependencies"]; + const factory = { + kind: factoryKind, + } as ModuleDeclaration["factory"]; + const exp = { + kind: exportKind, + } as ModuleDeclaration["export"]; + + // Adapt expectation based on which parameters are omitted and which ones are required + const expected: Partial = {}; + if (moduleNameKind) { + expected.moduleName = moduleName; + } else if (!dependenciesKind && factoryKind === SyntaxKind.StringLiteral) { + // If dependencies are omitted and factory is a string, it's the module name + // (given that there's a parameter that can be used for the factory) + expected.moduleName = factory as ModuleDeclaration["moduleName"]; + } + + if (dependenciesKind && expected.moduleName !== dependencies) { + expected.dependencies = dependencies; + } else if (factoryKind === SyntaxKind.ArrayLiteralExpression) { + expected.dependencies = factory as ModuleDeclaration["dependencies"]; + } + + + if (factoryKind && expected.dependencies !== factory && expected.moduleName !== factory) { + expected.factory = factory; + } else if (exportKind) { + expected.factory = exp; + } + + if (exportKind && expected.factory !== exp) { + expected.export = exp; + } + const args = [moduleName, dependencies, factory, exp] as DefineCallArgument[]; + permutations.push({ + args, + expected: expected as ModuleDeclaration + }); + } + } + } + } + return permutations; +} + +function resolveSyntaxKind(decl: ModuleDeclaration) { + const res = Object.create(null); + for (const key in decl) { + if (decl[key]?.kind) { + res[key] = ts.SyntaxKind[decl[key].kind]; + } + } + return res; +} + +function argsToString(args: DefineCallArgument[]): string { + return args.map(param => { + if (!param?.kind) { + return ""; + } + return SyntaxKind[param.kind]; + }).join(", "); +} + +function declToString(decl: ModuleDeclaration): string { + const args = [decl.moduleName, decl.dependencies, decl.factory, decl.export] as DefineCallArgument[]; + return argsToString(args); +} + +test("All combinations", async (t) => { + const permutations = generateArguments({ + moduleName: [SyntaxKind.StringLiteral, null /*implies omitted*/], + dependencies: [SyntaxKind.ArrayLiteralExpression, null /*implies omitted*/], + factory: [ + SyntaxKind.FunctionExpression, SyntaxKind.ArrowFunction, + SyntaxKind.StringLiteral, SyntaxKind.ArrayLiteralExpression, + SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword + ], + export: [SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, null /*implies omitted*/], + }); + + t.true(permutations.length > 0, `Generated ${permutations.length} permutations`); + permutations.forEach(({args, expected}) => { + // Omit any parameters with "kind" set to null + const res = _matchArgumentsToParameters(args.filter(_ => _?.kind)); + t.deepEqual( + resolveSyntaxKind(res), + resolveSyntaxKind(expected), + `Permutation: [${argsToString(args)}]` + + `\nExpected: [${declToString(expected)}] ` + + `\nResult: [${declToString(res)}]`); + }); +}); diff --git a/test/lib/detectors/transpilers/amd/snapshots/transpiler.ts.md b/test/lib/detectors/transpilers/amd/snapshots/transpiler.ts.md new file mode 100644 index 000000000..aa8e0f884 --- /dev/null +++ b/test/lib/detectors/transpilers/amd/snapshots/transpiler.ts.md @@ -0,0 +1,1650 @@ +# Snapshot report for `test/lib/detectors/transpilers/amd/transpiler.ts` + +The actual snapshot is saved in `transpiler.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## Transpile Dependencies.js + +> Snapshot 1 + + `import UIComponent from "sap/ui/core/UIComponent";␊ + import Device from "sap/ui/Device";␊ + export default class Component extends UIComponent {␊ + }␊ + //# sourceMappingURL=Dependencies.ts.map` + +> Snapshot 2 + + { + file: 'Dependencies.js', + mappings: 'OAAsE,WAAW,MAAlE,yBAAyB;OAA2C,MAAM,MAA/C;uCAGlC,WAAW', + names: [], + sourceRoot: '', + sources: [ + 'Dependencies.js', + ], + version: 3, + } + +## Transpile Dependencies_Dynamic.js + +> Snapshot 1 + + `import delta from "delta";␊ + var dependency = new Date().getTime() % 2 === 0 ? "alpha" : "beta";␊ + export default {␊ + verb: function () {␊ + return alphaOrBeta.verb() + 2 + delta();␊ + }␊ + };␊ + //# sourceMappingURL=Dependencies_Dynamic.ts.map` + +> Snapshot 2 + + { + file: 'Dependencies_Dynamic.js', + mappings: 'OAC4D,KAAK,MAAtC,OAAO;AADlC,IAAI,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;eAE1D;IACL,IAAI,EAAE;QACJ,OAAO,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC;IAC1C,CAAC;CACF', + names: [], + sourceRoot: '', + sources: [ + 'Dependencies_Dynamic.js', + ], + version: 3, + } + +## Transpile Dependencies_LocalImport.js + +> Snapshot 1 + + `import UIComponent from "sap/ui/core/UIComponent";␊ + import Device from "sap/ui/Device";␊ + import models from "./model/models";␊ + export default class Component extends UIComponent {␊ + }␊ + //# sourceMappingURL=Dependencies_LocalImport.ts.map` + +> Snapshot 2 + + { + file: 'Dependencies_LocalImport.js', + mappings: 'OAAwF,WAAW,MAApF,yBAAyB;OAA6D,MAAM,MAAjE,eAAe;OAAoD,MAAM,MAAxD,gBAAgB;uCAGnE,WAAW', + names: [], + sourceRoot: '', + sources: [ + 'Dependencies_LocalImport.js', + ], + version: 3, + } + +## Transpile Dependencies_NotProvided_Export_Object.js + +> Snapshot 1 + + `export default {␊ + add: function (x, y) {␊ + return x + y;␊ + }␊ + };␊ + //# sourceMappingURL=Dependencies_NotProvided_Export_Object.ts.map` + +> Snapshot 2 + + { + file: 'Dependencies_NotProvided_Export_Object.js', + mappings: 'eAAc;IACb,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;CACD', + names: [], + sourceRoot: '', + sources: [ + 'Dependencies_NotProvided_Export_Object.js', + ], + version: 3, + } + +## Transpile Dependencies_Var.js + +> Snapshot 1 + + `import UIComponent from "sap/ui/core/UIComponent";␊ + import Device from "sap/ui/Device";␊ + import models from "./model/models";␊ + export default class Component extends UIComponent {␊ + }␊ + //# sourceMappingURL=Dependencies_Var.ts.map` + +> Snapshot 2 + + { + file: 'Dependencies_Var.js', + mappings: 'OAC8B,WAAW,MAD3B,yBAAyB;OACI,MAAM,MADR,eAAe;OACL,MAAM,MADC,gBAAgB;uCAIlE,WAAW', + names: [], + sourceRoot: '', + sources: [ + 'Dependencies_Var.js', + ], + version: 3, + } + +## Transpile ExportFlag.js + +> Snapshot 1 + + `import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";␊ + export default class ReuseExtension extends ControllerExtension {␊ + }␊ + //# sourceMappingURL=ExportFlag.ts.map` + +> Snapshot 2 + + { + file: 'ExportFlag.js', + mappings: 'OAAgE,mBAAmB,MAApE,qCAAqC;4CAC5C,mBAAmB', + names: [], + sourceRoot: '', + sources: [ + 'ExportFlag.js', + ], + version: 3, + } + +## Transpile Export_Object.js + +> Snapshot 1 + + `import JSONModel from "sap/ui/model/json/JSONModel";␊ + import BindingMode from "sap/ui/model/BindingMode";␊ + import Device from "sap/ui/Device";␊ + export default {␊ + createDeviceModel: function () {␊ + var oModel = new JSONModel(Device);␊ + oModel.setDefaultBindingMode(BindingMode.OneWay);␊ + return oModel;␊ + }␊ + };␊ + //# sourceMappingURL=Export_Object.ts.map` + +> Snapshot 2 + + { + file: 'Export_Object.js', + mappings: 'OAAsG,SAAS,MAAhG,6BAA6B;OAAqE,WAAW,MAA9E,0BAA0B;OAAsD,MAAM,MAA1D,eAAe;eAGjF;IACN,iBAAiB,EAAE;QAClB,IAAI,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,CAAC,qBAAqB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC;IACf,CAAC;CACD', + names: [], + sourceRoot: '', + sources: [ + 'Export_Object.js', + ], + version: 3, + } + +## Transpile Factory_ArrowFunction.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_ArrowFunction.ts.map` + +> Snapshot 2 + + { + file: 'Factory_ArrowFunction.js', + mappings: 'OAAiB,UAAU,MAMzB,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAPvB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_ArrowFunction.js', + ], + version: 3, + } + +## Transpile Factory_ArrowFunctionExpr.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_ArrowFunctionExpr.ts.map` + +> Snapshot 2 + + { + file: 'Factory_ArrowFunctionExpr.js', + mappings: 'OAA+C,UAAU,MAA1C,4BAA4B;0CAAoB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_ArrowFunctionExpr.js', + ], + version: 3, + } + +## Transpile Factory_BasicModule.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import UIComponent from "sap/ui/core/UIComponent";␊ + import History from "sap/ui/core/routing/History";␊ + import Button from "sap/m/Button";␊ + export default class BaseController extends Controller {␊ + createButton() {␊ + var btn = new Button({␊ + blocked: true␊ + });␊ + btn.attachTap(function () {␊ + console.log("Tapped");␊ + });␊ + return btn;␊ + }␊ + }␊ + //# sourceMappingURL=Factory_BasicModule.ts.map` + +> Snapshot 2 + + { + file: 'Factory_BasicModule.js', + mappings: 'OACW,UAAU,MADN,4BAA4B;OACpB,WAAW,MADW,yBAAyB;OAClC,OAAO,MAD6B,6BAA6B;OACxD,MAAM,MADoD,cAAc;4CAI7G,UAAU;IAEhB,YAAY;QACX,IAAI,GAAG,GAAG,IAAI,MAAM,CAAC;YACpB,OAAO,EAAE,IAAI;SACb,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC;IACZ,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Factory_BasicModule.js', + ], + version: 3, + } + +## Transpile Factory_ClassWithoutName.js + +> Snapshot 1 + + `import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";␊ + export default ControllerExtension.extend({});␊ + //# sourceMappingURL=Factory_ClassWithoutName.ts.map` + +> Snapshot 2 + + { + file: 'Factory_ClassWithoutName.js', + mappings: 'OAAgE,mBAAmB,MAApE,qCAAqC;eAC5C,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Factory_ClassWithoutName.js', + ], + version: 3, + } + +## Transpile Factory_Empty.js + +> Snapshot 1 + + '//# sourceMappingURL=Factory_Empty.ts.map' + +> Snapshot 2 + + { + file: 'Factory_Empty.js', + mappings: '', + names: [], + sourceRoot: '', + sources: [ + 'Factory_Empty.js', + ], + version: 3, + } + +## Transpile Factory_Empty_2.js + +> Snapshot 1 + + '//# sourceMappingURL=Factory_Empty_2.ts.map' + +> Snapshot 2 + + { + file: 'Factory_Empty_2.js', + mappings: '', + names: [], + sourceRoot: '', + sources: [ + 'Factory_Empty_2.js', + ], + version: 3, + } + +## Transpile Factory_ExtendCall.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import UIComponent from "sap/ui/core/UIComponent";␊ + import History from "sap/ui/core/routing/History";␊ + import Button from "sap/m/Button";␊ + const someValue1 = "foo";␊ + const someValue2 = new Button();␊ + export default class BaseController extends Controller {␊ + static metadata = {␊ + interfaces: [␊ + library.IAsyncContentCreation␊ + ],␊ + manifest: "json"␊ + };␊ + prop1 = 1;␊ + prop2(value) {␊ + console.log(value);␊ + }␊ + prop3 = (value) => {␊ + console.log(value);␊ + };␊ + prop4 = new Button();␊ + prop5 = History.getInstance();␊ + prop6 = someFunc("foo");␊ + prop7 = require("sap/m/Button");␊ + prop8 = someValue1;␊ + prop9 = \`${someValue1}\`;␊ + prop10 = someValue2;␊ + method1(value) {␊ + console.log(value);␊ + }␊ + }␊ + //# sourceMappingURL=Factory_ExtendCall.ts.map` + +> Snapshot 2 + + { + file: 'Factory_ExtendCall.js', + mappings: 'OACW,UAAU,MADN,4BAA4B;OACpB,WAAW,MADW,yBAAyB;OAClC,OAAO,MAD6B,6BAA6B;OACxD,MAAM,MADoD,cAAc;AAGpH,MAAM,UAAU,GAAG,KAAK,CAAC;AACzB,MAAM,UAAU,GAAG,IAAI,MAAM,EAAE,CAAC;4CACzB,UAAU;WAChB,QAAQ,GAAE;QACA,UAAU,EAAE;YACR,OAAO,CAAC,qBAAqB;SAChC;QACD,QAAQ,EAAE,MAAM;KACzB;IACD,KAAK,GAAE,CAAC;IACR,KAAK,CAAW,KAAK;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,KAAK,GAAE,CAAC,KAAK,EAAE,EAAE;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,KAAK,GAAE,IAAI,MAAM,EAAE;IACnB,KAAK,GAAE,OAAO,CAAC,WAAW,EAAE;IAC5B,KAAK,GAAE,QAAQ,CAAC,KAAK,CAAC;IACtB,KAAK,GAAE,OAAO,CAAC,cAAc,CAAC;IAC9B,KAAK,GAAE,UAAU;IACjB,KAAK,GAAE,GAAG,UAAU,EAAE;IACtB,MAAM,GAAE,UAAU;IAClB,OAAO,CAAC,KAAK;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Factory_ExtendCall.js', + ], + version: 3, + } + +## Transpile Factory_FunctionVarDeclaration.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_FunctionVarDeclaration.ts.map` + +> Snapshot 2 + + { + file: 'Factory_FunctionVarDeclaration.js', + mappings: 'OAA0B,UAAU,MAMlC,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAPvB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_FunctionVarDeclaration.js', + ], + version: 3, + } + +## Transpile Factory_FunctionVarExpression.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_FunctionVarExpression.ts.map` + +> Snapshot 2 + + { + file: 'Factory_FunctionVarExpression.js', + mappings: 'OAAiB,UAAU,MAMzB,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAPvB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_FunctionVarExpression.js', + ], + version: 3, + } + +## Transpile Factory_GlobalVar.js + +> Snapshot 1 + + `import "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default window.MyFactory;␊ + //# sourceMappingURL=Factory_GlobalVar.ts.map` + +> Snapshot 2 + + { + file: 'Factory_GlobalVar.js', + mappings: 'OAEE,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;eAE9B,MAAM,CAAC,SAAS', + names: [], + sourceRoot: '', + sources: [ + 'Factory_GlobalVar.js', + ], + version: 3, + } + +## Transpile Factory_MultipleReturns.js + +> Snapshot 1 + + `import merge from "some/module";␊ + import some_other_module_1 from "some/other/module";␊ + export default (function (merge) {␊ + const otherModule = some_other_module_1;␊ + if (otherModule) {␊ + return otherModule;␊ + }␊ + return merge;␊ + }(merge));␊ + //# sourceMappingURL=Factory_MultipleReturns.ts.map` + +> Snapshot 2 + + { + file: 'Factory_MultipleReturns.js', + mappings: 'OAAyC,KAAK,MAA/B,aAAa;gCACQ,mBAAmB;gBADxB,UAAU,KAAK;IAC7C,MAAM,WAAW,sBAAsC,CAAC;IACxD,IAAI,WAAW,EAAE,CAAC;QACjB,OAAO,WAAW,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CANwC,KAAK', + names: [], + sourceRoot: '', + sources: [ + 'Factory_MultipleReturns.js', + ], + version: 3, + } + +## Transpile Factory_NotProvided_A.js + +> Snapshot 1 + + '//# sourceMappingURL=Factory_NotProvided_A.ts.map' + +> Snapshot 2 + + { + file: 'Factory_NotProvided_A.js', + mappings: '', + names: [], + sourceRoot: '', + sources: [ + 'Factory_NotProvided_A.js', + ], + version: 3, + } + +## Transpile Factory_NotProvided_B.js + +> Snapshot 1 + + `import "sap/ui/core/UIComponent";␊ + //# sourceMappingURL=Factory_NotProvided_B.ts.map` + +> Snapshot 2 + + { + file: 'Factory_NotProvided_B.js', + mappings: 'OAAe,yBAAyB', + names: [], + sourceRoot: '', + sources: [ + 'Factory_NotProvided_B.js', + ], + version: 3, + } + +## Transpile Factory_ReturnCallExp.js + +> Snapshot 1 + + `import merge from "sap/base/util/merge";␊ + export default merge({}, {});␊ + //# sourceMappingURL=Factory_ReturnCallExp.ts.map` + +> Snapshot 2 + + { + file: 'Factory_ReturnCallExp.js', + mappings: 'OAAiD,KAAK,MAAvC,qBAAqB;eAC5B,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Factory_ReturnCallExp.js', + ], + version: 3, + } + +## Transpile Factory_cond_iife.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_cond_iife.ts.map` + +> Snapshot 2 + + { + file: 'Factory_cond_iife.js', + mappings: 'OAWa,UAAU,MAPnB,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAMzB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_cond_iife.js', + ], + version: 3, + } + +## Transpile Factory_cond_iife_2.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_cond_iife_2.ts.map` + +> Snapshot 2 + + { + file: 'Factory_cond_iife_2.js', + mappings: 'OAWa,UAAU,MAPnB,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAMzB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_cond_iife_2.js', + ], + version: 3, + } + +## Transpile Factory_hoisted_function.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_hoisted_function.ts.map` + +> Snapshot 2 + + { + file: 'Factory_hoisted_function.js', + mappings: 'OASiB,UAAU,MAPzB,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAMvB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_hoisted_function.js', + ], + version: 3, + } + +## Transpile Factory_iife.js + +> Snapshot 1 + + `import Controller from "sap/ui/core/mvc/Controller";␊ + import "sap/ui/core/UIComponent";␊ + import "sap/ui/core/routing/History";␊ + export default class MyController extends Controller {␊ + }␊ + //# sourceMappingURL=Factory_iife.ts.map` + +> Snapshot 2 + + { + file: 'Factory_iife.js', + mappings: 'OASa,UAAU,MANpB,4BAA4B;OAC5B,yBAAyB;OACzB,6BAA6B;0CAKxB,UAAU', + names: [], + sourceRoot: '', + sources: [ + 'Factory_iife.js', + ], + version: 3, + } + +## Transpile Factory_jQueryExtend.js + +> Snapshot 1 + + `import jQuery from "sap/ui/thirdparty/jquery";␊ + import base from "./base";␊ + export default jQuery.extend(base, { foo: "bar" });␊ + //# sourceMappingURL=Factory_jQueryExtend.ts.map` + +> Snapshot 2 + + { + file: 'Factory_jQueryExtend.js', + mappings: 'OAAgE,MAAM,MAAvD,0BAA0B;OAA+B,IAAI,MAAjC,QAAQ;eAC3C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Factory_jQueryExtend.js', + ], + version: 3, + } + +## Transpile ModuleName.js + +> Snapshot 1 + + `export default function () {␊ + return "MyModuleContent";␊ + }␊ + //# sourceMappingURL=ModuleName.ts.map` + +> Snapshot 2 + + { + file: 'ModuleName.js', + mappings: ';IAEE,OAAO,iBAAiB,CAAC;AAC1B,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'ModuleName.js', + ], + version: 3, + } + +## Transpile ModuleName_Dynamic.js + +> Snapshot 1 + + `const moduleName = (new Date().getTime() % 2 === 0 ? "My" : "Your") + " Module";␊ + sap.ui.define(moduleName, function () {␊ + return function () {␊ + return "MyModuleContent";␊ + };␊ + });␊ + //# sourceMappingURL=ModuleName_Dynamic.ts.map` + +> Snapshot 2 + + { + file: 'ModuleName_Dynamic.js', + mappings: 'AAAA,MAAM,UAAU,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAChF,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE;IACzB,OAAO;QACN,OAAO,iBAAiB,CAAC;IAC1B,CAAC,CAAC;AACH,CAAC,CAAC,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'ModuleName_Dynamic.js', + ], + version: 3, + } + +## Transpile ModuleName_FactoryArrowFunction.js + +> Snapshot 1 + + `export default function () {␊ + return "MyModuleContent";␊ + }␊ + //# sourceMappingURL=ModuleName_FactoryArrowFunction.ts.map` + +> Snapshot 2 + + { + file: 'ModuleName_FactoryArrowFunction.js', + mappings: ';IAEI,OAAO,iBAAiB,CAAC;AAC3B,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'ModuleName_FactoryArrowFunction.js', + ], + version: 3, + } + +## Transpile Noop_DynamicImport.js + +> Snapshot 1 + + `export default () => {␊ + import('./foo')␊ + .then(() => { console.log('success'); })␊ + .catch(() => { console.log('error'); });␊ + };␊ + //# sourceMappingURL=Noop_DynamicImport.ts.map` + +> Snapshot 2 + + { + file: 'Noop_DynamicImport.js', + mappings: 'AAAA,eAAe,GAAG,EAAE;IAClB,MAAM,CAAC,OAAO,CAAC;SACZ,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA,CAAC,CAAC,CAAC;SACtC,KAAK,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;AAC1C,CAAC,CAAA', + names: [], + sourceRoot: '', + sources: [ + 'Noop_DynamicImport.js', + ], + version: 3, + } + +## Transpile Noop_EmptyDefine.js + +> Snapshot 1 + + '//# sourceMappingURL=Noop_EmptyDefine.ts.map' + +> Snapshot 2 + + { + file: 'Noop_EmptyDefine.js', + mappings: '', + names: [], + sourceRoot: '', + sources: [ + 'Noop_EmptyDefine.js', + ], + version: 3, + } + +## Transpile Noop_NoDefine.js + +> Snapshot 1 + + `// This file contains "sap.ui.define", but no real sap.ui.define call␊ + sap.ui.define;␊ + //# sourceMappingURL=Noop_NoDefine.ts.map` + +> Snapshot 2 + + { + file: 'Noop_NoDefine.js', + mappings: 'AAAA,qEAAqE;AACrE,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Noop_NoDefine.js', + ], + version: 3, + } + +## Transpile Require_AMD.js + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import require from "require";␊ + import exports from "exports";␊ + import module from "module";␊ + import sap_m_NotLoaded_1 from "sap/m/NotLoaded";␊ + new Button({␊ + text: "Hello World",␊ + press() {␊ + console.log(sap_m_NotLoaded_1); // returns undefined␊ + require(["./Input"], (Input) => {␊ + console.log(Input);␊ + console.log(require);␊ + console.log(exports);␊ + console.log(module);␊ + });␊ + console.log(require("./NotLoaded")); // throws an error␊ + }␊ + }).placeAt("content");␊ + //# sourceMappingURL=Require_AMD.ts.map` + +> Snapshot 2 + + { + file: 'Require_AMD.js', + mappings: 'OAA8E,MAAM,MAAxD,cAAc;OAA4C,OAAO,MAAjD,SAAS;OAA0C,OAAO,MAA/C,SAAS;OAAwC,MAAM,MAA5C,QAAQ;8BAI5C,iBAAiB;AAH9C,IAAI,MAAM,CAAC;IACV,IAAI,EAAE,aAAa;IACnB,KAAK;QACJ,OAAO,CAAC,GAAG,mBAAmC,CAAA,CAAC,oBAAoB;QACnE,OAAO,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAA,CAAC,kBAAkB;IACvD,CAAC;CACD,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Require_AMD.js', + ], + version: 3, + } + +## Transpile Require_Callback.js + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + export default {␊ + renderButton() {␊ + var msg = "Tapped";␊ + ((Button) => {␊ + new Button({␊ + tap: () => console.log(msg) // Event "tap" is deprecated␊ + }).placeAt("button");␊ + })(Button);␊ + },␊ + renderInput() {␊ + console.log(\`Not implemented\`);␊ + }␊ + };␊ + //# sourceMappingURL=Require_Callback.ts.map` + +> Snapshot 2 + + { + file: 'Require_Callback.js', + mappings: 'OAIqC,MAAM,MAAxB,cAAc;eAHzB;IACN,YAAY;QACX,IAAI,GAAG,GAAG,QAAQ,CAAC;QACc,CAAA,CAAC,MAAM,EAAE,EAAE;YAC3C,IAAI,MAAM,CAAC;gBACV,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,4BAA4B;aACxD,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtB,CAAC,CAAA,CAJiC,MAAM,EAIrC;IACJ,CAAC;IACD,WAAW;QACV,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAChC,CAAC;CACD', + names: [], + sourceRoot: '', + sources: [ + 'Require_Callback.js', + ], + version: 3, + } + +## Transpile Require_Callback_2.js + +> Snapshot 1 + + `import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + import MyModule from "my/module";␊ + import Module from "my/module";␊ + import Module from "my/module";␊ + true && ((Module) => {␊ + return Module;␊ + })(Module);␊ + true ? ((Module) => {␊ + return Module;␊ + })(Module) : "foo";␊ + if (false) {␊ + return "bar";␊ + }␊ + else if (((Module) => {␊ + return Module;␊ + })(Module)) {␊ + return "baz";␊ + }␊ + foo(((Module) => {␊ + return Module;␊ + })(Module), "bar");␊ + if (((Module) => {␊ + return Module;␊ + })(Module)) {␊ + return ((Module) => {␊ + return Module;␊ + })(Module);␊ + }␊ + const arr = [((Module) => {␊ + return Module;␊ + })(Module), ((Module) => {␊ + return Module;␊ + })(Module)];␊ + let val = ((Module) => {␊ + return Module;␊ + })(Module);␊ + let val2 = ((Module) => {␊ + return Module;␊ + })(Module) + 1;␊ + let val3 = -((Module) => {␊ + return Module;␊ + })(Module);␊ + let val4 = ((Module) => {␊ + return Module;␊ + })(Module)++;␊ + let val5 = () => ((Module) => {␊ + return Module;␊ + })(Module);␊ + window.sap.ui.require(["my/module"], (Module) => {␊ + return Module;␊ + });␊ + window[((Module) => {␊ + return Module;␊ + })(Module)];␊ + window.["window"];␊ + ((Module) => {␊ + return Module;␊ + })(Module);␊ + window.["sap"]["ui"]["require"](["my/module"], (Module) => {␊ + return Module;␊ + });␊ + let val = ((Module) => {␊ + return Module;␊ + })(Module);␊ + let val2 = ((Module) => {␊ + return Module;␊ + })(Module) + 1;␊ + let val3 = () => ((Module) => {␊ + return Module;␊ + })(Module);␊ + while (((Module) => {␊ + return Module;␊ + })(Module)) {␊ + return "foo";␊ + }␊ + do {␊ + console.log("foo");␊ + } while (((Module) => {␊ + return Module;␊ + })(Module));␊ + for (let i = 0; i < ((Module) => {␊ + return Module;␊ + })(Module); i++) {␊ + ((Module) => {␊ + return Module;␊ + })(Module)[i];␊ + }␊ + function () {␊ + ((Module) => {␊ + return Module;␊ + })(Module);␊ + }␊ + () => {␊ + ((Module) => {␊ + return Module;␊ + })(Module);␊ + };␊ + (() => ((Module) => {␊ + return Module;␊ + })(Module));␊ + var ;␊ + function () {␊ + ((Module) => {␊ + return Module;␊ + })(Module);␊ + }␊ + const obj1 = {␊ + prop1: ((Module) => {␊ + return Module;␊ + })(Module),␊ + [((Module) => {␊ + return Module;␊ + })(Module)]: "foo"␊ + };␊ + class MyClass {␊ + prop1 = ((Module) => {␊ + return Module;␊ + })(Module);␊ + [((Module) => {␊ + return Module;␊ + })(Module)];␊ + load() {␊ + ((Module) => {␊ + return Module;␊ + })(Module);␊ + }␊ + }␊ + function* generatorFunction() {␊ + yield ((Module) => {␊ + return Module;␊ + })(Module);␊ + }␊ + var deps = ["my/module"];␊ + (Module) => {␊ + return Module;␊ + };␊ + var callback = (MyModule) => {␊ + console.log(MyModule);␊ + };␊ + ((MyModule) => {␊ + console.log(MyModule);␊ + })(MyModule);␊ + var require = function (deps) {␊ + ((Module) => {␊ + return Module;␊ + })(Module);␊ + sap.ui.require(deps, (Module) => {␊ + return Module;␊ + });␊ + };␊ + require(["my/module"]);␊ + var specialRequire = function (param = ((Module) => {␊ + return Module;␊ + })(Module)) {␊ + sap.ui.require(param, (Module) => {␊ + return Module;␊ + });␊ + };␊ + //# sourceMappingURL=Require_Callback_2.ts.map` + +> Snapshot 2 + + { + file: 'Require_Callback_2.js', + mappings: 'OAAuC,MAAM,MAArB,WAAW;OAIG,MAAM,MAArB,WAAW;OAMQ,MAAM,MAArB,WAAW;OAMH,MAAM,MAArB,WAAW;OAII,MAAM,MAArB,WAAW;OAGQ,MAAM,MAArB,WAAW;OAIS,MAAM,MAArB,WAAW;OAEL,MAAM,MAArB,WAAW;OAGU,MAAM,MAArB,WAAW;OAGK,MAAM,MAArB,WAAW;OAGK,MAAM,MAArB,WAAW;OAGG,MAAM,MAArB,WAAW;OAGU,MAAM,MAArB,WAAW;OAON,MAAM,MAArB,WAAW;OAGc,MAAM,MAArB,WAAW;OAQH,MAAM,MAArB,WAAW;OAGK,MAAM,MAArB,WAAW;OAGU,MAAM,MAArB,WAAW;OAIP,MAAM,MAArB,WAAW;OAQM,MAAM,MAArB,WAAW;OAIgB,MAAM,MAArB,WAAW;OAGf,MAAM,MAArB,WAAW;OAMI,MAAM,MAArB,WAAW;OAMI,MAAM,MAArB,WAAW;OAKU,MAAM,MAArB,WAAW;OAKF,MAAM,MAArB,WAAW;OAMW,MAAM,MAArB,WAAW;OAGF,MAAM,MAArB,WAAW;OAMW,MAAM,MAArB,WAAW;OAGH,MAAM,MAArB,WAAW;OAII,MAAM,MAArB,WAAW;OAOU,MAAM,MAArB,WAAW;OAQnB,QAAQ,MAHZ,WAAW;OASS,MAAM,MAArB,WAAW;OAS0C,MAAM,MAArB,WAAW;AAjKlE,IAAI,IAAkC,CAAA,CAAC,MAAM,EAAE,EAAE;IAChD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFsC,MAAM,CAE3C,CAAC;AAEH,IAAI,CAAC,CAAC,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFqC,MAAM,EAEzC,CAAC,CAAC,KAAK,CAAC;AAEX,IAAI,KAAK,EAAE,CAAC;IACX,OAAO,KAAK,CAAC;AACd,CAAC;KAAM,IAAkC,CAAA,CAAC,MAAM,EAAE,EAAE;IACnD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFyC,MAAM,GAE5C,CAAC;IACJ,OAAO,KAAK,CAAC;AACd,CAAC;AAED,GAAG,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IAC5C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFkC,MAAM,GAErC,KAAK,CAAC,CAAC;AAEX,IAAkC,CAAA,CAAC,MAAM,EAAE,EAAE;IAC5C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFkC,MAAM,GAErC,CAAC;IACJ,OAAqC,CAAA,CAAC,MAAM,EAAE,EAAE;QAChD,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAFsC,MAAM,EAE1C;AACH,CAAC;AACD,MAAM,GAAG,GAAG,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;QACrD,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF2C,MAAM,GAEhB,CAAA,CAAC,MAAM,EAAE,EAAE;QAC5C,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAFkC,MAAM,EAEtC,CAAC;AACJ,IAAI,GAAG,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IAClD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFwC,MAAM,CAE7C,CAAC;AACH,IAAI,IAAI,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IACnD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFyC,MAAM,IAE3C,CAAC,CAAC;AACP,IAAI,IAAI,GAAG,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IACpD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAF0C,MAAM,CAE/C,CAAC;AACH,IAAI,IAAI,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IACnD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFyC,MAAM,GAE5C,CAAC;AACL,IAAI,IAAI,GAAG,GAAG,EAAE,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IACzD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAF+C,MAAM,CAEpD,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC,CAAC,CAAC;AACH,MAAM,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFqC,MAAM,EAEzC,CAAC;AACJ,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAA;AAA8B,CAAA,CAAC,MAAM,EAAE,EAAE;IACzD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAF+C,MAAM,EAEnD;AAEH,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE;IACzD,OAAO,MAAM,CAAC;AACf,CAAC,CAAC,CAAC;AAEH,IAAI,GAAG,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IAClD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFwC,MAAM,CAE7C,CAAC;AACH,IAAI,IAAI,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IACnD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFyC,MAAM,IAE3C,CAAC,CAAC;AACP,IAAI,IAAI,GAAG,GAAG,EAAE,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IACxD,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAF8C,MAAM,CAEnD,CAAC;AAEJ,OAAoC,CAAA,CAAC,MAAM,EAAE,EAAE;IAC7C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFmC,MAAM,GAEtC,CAAC;IACL,OAAO,KAAK,CAAC;AACd,CAAC;AAED,GAAG,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC,QAAqC,CAAA,CAAC,MAAM,EAAE,EAAE;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFqC,MAAM,GAExC;AAEL,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IAC3D,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFiD,MAAM,CAEtD,EAAE,CAAC,EAAE,EAAE,CAAC;IACoB,CAAA,CAAC,MAAM,EAAE,EAAE;QACxC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF8B,MAAM,EAElC,CAAC,CAAC,CAAA;AACN,CAAC;AAED,SAAS,AAAD;IACuB,CAAA,CAAC,MAAM,EAAE,EAAE;QACxC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF8B,MAAM,EAElC;AACJ,CAAC;AAED,GAAG,EAAE;IAC0B,CAAA,CAAC,MAAM,EAAE,EAAE;QACxC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF8B,MAAM,EAElC;AACJ,CAAC,CAAA;AAED,CAAC,GAAG,EAAE,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;IAC/C,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFqC,MAAM,CAE1C,CAAC,CAAC;AAEJ,IAAG,CAAA;AAAC,SAAS,AAAD;IACmB,CAAA,CAAC,MAAM,EAAE,EAAE;QACxC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF8B,MAAM,EAElC;AACJ,CAAC;AAED,MAAM,IAAI,GAAG;IACZ,KAAK,EAAgC,CAAA,CAAC,MAAM,EAAE,EAAE;QAC/C,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAFqC,MAAM,CAE1C;IACF,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;QACzC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF+B,MAAM,EAEnC,EAAE,KAAK;CACV,CAAC;AAEF,MAAM,OAAO;IACZ,KAAK,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;QAChD,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAFsC,MAAM,EAE1C;IACH,CAA+B,CAAA,CAAC,MAAM,EAAE,EAAE;QACzC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF+B,MAAM,EAEnC,CAAQ;IACX,IAAI;QAC2B,CAAA,CAAC,MAAM,EAAE,EAAE;YACxC,OAAO,MAAM,CAAC;QACf,CAAC,CAAA,CAF8B,MAAM,EAElC;IACJ,CAAC;CACD;AAED,QAAQ,CAAC,CAAC,iBAAiB;IACzB,MAAoC,CAAA,CAAC,MAAM,EAAE,EAAE;QAC/C,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAFqC,MAAM,CAE1C,CAAC;AACJ,CAAC;AAED,IAAI,IAAI,GAAG,CAAC,WAAW,CAAE,CAAA;AAAC,CAAC,MAAM,EAAE,EAAE;IACnC,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AACH,IAAI,QAAQ,GAAG,CAAC,QAAQ,EAAE,EAAE;IAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC,CAAC;AACF,AAHe,CAAA,CAAC,QAAQ,EAAE,EAAE;IAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC,CAAA,CAFe,QAAQ,EAGO;AAE/B,IAAI,OAAO,GAAG,UAAU,IAAI;IACG,CAAA,CAAC,MAAM,EAAE,EAAE;QACxC,OAAO,MAAM,CAAC;IACf,CAAC,CAAA,CAF8B,MAAM,EAElC;IACH,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE;QAC/B,OAAO,MAAM,CAAC;IACf,CAAC,CAAC,CAAC;AACJ,CAAC,CAAA;AACD,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AAEvB,IAAI,cAAc,GAAG,UAAU,KAAK,GAAiC,CAAA,CAAC,MAAM,EAAE,EAAE;IAC9E,OAAO,MAAM,CAAC;AACf,CAAC,CAAA,CAFoE,MAAM,CAEzE;IACF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE;QAChC,OAAO,MAAM,CAAC;IACf,CAAC,CAAC,CAAC;AACJ,CAAC,CAAA', + names: [], + sourceRoot: '', + sources: [ + 'Require_Callback_2.js', + ], + version: 3, + } + +## Transpile Require_Errback.js + +> Snapshot 1 + + `import module from "some/module";␊ + ((module) => {␊ + module.renderButton();␊ + })(module);␊ + function extracted_require_errback_1(err) {␊ + console.log(err);␊ + }␊ + //# sourceMappingURL=Require_Errback.ts.map` + +> Snapshot 2 + + { + file: 'Require_Errback.js', + mappings: 'OAAiC,MAAM,MAAvB,aAAa;AAAG,CAAA,CAAC,MAAM,EAAE,EAAE;IAC1C,MAAM,CAAC,YAAY,EAAE,CAAC;AACvB,CAAC,CAAA,CAFgC,MAAM,EAIpC;qCAFC,GAAG;IACN,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAClB,CAAC', + names: [], + sourceRoot: '', + sources: [ + 'Require_Errback.js', + ], + version: 3, + } + +## Transpile Require_Import.js + +> Snapshot 1 + + `import "my/module";␊ + import "my/other/module";␊ + //# sourceMappingURL=Require_Import.ts.map` + +> Snapshot 2 + + { + file: 'Require_Import.js', + mappings: 'OAAgB,WAAW;OAAE', + names: [], + sourceRoot: '', + sources: [ + 'Require_Import.js', + ], + version: 3, + } + +## Transpile Require_Import_2.js + +> Snapshot 1 + + `import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import "my/module";␊ + import MyModule from "my/module";␊ + import "my/module";␊ + import "my/module";␊ + true && undefined;␊ + true ? undefined : "foo";␊ + if (false) {␊ + return "bar";␊ + }␊ + else if (undefined) {␊ + return "baz";␊ + }␊ + foo();␊ + let val2 = undefined + 1;␊ + window.sap.ui.require(["my/module"]);␊ + window[undefined];␊ + window.["sap"].ui.require(["my/module"]);␊ + let val2 = undefined + 1;␊ + new val()();␊ + while (undefined) {␊ + return "foo";␊ + }␊ + do {␊ + console.log("foo");␊ + } while (undefined);␊ + for (let i = 0; i < undefined; i++) {␊ + undefined[i];␊ + }␊ + var ;␊ + const obj1 = {␊ + prop1: undefined␊ + };␊ + class MyClass {␊ + prop1 = undefined;␊ + }␊ + var deps = ["my/module"];␊ + var callback = (MyModule) => {␊ + console.log(MyModule);␊ + };␊ + ((MyModule) => {␊ + console.log(MyModule);␊ + })(MyModule);␊ + var require = function (deps) {␊ + sap.ui.require(deps);␊ + };␊ + require(["my/module"]);␊ + var specialRequire = function () {␊ + sap.ui.require(param);␊ + };␊ + //# sourceMappingURL=Require_Import_2.ts.map` + +> Snapshot 2 + + { + file: 'Require_Import_2.js', + mappings: 'OAAgB,WAAW;OAEH,WAAW;OAEZ,WAAW;OAIP,WAAW;OAGlB,WAAW;OAEX,WAAW;OACP,WAAW;OAEN,WAAW;OAAoB,WAAW;OAC7C,WAAW;OACV,WAAW;OACV,WAAW;OACZ,WAAW;OACL,WAAW;OAGrB,WAAW;OAGR,WAAW;OACV,WAAW;OACL,WAAW;OAEpB,WAAW;OAAoB,WAAW;OAE5C,WAAW;OAMT,WAAW;OAEC,WAAW;OAC9B,WAAW;OAIX,WAAW;OAIX,WAAW;OAGL,WAAW;OAGjB,WAAW;OAIJ,WAAW;OACjB,WAAW;OAIJ,WAAW;OAClB,WAAW;OAEX,WAAW;OAKL,WAAW;OAInB,QAAQ,MADZ,WAAW;OAON,WAAW;OAK2B,WAAW;AAtFlE,IAAI,aAAiC,CAAC;AAEtC,IAAI,CAAC,CAAC,WAA+B,CAAC,CAAC,KAAK,CAAC;AAE7C,IAAI,KAAK,EAAE,CAAC;IACX,OAAO,KAAK,CAAC;AACd,CAAC;KAAM,eAAmC,CAAC;IAC1C,OAAO,KAAK,CAAC;AACd,CAAC;AACD,GAAG,EAA+B,CAAC;AAOnC,IAAI,IAAI,GAAG,YAAgC,CAAC,CAAC;AAK7C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AACrC,MAAM,WAA+B,CAAC;AACtC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AAGzC,IAAI,IAAI,GAAG,YAAgC,CAAC,CAAC;AAG7C,IAAI,GAAG,EAA+B,EAA+B,CAAC;AAEtE,kBAAqC,CAAC;IACrC,OAAO,KAAK,CAAC;AACd,CAAC;AAED,GAAG,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC,mBAAsC;AAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,YAAgC,EAAE,CAAC,EAAE,EAAE,CAAC;IACxD,UAA8B,CAAC,CAAC,CAAA;AACjC,CAAC;AAYD,IAAG,CAAA;AAIH,MAAM,IAAI,GAAG;IACZ,KAAK,WAA+B;CAEpC,CAAC;AAEF,MAAM,OAAO;IACZ,KAAK,aAAiC;CAKtC;AAMD,IAAI,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;AACzB,IAAI,QAAQ,GAAG,CAAC,QAAQ,EAAE,EAAE;IAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC,CAAC;AACF,AAHe,CAAA,CAAC,QAAQ,EAAE,EAAE;IAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC,CAAA,CAFe,QAAQ,EAGO;AAE/B,IAAI,OAAO,GAAG,UAAU,IAAI;IAE3B,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC,CAAA;AACD,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AAEvB,IAAI,cAAc,GAAG;IACpB,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAA', + names: [], + sourceRoot: '', + sources: [ + 'Require_Import_2.js', + ], + version: 3, + } + +## Transpile Require_Probing.js + +> Snapshot 1 + + `import sap_m_Table_1 from "sap/m/Table";␊ + import sap_ui_model_json_JSONModel_1 from "sap/ui/model/json/JSONModel";␊ + export default {␊ + maybeTable() {␊ + var Table = sap_m_Table_1; // Convert to import for Table␊ + if (Table) {␊ + var JSONModel = sap_ui_model_json_JSONModel_1;␊ + return new Table().setModel(new JSONModel());␊ + }␊ + }␊ + };␊ + //# sourceMappingURL=Require_Probing.ts.map` + +> Snapshot 2 + + { + file: 'Require_Probing.js', + mappings: '0BAG8B,aAAa;0CAER,6BAA6B;eAJxD;IACN,UAAU;QACT,IAAI,KAAK,gBAAgC,CAAC,CAAC,8BAA8B;QACzE,IAAI,KAAK,EAAE,CAAC;YACX,IAAI,SAAS,gCAAgD,CAAC;YAC9D,OAAO,IAAI,KAAK,EAAE,CAAC,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;QAC9C,CAAC;IACF,CAAC;CACD', + names: [], + sourceRoot: '', + sources: [ + 'Require_Probing.js', + ], + version: 3, + } + +## Transpile Require_Probing_2.js + +> Snapshot 1 + + `import my_module_1 from "my/module";␊ + import my_module_2 from "my/module";␊ + import my_module_3 from "my/module";␊ + import my_module_4 from "my/module";␊ + import my_module_5 from "my/module";␊ + import my_module_6 from "my/module";␊ + import my_module_7 from "my/module";␊ + import my_module_8 from "my/module";␊ + import my_module_9 from "my/module";␊ + import my_module_10 from "my/module";␊ + import my_module_11 from "my/module";␊ + import my_module_12 from "my/module";␊ + import my_module_13 from "my/module";␊ + import my_module_14 from "my/module";␊ + import my_module_15 from "my/module";␊ + import my_module_16 from "my/module";␊ + import my_module_17 from "my/module";␊ + import my_module_18 from "my/module";␊ + import my_module_19 from "my/module";␊ + import my_module_20 from "my/module";␊ + import my_module_21 from "my/module";␊ + import my_module_22 from "my/module";␊ + import my_module_23 from "my/module";␊ + import my_module_24 from "my/module";␊ + import my_module_25 from "my/module";␊ + import my_module_26 from "my/module";␊ + import my_module_27 from "my/module";␊ + import my_module_28 from "my/module";␊ + import my_module_29 from "my/module";␊ + import my_module_30 from "my/module";␊ + import my_module_31 from "my/module";␊ + import my_module_32 from "my/module";␊ + import my_module_33 from "my/module";␊ + import my_module_34 from "my/module";␊ + import my_module_35 from "my/module";␊ + import my_module_36 from "my/module";␊ + import my_module_37 from "my/module";␊ + my_module_1;␊ + true && my_module_2;␊ + true ? my_module_3 : "foo";␊ + if (false) {␊ + return "bar";␊ + }␊ + else if (my_module_4) {␊ + return "baz";␊ + }␊ + foo(my_module_5);␊ + if (my_module_6) {␊ + return my_module_7;␊ + }␊ + const arr = [my_module_8, my_module_9];␊ + let val = my_module_10;␊ + let val2 = my_module_11 + 1;␊ + let val3 = -my_module_12;␊ + let val4 = my_module_13++;␊ + let val5 = () => my_module_14;␊ + window.sap.ui.require("my/module");␊ + window[my_module_15];␊ + window.["sap"].ui.require("my/module");␊ + let val = my_module_16;␊ + let val2 = my_module_17 + 1;␊ + let val3 = () => my_module_18;␊ + new val(my_module_19)(my_module_20);␊ + while (my_module_21) {␊ + return "foo";␊ + }␊ + do {␊ + console.log("foo");␊ + } while (my_module_22);␊ + for (let i = 0; i < my_module_23; i++) {␊ + my_module_24[i];␊ + }␊ + function () {␊ + my_module_25;␊ + }␊ + () => {␊ + my_module_26;␊ + };␊ + (() => my_module_27);␊ + var ;␊ + function () {␊ + my_module_28;␊ + }␊ + const obj1 = {␊ + prop1: my_module_29,␊ + [my_module_30]: "foo"␊ + };␊ + class MyClass {␊ + prop1 = my_module_31;␊ + [my_module_32];␊ + load() {␊ + my_module_33;␊ + }␊ + }␊ + function* generatorFunction() {␊ + yield my_module_34;␊ + }␊ + var deps = "my/module";␊ + var callback = (MyModule) => {␊ + console.log(MyModule);␊ + };␊ + my_module_35;␊ + var require = function (deps) {␊ + my_module_36;␊ + sap.ui.require(deps);␊ + };␊ + require("my/module");␊ + var specialRequire = function (param = my_module_37) {␊ + sap.ui.require(param);␊ + };␊ + //# sourceMappingURL=Require_Probing_2.ts.map` + +> Snapshot 2 + + { + file: 'Require_Probing_2.js', + mappings: 'wBAAe,WAAW;wBAEH,WAAW;wBAEZ,WAAW;wBAIP,WAAW;wBAIlB,WAAW;wBAEX,WAAW;wBACP,WAAW;wBAEN,WAAW;wBAAkB,WAAW;yBAC3C,WAAW;yBACV,WAAW;yBACV,WAAW;yBACZ,WAAW;yBACL,WAAW;yBAGrB,WAAW;yBAGR,WAAW;yBACV,WAAW;yBACL,WAAW;yBAEpB,WAAW;yBAAkB,WAAW;yBAE1C,WAAW;yBAMT,WAAW;yBAEC,WAAW;yBAC9B,WAAW;yBAIX,WAAW;yBAIX,WAAW;yBAGL,WAAW;yBAGjB,WAAW;yBAIJ,WAAW;yBACjB,WAAW;yBAIJ,WAAW;yBAClB,WAAW;yBAEX,WAAW;yBAKL,WAAW;yBAGvB,WAAW;yBAON,WAAW;yBAK2B,WAAW;AAzFjE,YAA4B;AAE5B,IAAI,eAA+B,CAAC;AAEpC,IAAI,CAAC,CAAC,aAA6B,CAAC,CAAC,KAAK,CAAC;AAE3C,IAAI,KAAK,EAAE,CAAC;IACX,OAAO,KAAK,CAAC;AACd,CAAC;KAAM,iBAAiC,CAAC;IACxC,OAAO,KAAK,CAAC;AACd,CAAC;AAED,GAAG,aAA6B,CAAC;AAEjC,iBAAiC,CAAC;IACjC,mBAAmC;AACpC,CAAC;AACD,MAAM,GAAG,GAAG,0BAA0D,CAAC;AACvE,IAAI,GAAG,eAA8B,CAAC;AACtC,IAAI,IAAI,GAAG,eAA8B,CAAC,CAAC;AAC3C,IAAI,IAAI,GAAG,aAA4B,CAAC;AACxC,IAAI,IAAI,GAAG,cAA6B,CAAC;AACzC,IAAI,IAAI,GAAG,GAAG,EAAE,aAA4B,CAAC;AAE7C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AACnC,MAAM,cAA6B,CAAC;AACpC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AAEvC,IAAI,GAAG,eAA8B,CAAC;AACtC,IAAI,IAAI,GAAG,eAA8B,CAAC,CAAC;AAC3C,IAAI,IAAI,GAAG,GAAG,EAAE,aAA4B,CAAC;AAE7C,IAAI,GAAG,cAA6B,cAA6B,CAAC;AAElE,qBAAmC,CAAC;IACnC,OAAO,KAAK,CAAC;AACd,CAAC;AAED,GAAG,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC,sBAAoC;AAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,eAA8B,EAAE,CAAC,EAAE,EAAE,CAAC;IACtD,aAA4B,CAAC,CAAC,CAAA;AAC/B,CAAC;AAED,SAAS,AAAD;IACP,aAA4B;AAC7B,CAAC;AAED,GAAG,EAAE;IACJ,aAA4B;AAC7B,CAAC,CAAA;AAED,CAAC,GAAG,EAAE,aAA4B,CAAC,CAAC;AAEpC,IAAG,CAAA;AAAC,SAAS,AAAD;IACX,aAA4B;AAC7B,CAAC;AAED,MAAM,IAAI,GAAG;IACZ,KAAK,cAA6B;IAClC,cAA6B,EAAE,KAAK;CACpC,CAAC;AAEF,MAAM,OAAO;IACZ,KAAK,gBAA+B;IACpC,cAA6B,CAAQ;IACrC,IAAI;QACH,aAA2B;IAC5B,CAAC;CACD;AAED,QAAQ,CAAC,CAAC,iBAAiB;IACzB,kBAAiC,CAAC;AACpC,CAAC;AAED,IAAI,IAAI,GAAG,WAAW,CAAC;AACvB,IAAI,QAAQ,GAAG,CAAC,QAAQ,EAAE,EAAE;IAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC,CAAC;AACF,aAA+B;AAE/B,IAAI,OAAO,GAAG,UAAU,IAAI;IAC3B,aAA4B;IAC5B,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC,CAAA;AACD,OAAO,CAAC,WAAW,CAAC,CAAC;AAErB,IAAI,cAAc,GAAG,UAAU,KAAK,eAA8B;IACjE,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAA', + names: [], + sourceRoot: '', + sources: [ + 'Require_Probing_2.js', + ], + version: 3, + } + +## Transpile Dependencies_NotProvided.js + +> Snapshot 1 + + `export default {␊ + add: function (x, y) {␊ + return x + y;␊ + }␊ + };␊ + ` + +> Snapshot 2 + + { + file: 'UNKNOWN', + mappings: ';EACCA,KAAK,UAAUC,GAAGC;WACVD,IAAIC', + names: [ + 'add', + 'x', + 'y', + ], + sources: [ + 'UNKNOWN', + ], + version: 3, + } + +## Transpile sapUiTestGenericUtils.js + +> Snapshot 1 + + `import ObjectPath from "sap/base/util/ObjectPath";␊ + import DataType from "sap/ui/base/DataType";␊ + import Lib from "sap/ui/core/Lib";␊ + import GenericTestCollection from "sap/ui/test/generic/GenericTestCollection";␊ + import require from "require";␊ + /**␊ + * @typedef {object} sap.ui.test.generic.ClassInfo␊ + * @property {string} className The class name␊ + * @property {sap.ui.core.Control|sap.ui.core.Element} [fnClass=undefined] The loaded class␊ + * @property {Error} [error=undefined] The error that might occur␊ + *␊ + * @private␊ + **/␊ + /**␊ + * @namespace sap.ui.test.generic.Utils␊ + * @private␊ + * @ui5-restricted SAPUI5 Distribution Layer Libraries␊ + */␊ + var Utils = {␊ + /**␊ + * @param {string} sClassName The class name which should be loaded␊ + * @param {string} sContainingModuleName Name of the module that contains the class. If not given, it is assumed that a module with the same name as the class (dots replaced by slashes) exports the class.␊ + * When given, the module is loaded and the class is retrieved via its global name␊ + * @return {Promise} Returns a promise resolving with a sap.ui.test.generic.ClassInfo object.␊ + */␊ + loadClass: function (sClassName, sContainingModuleName) {␊ + return new Promise(function (resolve) {␊ + var sModuleName = sContainingModuleName ? sContainingModuleName : sClassName.replace(/\\./g, "/");␊ + require([sModuleName], function (Class) {␊ + if (sContainingModuleName) {␊ + Class = ObjectPath.get(sClassName);␊ + }␊ + resolve({␊ + className: sClassName,␊ + fnClass: Class,␊ + error: undefined␊ + });␊ + }, function (err) {␊ + var Class = ObjectPath.get(sClassName);␊ + resolve({␊ + className: sClassName,␊ + fnClass: Class,␊ + error: err␊ + });␊ + });␊ + });␊ + },␊ + /**␊ + * Loads all control classes for the given library.␊ + *␊ + * @param {object} [mTestParams] Test specific parameters␊ + * @param {string} [mTestParams.library] The library name␊ + * @param {sap.ui.test.generic.GenericTestCollection.ObjectCapabilities} [mTestParams.objectCapabilities] The capabilities of the controls␊ + * @param {object} [mOptions] Object that holds further configs.␊ + * @param {boolean} [mOptions.includeElements=false] Whether the library's elements should be considered as well.␊ + * @return {Promise} Returns a promise resolving with an array of sap.ui.test.generic.ClassInfo objects.␊ + */␊ + loadAllControls: function (mTestParams, mOptions) {␊ + var sLibName = mTestParams.library;␊ + var mCapabilities = mTestParams.objectCapabilities || {};␊ + var aLoadedElementsAndControls = [];␊ + mOptions = mOptions || {};␊ + var aLoadClassPromises = [];␊ + var loadControls = function () {␊ + return Lib.load(sLibName).then(function (library) {␊ + var aClasses = library ? library.controls : [];␊ + if (mOptions.includeElements) {␊ + aClasses = aClasses.concat(library.elements);␊ + }␊ + aClasses = aClasses.filter(function (sControlName) {␊ + // Check if there are new controls or elements available in library after the previous loading␊ + return !aLoadedElementsAndControls.includes(sControlName);␊ + });␊ + if (aClasses.length > 0) {␊ + aClasses.forEach(function (sClass) {␊ + var sModuleName = mCapabilities[sClass] && mCapabilities[sClass].moduleName;␊ + aLoadClassPromises.push(Utils.loadClass(sClass, sModuleName));␊ + aLoadedElementsAndControls.push(sClass);␊ + });␊ + return Promise.all(aLoadClassPromises).then(loadControls);␊ + }␊ + return Promise.all(aLoadClassPromises);␊ + });␊ + };␊ + return loadControls().then(function (aClassInfo) {␊ + var i;␊ + var aClassInfoError = aClassInfo.filter(function (oClassInfo) {␊ + return oClassInfo.error !== undefined;␊ + });␊ + aClassInfo = aClassInfo.filter(function (oClassInfo) {␊ + return !!oClassInfo.fnClass;␊ + });␊ + if (aClassInfoError.length) {␊ + QUnit.test("Controls only available in global namespace", function (assert) {␊ + for (i = 0; i < aClassInfoError.length; i++) {␊ + assert.ok(false, aClassInfoError[i].className + " seems to be only available using global namespace." +␊ + " If the class exists, but is not a module of its own, then specify the module that contains the class within the testsuite config.");␊ + }␊ + });␊ + }␊ + return aClassInfo;␊ + });␊ + },␊ + /**␊ + * Create a control or element based on the given object capabilities␊ + *␊ + * @param {sap.ui.core.Control|sap.ui.core.Element} Class The control or element class to instantiate␊ + * @param {sap.ui.test.generic.GenericTestCollection.ObjectCapabilities} oObjectCapabilities The capabilities of the correspodning control␊ + * @param {map} mSettings Settings which should be used to create the control or element␊ + * @return {sap.ui.core.Control|sap.ui.core.Element} Instance of the control or element␊ + */␊ + createControlOrElement: function (Class, oObjectCapabilities, mSettings) {␊ + if (oObjectCapabilities && oObjectCapabilities.create) {␊ + return oObjectCapabilities.create(Class, mSettings);␊ + }␊ + else {␊ + return new Class(mSettings);␊ + }␊ + },␊ + /**␊ + * Tries to fill all control properties with string values␊ + *␊ + * @param {sap.ui.core.Control} oControl The control whose properties get filled␊ + * @param {sap.ui.test.generic.GenericTestCollection.ObjectCapabilities} oObjectCapabilities The capabilities of the corresponding control␊ + */␊ + fillControlProperties: function (oControl, oObjectCapabilities) {␊ + var mProperties = oControl.getMetadata().getAllProperties(), mPropertyCapabilities = oObjectCapabilities && oObjectCapabilities.properties || {}, vValueToSet = "test"; // just try a string as default, with some frequently happening exceptions␊ + for (var sPropertyName in mProperties) {␊ + var oProperty = mProperties[sPropertyName], sPropertyCapability;␊ + // Check if property should be skipped because of known issues or if a specific value should be used for setting the property␊ + if (mPropertyCapabilities[sPropertyName]) {␊ + if (GenericTestCollection.ExcludeReason.hasOwnProperty(mPropertyCapabilities[sPropertyName])) {␊ + sPropertyCapability = mPropertyCapabilities[sPropertyName];␊ + }␊ + else {␊ + vValueToSet = mPropertyCapabilities[sPropertyName];␊ + }␊ + }␊ + if (sPropertyCapability !== GenericTestCollection.ExcludeReason.NotChangeableAfterInit &&␊ + sPropertyCapability !== GenericTestCollection.ExcludeReason.SetterNeedsSpecificSettings &&␊ + sPropertyCapability !== GenericTestCollection.ExcludeReason.OnlyChangeableViaBinding) {␊ + try {␊ + if (oProperty.type === "boolean") {␊ + vValueToSet = false;␊ + }␊ + else if (oProperty.type === "int") {␊ + vValueToSet = 100;␊ + }␊ + else if (oProperty.type.startsWith("sap.")) {␊ + var oEnum = require(oProperty.type.replace(/\\./g, "\\/"));␊ + vValueToSet = oEnum[Object.keys(oEnum)[0]];␊ + }␊ + oControl[oProperty._sMutator](vValueToSet);␊ + }␊ + catch (e) {␊ + // type check error, ignore␊ + // QUnit.assert.ok(true, "INFO: Failed to fill property: '" + sPropertyName + "' to control '" + oControl.getMetadata().getName() + "'");␊ + }␊ + }␊ + }␊ + try {␊ + oControl.setTooltip("test"); // seems not to be a property...␊ + }␊ + catch (error) {␊ + // This case currently only happens in sap.ui.webc libraries␊ + // They can't handle a string as tooltip properly therefore␊ + // setting tooltip on these controls fails␊ + // Adding this try catch here instead of exception in order␊ + // to avoid an entry for each of the controls in the␊ + // corresponding config files␊ + // The libraries where not tested before the introduction␊ + // of the new generic tests for libraries. Therefore the␊ + // issue was not 'visible' before␊ + QUnit.assert.ok(true, "WARNING: setTooltip is not able to handle strings");␊ + }␊ + },␊ + fillControlAggregations: function (oControl, mObjectCapabilities) {␊ + var oMetadata = oControl.getMetadata(), oObjectCapabilities = mObjectCapabilities[oMetadata.getName()], mAggregations = oMetadata.getAggregations();␊ + return Promise.all(Object.values(mAggregations).map(function (oAggregation) {␊ + var sAggregationType = oAggregation.type;␊ + // Specific handling for frequently used abstract and interface classes␊ + switch (oAggregation.type) {␊ + case "sap.ui.core.Control":␊ + // Use sap.m.Text in case aggregation is of type sap.ui.core.Control␊ + sAggregationType = "sap.m.Text";␊ + break;␊ + case "sap.ui.core.Element":␊ + // Use sap.ui.core.Icon in case aggregation is of type sap.ui.core.Element␊ + sAggregationType = "sap.ui.core.Icon";␊ + break;␊ + case "sap.ui.core.Toolbar":␊ + // Toolbar is interface - Special treatment because of legacy coding in old␊ + // DuplicateIdCheck qunit␊ + sAggregationType = "sap.m.Toolbar";␊ + break;␊ + default:␊ + sAggregationType = oAggregation.type;␊ + break;␊ + }␊ + // Check if aggregation should be skipped because of known issues or if a specific control should be used for the aggregation␊ + if (oObjectCapabilities && oObjectCapabilities.aggregations && oObjectCapabilities.aggregations[oAggregation.name]) {␊ + if (GenericTestCollection.ExcludeReason.hasOwnProperty(oObjectCapabilities.aggregations[oAggregation.name])) {␊ + var sAggregationCapability = oObjectCapabilities.aggregations[oAggregation.name];␊ + if (sAggregationCapability === GenericTestCollection.ExcludeReason.NotChangeableAfterInit ||␊ + sAggregationCapability === GenericTestCollection.ExcludeReason.SetterNeedsSpecificSettings) {␊ + return Promise.resolve(undefined); // Skip this aggregation because it can't be added generically␊ + }␊ + }␊ + else {␊ + sAggregationType = oObjectCapabilities.aggregations[oAggregation.name];␊ + }␊ + }␊ + var sModuleName = mObjectCapabilities[sAggregationType] && mObjectCapabilities[sAggregationType].moduleName ? mObjectCapabilities[sAggregationType].moduleName : undefined;␊ + if (DataType.isInterfaceType(sAggregationType)) {␊ + return Promise.resolve(undefined); // Can't handle interface types generically␊ + }␊ + return Utils.loadClass(sAggregationType, sModuleName).then(function (oClassInfo) {␊ + var oElement;␊ + if (!oClassInfo.fnClass) {␊ + QUnit.assert.ok(false, "No class of type " + sAggregationType + " for aggregation '" + oAggregation.name + "' of " + oControl + " could be loaded. Does this class exist? Is it properly implemented?");␊ + return;␊ + }␊ + if (oClassInfo.fnClass.getMetadata().isAbstract()) {␊ + // we also shouldn't instantiate abstract classes␊ + return;␊ + }␊ + else {␊ + // A specific Control or Element type. Try to add a working instance.␊ + oElement = new oClassInfo.fnClass();␊ + }␊ + // In case we were able to instantiate a suitable Element, add it into the aggregation.␊ + if (oElement) {␊ + oControl[oAggregation._sMutator](oElement);␊ + }␊ + return oElement;␊ + }).catch(function () {␊ + // error while creating or adding a child element: not a problem, just reducing test coverage a bit␊ + // QUnit.assert.ok(true, "INFO: Failed to add aggregation '" + oAggregation.name + "' of type '" + oAggregation.type + "' to control '" + oControl.getMetadata().getName() + "'");␊ + });␊ + }));␊ + }␊ + };␊ + export default Utils;␊ + //# sourceMappingURL=sapUiTestGenericUtils.ts.map` + +> Snapshot 2 + + { + file: 'sapUiTestGenericUtils.js', + mappings: 'OAWY,UAAU,MALrB,0BAA0B;OAKH,QAAQ,MAJ/B,sBAAsB;OAIW,GAAG,MAHpC,iBAAiB;OAGqB,qBAAqB,MAF3D,2CAA2C;OAEkB,OAAO,MADpE,SAAS;AAIT;;;;;;;IAOI;AAEJ;;;;GAIG;AACH,IAAI,KAAK,GAAG;IACX;;;;;OAKG;IACH,SAAS,EAAE,UAAS,UAAU,EAAE,qBAAqB;QACpD,OAAO,IAAI,OAAO,CAAC,UAAS,OAAO;YAClC,IAAI,WAAW,GAAG,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACjG,OAAO,CAAC,CAAC,WAAW,CAAC,EAAE,UAAS,KAAK;gBACpC,IAAI,qBAAqB,EAAE,CAAC;oBAC3B,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACpC,CAAC;gBACD,OAAO,CAAC;oBACP,SAAS,EAAE,UAAU;oBACrB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,SAAS;iBAChB,CAAC,CAAC;YAEJ,CAAC,EAAE,UAAS,GAAG;gBACd,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBACvC,OAAO,CAAC;oBACP,SAAS,EAAE,UAAU;oBACrB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,GAAG;iBACV,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,eAAe,EAAE,UAAS,WAAW,EAAE,QAAQ;QAC9C,IAAI,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QACnC,IAAI,aAAa,GAAG,WAAW,CAAC,kBAAkB,IAAI,EAAE,CAAC;QACzD,IAAI,0BAA0B,GAAG,EAAE,CAAC;QAEpC,QAAQ,GAAG,QAAQ,IAAI,EAAE,CAAC;QAE1B,IAAI,kBAAkB,GAAG,EAAE,CAAC;QAE5B,IAAI,YAAY,GAAG;YAClB,OAAO,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,OAAO;gBAC/C,IAAI,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBAE/C,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;oBAC9B,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAC9C,CAAC;gBAED,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,YAAY;oBAChD,8FAA8F;oBAC9F,OAAO,CAAC,0BAA0B,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;gBAC3D,CAAC,CAAC,CAAC;gBAEH,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzB,QAAQ,CAAC,OAAO,CAAC,UAAS,MAAM;wBAC/B,IAAI,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC;wBAE5E,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;wBAC9D,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACzC,CAAC,CAAC,CAAC;oBACH,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC3D,CAAC;gBACD,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACxC,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC;QAEF,OAAO,YAAY,EAAE,CAAC,IAAI,CAAC,UAAU,UAAU;YAC9C,IAAI,CAAC,CAAC;YACN,IAAI,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,UAAU;gBAC3D,OAAO,UAAU,CAAC,KAAK,KAAK,SAAS,CAAC;YACvC,CAAC,CAAC,CAAC;YAEH,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,UAAU;gBAClD,OAAO,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;YAC7B,CAAC,CAAC,CAAC;YAEH,IAAI,eAAe,CAAC,MAAM,EAAE,CAAC;gBAC5B,KAAK,CAAC,IAAI,CAAC,6CAA6C,EAAE,UAAU,MAAM;oBACzE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,qDAAqD;4BACpG,oIAAoI,CAAC,CAAC;oBACxI,CAAC;gBACF,CAAC,CAAC,CAAC;YACJ,CAAC;YACD,OAAO,UAAU,CAAC;QACnB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,sBAAsB,EAAE,UAAU,KAAK,EAAE,mBAAmB,EAAE,SAAS;QACtE,IAAI,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,EAAE,CAAC;YACvD,OAAO,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACP,OAAO,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;IAEF,CAAC;IAED;;;;;OAKG;IACF,qBAAqB,EAAE,UAAS,QAAQ,EAAE,mBAAmB;QAC7D,IAAI,WAAW,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,gBAAgB,EAAE,EAC1D,qBAAqB,GAAG,mBAAmB,IAAI,mBAAmB,CAAC,UAAU,IAAI,EAAE,EACnF,WAAW,GAAG,MAAM,CAAC,CAAC,0EAA0E;QAEjG,KAAK,IAAI,aAAa,IAAI,WAAW,EAAE,CAAC;YACvC,IAAI,SAAS,GAAG,WAAW,CAAC,aAAa,CAAC,EACzC,mBAAmB,CAAC;YAErB,6HAA6H;YAC7H,IAAI,qBAAqB,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC1C,IAAI,qBAAqB,CAAC,aAAa,CAAC,cAAc,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;oBAC9F,mBAAmB,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;gBAC5D,CAAC;qBAAM,CAAC;oBACP,WAAW,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;gBACpD,CAAC;YACF,CAAC;YAED,IAAI,mBAAmB,KAAK,qBAAqB,CAAC,aAAa,CAAC,sBAAsB;gBACrF,mBAAmB,KAAK,qBAAqB,CAAC,aAAa,CAAC,2BAA2B;gBACvF,mBAAmB,KAAK,qBAAqB,CAAC,aAAa,CAAC,wBAAwB,EAAE,CAAC;gBACvF,IAAI,CAAC;oBACJ,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;wBAClC,WAAW,GAAG,KAAK,CAAC;oBACrB,CAAC;yBAAM,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;wBACrC,WAAW,GAAG,GAAG,CAAC;oBACnB,CAAC;yBAAM,IAAI,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;wBAC9C,IAAI,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;wBACzD,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC5C,CAAC;oBAED,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,CAAC;gBAC5C,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACZ,2BAA2B;oBAC3B,yIAAyI;gBAC1I,CAAC;YACF,CAAC;QACF,CAAC;QACD,IAAI,CAAC;YACJ,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,gCAAgC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,4DAA4D;YAC5D,2DAA2D;YAC3D,0CAA0C;YAC1C,2DAA2D;YAC3D,oDAAoD;YACpD,6BAA6B;YAC7B,yDAAyD;YACzD,wDAAwD;YACxD,iCAAiC;YACjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,mDAAmD,CAAC,CAAC;QAC5E,CAAC;IACF,CAAC;IAED,uBAAuB,EAAE,UAAS,QAAQ,EAAE,mBAAmB;QAC9D,IAAI,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,EACrC,mBAAmB,GAAG,mBAAmB,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,EAC9D,aAAa,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,GAAG,CACjB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,UAAS,YAAY;YACrD,IAAI,gBAAgB,GAAG,YAAY,CAAC,IAAI,CAAC;YAEzC,uEAAuE;YACvE,QAAQ,YAAY,CAAC,IAAI,EAAE,CAAC;gBAC5B,KAAK,qBAAqB;oBACzB,oEAAoE;oBACpE,gBAAgB,GAAG,YAAY,CAAC;oBAChC,MAAM;gBACP,KAAK,qBAAqB;oBACzB,0EAA0E;oBAC1E,gBAAgB,GAAG,kBAAkB,CAAC;oBACtC,MAAM;gBACP,KAAK,qBAAqB;oBACzB,2EAA2E;oBAC3E,yBAAyB;oBACzB,gBAAgB,GAAG,eAAe,CAAC;oBACnC,MAAM;gBACP;oBACC,gBAAgB,GAAG,YAAY,CAAC,IAAI,CAAC;oBACrC,MAAM;YACP,CAAC;YAED,6HAA6H;YAC7H,IAAI,mBAAmB,IAAI,mBAAmB,CAAC,YAAY,IAAI,mBAAmB,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpH,IAAI,qBAAqB,CAAC,aAAa,CAAC,cAAc,CAAC,mBAAmB,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBAC7G,IAAI,sBAAsB,GAAG,mBAAmB,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;oBAEjF,IAAI,sBAAsB,KAAK,qBAAqB,CAAC,aAAa,CAAC,sBAAsB;wBACxF,sBAAsB,KAAK,qBAAqB,CAAC,aAAa,CAAC,2BAA2B,EAAE,CAAC;wBAC7F,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,8DAA8D;oBAClG,CAAC;gBACF,CAAC;qBAAM,CAAC;oBACP,gBAAgB,GAAG,mBAAmB,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;gBACxE,CAAC;YACF,CAAC;YACD,IAAI,WAAW,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,IAAI,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;YAE3K,IAAI,QAAQ,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAChD,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,2CAA2C;YAC/E,CAAC;YACD,OAAO,KAAK,CAAC,SAAS,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,UAAS,UAAU;gBAC7E,IAAI,QAAQ,CAAC;gBAEb,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;oBACzB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,YAAY,CAAC,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,sEAAsE,CAAC,CAAC;oBACxM,OAAO;gBACR,CAAC;gBAED,IAAI,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,EAAG,CAAC;oBACpD,iDAAiD;oBACjD,OAAO;gBAER,CAAC;qBAAM,CAAC;oBACP,qEAAqE;oBACrE,QAAQ,GAAG,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACrC,CAAC;gBAED,uFAAuF;gBACvF,IAAI,QAAQ,EAAE,CAAC;oBACd,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAC5C,CAAC;gBAED,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC,CAAC,KAAK,CAAC;gBACR,mGAAmG;gBACnG,kLAAkL;YACnL,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CACF,CAAC;IACH,CAAC;CACD,CAAC;eAEK,KAAK', + names: [], + sourceRoot: '', + sources: [ + 'sapUiTestGenericUtils.js', + ], + version: 3, + } diff --git a/test/lib/detectors/transpilers/amd/snapshots/transpiler.ts.snap b/test/lib/detectors/transpilers/amd/snapshots/transpiler.ts.snap new file mode 100644 index 000000000..1e86691df Binary files /dev/null and b/test/lib/detectors/transpilers/amd/snapshots/transpiler.ts.snap differ diff --git a/test/lib/detectors/transpilers/amd/transpiler.ts b/test/lib/detectors/transpilers/amd/transpiler.ts new file mode 100644 index 000000000..c9d1c2a4f --- /dev/null +++ b/test/lib/detectors/transpilers/amd/transpiler.ts @@ -0,0 +1,25 @@ +import anyTest, {TestFn} from "ava"; +import sinonGlobal from "sinon"; +import path from "node:path"; +// import fs from "node:fs/promises"; +import {fileURLToPath} from "node:url"; +// import {amdToEsm} from "../../../../../src/detectors/transpilers/amd/transpiler.js"; +import {createTestsForFixtures} from "./_helper.js"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixtures = path.join(__dirname, "..", "..", "..", "..", "fixtures", "transpiler", "amd"); + +const test = anyTest as TestFn<{ + sinon: sinonGlobal.SinonSandbox, + createdFiles: object, +}>; + +test.beforeEach(async (t) => { + t.context.sinon = sinonGlobal.createSandbox(); + t.context.createdFiles = {}; +}); +test.afterEach.always((t) => { + t.context.sinon.restore(); +}); + +createTestsForFixtures(fixtures); diff --git a/test/lib/detectors/transpilers/xml/_helper.ts b/test/lib/detectors/transpilers/xml/_helper.ts new file mode 100644 index 000000000..ab545a439 --- /dev/null +++ b/test/lib/detectors/transpilers/xml/_helper.ts @@ -0,0 +1,55 @@ +import anyTest, {TestFn} from "ava"; +import sinonGlobal from "sinon"; +import path from "node:path"; +import util from "util"; +import fs from "node:fs"; +import {xmlToJs} from "../../../../../src/detectors/transpilers/xml/transpiler.js"; + +util.inspect.defaultOptions.depth = 4; // Increase AVA's printing depth since coverageInfo objects are on level 4 + +const test = anyTest as TestFn<{ + sinon: sinonGlobal.SinonSandbox, +}>; + +// Helper function to create linting tests for all files in a directory +export function createTestsForFixtures(fixturesPath: string) { + try { + const testFiles = fs.readdirSync(fixturesPath); + if (!testFiles.length) { + throw new Error(`Failed to find any fixtures in directory ${fixturesPath}`); + } + for (const fileName of testFiles) { + if (!fileName.endsWith(".xml")) { + // Ignore non-XML files + continue; + } + + let testName = fileName; + let defineTest = test; + if (fileName.startsWith("_")) { + // Skip tests for files starting with underscore + defineTest = defineTest.skip as typeof test; + testName = fileName.slice(1); + } else if (fileName.startsWith("only_")) { + // Only run test when file starts with only_ + defineTest = defineTest.only as typeof test; + testName = fileName.slice(5); + } + + defineTest(`Transpile ${testName}`, async (t) => { + const filePath = path.join(fixturesPath, fileName); + const fileStream = fs.createReadStream(filePath); + const {source, map, messages} = await xmlToJs(testName, fileStream); + t.snapshot(source); + t.snapshot(map && JSON.parse(map)); + t.snapshot(messages); + }); + } + } catch (err) { + if (err instanceof Error) { + throw new Error( + `Failed to list files of directory ${fixturesPath}: ${err.message}`); + } + throw err; + } +} diff --git a/test/lib/detectors/transpilers/xml/snapshots/transpiler.ts.md b/test/lib/detectors/transpilers/xml/snapshots/transpiler.ts.md new file mode 100644 index 000000000..4bd552b74 --- /dev/null +++ b/test/lib/detectors/transpilers/xml/snapshots/transpiler.ts.md @@ -0,0 +1,973 @@ +# Snapshot report for `test/lib/detectors/transpilers/xml/transpiler.ts` + +The actual snapshot is saved in `transpiler.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## Transpile ComplexAttributeValues.view.xml + +> Snapshot 1 + + `import AnnotationHelper from "sap/ui/model/odata/AnnotationHelper";␊ + import Button from "sap/m/Button";␊ + import Label from "sap/m/Label";␊ + import Link from "sap/m/Link";␊ + import Message from "sap/ui/core/Message";␊ + import View from "sap/ui/core/mvc/View";␊ + const oLink = new Link({␊ + href: "{\\n\\t\\t\\tparts: [\\n\\t\\t\\t\\t'/firstName',\\n\\t\\t\\t\\t'/lastName'\\n\\t\\t\\t],\\n\\t\\t\\tformatter: '.formatMail'\\n\\t\\t}",␊ + });␊ + ␊ + const oButton = new Button({␊ + text: "Hello \\"World\\"",␊ + });␊ + ␊ + const oLabel = new Label({␊ + text: "Hello \\"World\\"",␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oLink,␊ + oButton,␊ + oLabel,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'ComplexAttributeValues.view.js', + mappings: 'AAGC,mEAA2H;AAS3H,kCAAwC;AACxC,gCAA6B;AAR7B,8BAMK;AARL,0CAA2H;AAH5H,wCAIC;cACA,UAMK;IANC,uHAMH;;;gBACH,YAAwC;IAAhC,wBAA8B;;;eACtC,WAA6B;IAAtB,wBAAoB;;;6BAb5B,UAIC;IACA,OAMK', + names: [], + sources: [ + 'ComplexAttributeValues.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile CustomControl.view.xml + +> Snapshot 1 + + `import MyControl from "sap/my/lib/MyControl";␊ + import MyOtherControl from "sap/my/lib/MyOtherControl";␊ + import View from "sap/ui/core/mvc/View";␊ + const oMyOtherControl = new MyOtherControl({␊ + });␊ + ␊ + const oMyControl = new MyControl({␊ + dependents: [␊ + oMyOtherControl,␊ + ],␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oMyControl,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'CustomControl.view.js', + mappings: 'AAIC,6CAAW;AACV,uDAAkB;AALpB,wCAEC;wBAGC,oBAAkB;;;mBADnB,eAAW;IACV,UAAkB;;;;;6BALpB,UAEC;IAEA,OAAW', + names: [], + sources: [ + 'CustomControl.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile CustomData.view.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import CustomData from "sap/ui/core/CustomData";␊ + import CustomData2 from "sap/ui/core/CustomData";␊ + import View from "sap/ui/core/mvc/View";␊ + const oCustomData = new CustomData({␊ + key: "type",␊ + value: "{contact>/teamsCollabOptions/0/key}",␊ + });␊ + ␊ + const oCustomData2 = new CustomData2({␊ + key: "email",␊ + value: "{contact>/email}",␊ + });␊ + ␊ + const oButton = new Button({␊ + icon: "{contact>/teamsCollabOptions/0/icon}",␊ + tooltip: "{contact>/teamsCollabOptions/0/tooltip}",␊ + press: ".onTeamsCollabOptionPress",␊ + class: "sapUiSmallMarginEnd",␊ + type: "Transparent",␊ + customData: [␊ + oCustomData,␊ + oCustomData2,␊ + ],␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oButton,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'CustomData.view.js', + mappings: 'AAIC,kCAOoB;AAJnB,gDAAoD;AACpD,iDAAkC;AARpC,wCAEoF;oBAKlF,gBAAoD;IAApD,YAAoD;IAApD,6CAAoD;;;qBACpD,iBAAkC;IAAlC,aAAkC;IAAlC,0BAAkC;;;gBAJnC,YAOoB;IANnB,6CAA2C;IAC3C,mDAAiD;IAGjD,mCAAiC;IACjC,6BAA2B;IAC3B,oBAAkB;IAPnB,UAOoB;;;;;;6BAXrB,UAEoF;IAEnF,OAOoB', + names: [], + sources: [ + 'CustomData.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile CustomData_FESR.fragment.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import CustomData from "sap/ui/core/CustomData";␊ + import CustomData2 from "sap/ui/core/CustomData";␊ + const oCustomData = new CustomData({␊ + key: "type",␊ + value: "{contact>/teamsCollabOptions/0/key}",␊ + });␊ + ␊ + const oCustomData2 = new CustomData2({␊ + key: "email",␊ + value: "{contact>/email}",␊ + });␊ + ␊ + const oButton = new Button({␊ + icon: "{contact>/teamsCollabOptions/0/icon}",␊ + tooltip: "{contact>/teamsCollabOptions/0/tooltip}",␊ + press: ".onTeamsCollabOptionPress",␊ + class: "sapUiSmallMarginEnd",␊ + type: "Transparent",␊ + customData: [␊ + oCustomData,␊ + oCustomData2,␊ + ],␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return [oButton];␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'CustomData_FESR.fragment.js', + mappings: 'AAOC,kCAQ2D;AAL1D,gDAAoD;AACpD,iDAAkC;oBADlC,gBAAoD;IAApD,YAAoD;IAApD,6CAAoD;;;qBACpD,iBAAkC;IAAlC,aAAkC;IAAlC,0BAAkC;;;gBAJnC,YAQ2D;IAP1D,6CAA2C;IAC3C,mDAAiD;IAGjD,mCAAiC;IACjC,6BAA2B;IAC3B,oBAAkB;IAPnB,UAQ2D', + names: [], + sources: [ + 'CustomData_FESR.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile DuplicateAggregations.view.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import Button2 from "sap/m/Button";␊ + import Button3 from "sap/m/Button";␊ + import Column from "sap/ui/table/Column";␊ + import Column2 from "sap/ui/table/Column";␊ + import Column3 from "sap/ui/table/Column";␊ + import Input from "sap/m/Input";␊ + import Label from "sap/m/Label";␊ + import Label2 from "sap/m/Label";␊ + import Label3 from "sap/m/Label";␊ + import Label4 from "sap/m/Label";␊ + import OverflowToolbar from "sap/m/OverflowToolbar";␊ + import Switch from "sap/m/Switch";␊ + import Table from "sap/ui/table/Table";␊ + import Text from "sap/m/Text";␊ + import Title from "sap/m/Title";␊ + import ToolbarSpacer from "sap/m/ToolbarSpacer";␊ + import View from "sap/ui/core/mvc/View";␊ + const oLabel = new Label({␊ + text: "Product Name",␊ + });␊ + ␊ + const oText = new Text({␊ + text: "{Name}",␊ + wrapping: "false",␊ + });␊ + ␊ + const oColumn = new Column({␊ + width: "11rem",␊ + label: [␊ + oLabel,␊ + ],␊ + template: [␊ + oText,␊ + ],␊ + });␊ + ␊ + const oTitle = new Title({␊ + id: "title",␊ + text: "Products",␊ + });␊ + ␊ + const oToolbarSpacer = new ToolbarSpacer({␊ + });␊ + ␊ + const oButton = new Button({␊ + icon: "sap-icon://activities",␊ + tooltip: "show indices of selected items",␊ + press: "getSelectedIndices",␊ + });␊ + ␊ + const oButton2 = new Button2({␊ + icon: "sap-icon://activity-items",␊ + tooltip: "show context of latest selection item",␊ + press: "getContextByIndex",␊ + });␊ + ␊ + const oButton3 = new Button3({␊ + icon: "sap-icon://decline",␊ + tooltip: "clear selection",␊ + press: "clearSelection",␊ + });␊ + ␊ + const oSwitch = new Switch({␊ + state: "true",␊ + customTextOn: "on",␊ + customTextOff: "off",␊ + tooltip: "enable select all items",␊ + change: "onSwitchChange",␊ + });␊ + ␊ + const oOverflowToolbar = new OverflowToolbar({␊ + style: "Clear",␊ + content: [␊ + oTitle,␊ + oToolbarSpacer,␊ + oButton,␊ + oButton2,␊ + oButton3,␊ + oSwitch,␊ + ],␊ + });␊ + ␊ + const oLabel2 = new Label2({␊ + text: "Product Id",␊ + });␊ + ␊ + const oInput = new Input({␊ + value: "{ProductId}",␊ + });␊ + ␊ + const oColumn2 = new Column2({␊ + width: "11rem",␊ + label: [␊ + oLabel2,␊ + ],␊ + template: [␊ + oInput,␊ + ],␊ + });␊ + ␊ + const oLabel3 = new Label3({␊ + text: "Quantity",␊ + });␊ + ␊ + const oLabel4 = new Label4({␊ + text: "{Quantity}",␊ + });␊ + ␊ + const oColumn3 = new Column3({␊ + width: "6rem",␊ + hAlign: "End",␊ + label: [␊ + oLabel3,␊ + ],␊ + template: [␊ + oLabel4,␊ + ],␊ + });␊ + ␊ + const oTable = new Table({␊ + groupBy: "some-column",␊ + columns: [␊ + oColumn,␊ + oColumn2,␊ + oColumn3,␊ + ],␊ + extension: [␊ + oOverflowToolbar,␊ + ],␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oTable,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'DuplicateAggregations.view.js', + mappings: 'AAkBI,kCAG6B;AAC7B,mCAG4B;AAC5B,mCAGyB;AAtB1B,yCAAsB;AAgCtB,0CAAsB;AAQtB,0CAAkC;AALhC,gCAA8B;AAlC/B,gCAA+B;AAgC/B,iCAA6B;AAQ7B,iCAA2B;AAE1B,iCAA6B;AAnC/B,oDAAiC;AAehC,kCAK0B;AA9B7B,uCAA6B;AAKzB,8BAAyC;AAM1C,gCAAqC;AACrC,gDAAkB;AAjBtB,wCAGC;eAKG,WAA+B;IAAtB,qBAAmB;;;cAE3B,UAAyC;IAAjC,eAAa;IAAC,kBAAgB;;;gBAHxC,YAAsB;IAAd,eAAa;IACpB,KAA+B;;;IAC/B,QAAU;;;;;eAOV,WAAqC;IAA5B,YAAU;IAAC,iBAAe;;;uBACnC,mBAAkB;;;gBAClB,YAG6B;IAF5B,8BAA4B;IAC5B,0CAAwC;IACxC,4BAA0B;;;iBAC3B,aAG4B;IAF3B,kCAAgC;IAChC,iDAA+C;IAC/C,2BAAyB;;;iBAC1B,aAGyB;IAFxB,2BAAyB;IACzB,2BAAyB;IACzB,wBAAsB;;;gBACvB,YAK0B;IAJzB,cAAY;IACZ,mBAAiB;IACjB,qBAAmB;IACnB,mCAAiC;IACjC,yBAAuB;;;yBApBzB,qBAAiC;IAAd,eAAa;IAC/B,OAAqC;;;;;;;;;;gBAwBrC,YAA6B;IAApB,mBAAiB;;;eAEzB,WAA8B;IAArB,qBAAmB;;;iBAH9B,aAAsB;IAAd,eAAa;IACpB,KAA6B;;;IAC7B,QAAU;;;;;gBAOV,YAA2B;IAAlB,iBAAe;;;gBAEvB,YAA6B;IAApB,mBAAiB;;;iBAH5B,aAAkC;IAA1B,cAAY;IAAC,cAAY;IAChC,KAA2B;;;IAC3B,QAAU;;;;;eA5Cb,WAA6B;IAAtB,uBAAqB;IAC3B,OAAS;;;;;IAQT,SAAW;;;;;6BAdb,UAGC;IAEA,OAA6B', + names: [], + sources: [ + 'DuplicateAggregations.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile IgnoredNamespaces.fragment.xml + +> Snapshot 1 + + `import SomeControl from "sap/m/SomeControl";␊ + import SomeOtherControl from "sap/m/SomeOtherControl";␊ + const oSomeControl = new SomeControl({␊ + });␊ + ␊ + const oSomeOtherControl = new SomeOtherControl({␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return [oSomeControl, oSomeOtherControl];␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'IgnoredNamespaces.fragment.js', + mappings: 'AAKC,4CAAwD;AACxD,sDAA0E;qBAD1E,iBAAwD;;;0BACxD,sBAA0E', + names: [], + sources: [ + 'IgnoredNamespaces.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile UnknownAttrNamespace.fragment.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + const oButton = new Button({␊ + Snapshot 2 + + { + file: 'UnknownAttrNamespace.fragment.js', + mappings: 'AAGC,kCAGS;gBAHT,YAGS;IAAT,aANA', + names: [], + sources: [ + 'UnknownAttrNamespace.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLFragment.fragment.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import Button2 from "sap/m/Button";␊ + import DateTimeInput from "sap/m/DateTimeInput";␊ + import MultiSelectionPlugin from "sap/ui/table/plugins/MultiSelectionPlugin";␊ + import SegmentedButton from "sap/m/SegmentedButton";␊ + import Table from "sap/ui/table/Table";␊ + import VBox from "sap/m/VBox";␊ + const oDateTimeInput = new DateTimeInput({␊ + });␊ + ␊ + const oButton = new Button({␊ + blocked: "true",␊ + });␊ + ␊ + const oMultiSelectionPlugin = new MultiSelectionPlugin({␊ + });␊ + ␊ + const oTable = new Table({␊ + groupBy: "some-column",␊ + plugins: [␊ + oMultiSelectionPlugin,␊ + ],␊ + });␊ + ␊ + const oButton2 = new Button2({␊ + tap: ".onButtonTap",␊ + });␊ + ␊ + const oSegmentedButton = new SegmentedButton({␊ + buttons: [␊ + oButton2,␊ + ],␊ + });␊ + ␊ + const oVBox = new VBox({␊ + items: [␊ + oDateTimeInput,␊ + oButton,␊ + oTable,␊ + oSegmentedButton,␊ + ],␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return oVBox;␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'XMLFragment.fragment.js', + mappings: 'AAOC,kCAAyB;AASxB,mCAA4B;AAX7B,gDAAiB;AAMb,6EAAqC;AAIzC,oDAAiB;AANjB,uCAAmC;AATpC,8BAGC;uBAEA,mBAAiB;;;gBAEjB,YAAyB;IAAjB,gBAAc;;;8BAIlB,0BAAqC;;;eAFzC,WAAmC;IAAtB,uBAAqB;IAChC,OAAe;;;;;iBAMhB,aAA4B;IAApB,oBAAkB;;;yBAD3B,qBAAiB;IAChB,OAA4B;;;;;cAhB9B,UAGC;IAEA,KAAiB', + names: [], + sources: [ + 'XMLFragment.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLFragmentDefinition.fragment.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import Button2 from "sap/m/Button";␊ + import DateTimeInput from "sap/m/DateTimeInput";␊ + import MultiSelectionPlugin from "sap/ui/table/plugins/MultiSelectionPlugin";␊ + import SegmentedButton from "sap/m/SegmentedButton";␊ + import Table from "sap/ui/table/Table";␊ + const oDateTimeInput = new DateTimeInput({␊ + });␊ + ␊ + const oButton = new Button({␊ + blocked: "true",␊ + });␊ + ␊ + const oMultiSelectionPlugin = new MultiSelectionPlugin({␊ + });␊ + ␊ + const oTable = new Table({␊ + groupBy: "some-column",␊ + plugins: [␊ + oMultiSelectionPlugin,␊ + ],␊ + });␊ + ␊ + const oButton2 = new Button2({␊ + tap: ".onButtonTap",␊ + });␊ + ␊ + const oSegmentedButton = new SegmentedButton({␊ + buttons: [␊ + oButton2,␊ + ],␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return [oDateTimeInput, oButton, oTable, oSegmentedButton];␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'XMLFragmentDefinition.fragment.js', + mappings: 'AAQC,kCAAyB;AASxB,mCAA4B;AAX7B,gDAAiB;AAMb,6EAAqC;AAIzC,oDAAiB;AANjB,uCAAmC;uBAJnC,mBAAiB;;;gBAEjB,YAAyB;IAAjB,gBAAc;;;8BAIlB,0BAAqC;;;eAFzC,WAAmC;IAAtB,uBAAqB;IAChC,OAAe;;;;;iBAMhB,aAA4B;IAApB,oBAAkB;;;yBAD3B,qBAAiB;IAChB,OAA4B', + names: [], + sources: [ + 'XMLFragmentDefinition.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLFragmentEmbedded.fragment.xml + +> Snapshot 1 + + `import Control from "sap/ui/core/Control";␊ + import MultiSelectionPlugin from "sap/ui/table/plugins/MultiSelectionPlugin";␊ + const oMultiSelectionPlugin = new MultiSelectionPlugin({␊ + });␊ + ␊ + const oControl = new Control({␊ + dependents: [␊ + oMultiSelectionPlugin,␊ + ],␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return oControl;␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'XMLFragmentEmbedded.fragment.js', + mappings: 'AACA,0CACE;AACA,6EAAqC;8BAArC,0BAAqC;;;iBAFvC,aACE;IACA,UAAqC', + names: [], + sources: [ + 'XMLFragmentEmbedded.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLFragmentEmbeddedFragDef.fragment.xml + +> Snapshot 1 + + `import Control from "sap/ui/core/Control";␊ + import MultiSelectionPlugin from "sap/ui/table/plugins/MultiSelectionPlugin";␊ + const oMultiSelectionPlugin = new MultiSelectionPlugin({␊ + });␊ + ␊ + const oControl = new Control({␊ + dependents: [␊ + oMultiSelectionPlugin,␊ + ],␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return [];␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'XMLFragmentEmbeddedFragDef.fragment.js', + mappings: 'AAKC,0CACE;AACA,6EAAqC;8BAArC,0BAAqC;;;iBAFvC,aACE;IACA,UAAqC', + names: [], + sources: [ + 'XMLFragmentEmbeddedFragDef.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLFragmentWithLowerCaseControl.fragment.xml + +> Snapshot 1 + + `import HorizontalLayout from "sap/ui/layout/HorizontalLayout";␊ + import Icon from "sap/ui/core/Icon";␊ + const oIcon = new Icon({␊ + src: "sap-icon://search",␊ + });␊ + ␊ + const oHorizontalLayout = new HorizontalLayout({␊ + button: [␊ + ],␊ + content: [␊ + oIcon,␊ + ],␊ + });␊ + ␊ + export default {␊ + createContent: function () {␊ + return oHorizontalLayout;␊ + };␊ + }␊ + ` + +> Snapshot 2 + + { + file: 'XMLFragmentWithLowerCaseControl.fragment.js', + mappings: 'AAAA,8DAAkG;AAEjG,oCAAwC;cAAxC,UAAwC;IAA1B,yBAAuB;;;0BAFtC,sBAAkG;IACjG,MAAkD;;IAClD,OAAwC', + names: [], + sources: [ + 'XMLFragmentWithLowerCaseControl.fragment.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLHtmlSvg.view.xml + +> Snapshot 1 + + `import View from "sap/ui/core/mvc/View";␊ + export default const oView = new View({␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'XMLHtmlSvg.view.js', + mappings: 'AAAA,wCAGC;6BAHD,UAGC', + names: [], + sources: [ + 'XMLHtmlSvg.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [ + { + column: 1, + line: 6, + message: 'Usage of native HTML in XML Views/Fragments is deprecated', + messageDetails: '{@link topic:be54950cae1041f59d4aa97a6bade2d8 Using Native HTML in XML Views (deprecated)}', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + line: 8, + message: 'Usage of SVG in XML Views/Fragments is deprecated', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + line: 9, + message: 'Usage of SVG in XML Views/Fragments is deprecated', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + line: 10, + message: 'Usage of SVG in XML Views/Fragments is deprecated', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ] + +## Transpile XMLRequire.view.xml + +> Snapshot 1 + + `import Box from "sap/m/MessageBox";␊ + import Button from "sap/m/Button";␊ + import Helper from "sap/ui/demo/todo/util/Helper";␊ + import Label from "sap/m/Label";␊ + import Message from "sap/ui/core/Message";␊ + import View from "sap/ui/core/mvc/View";␊ + const oLabel = new Label({␊ + text: "{path: 'badge>SecondaryInfo/Label', formatter: 'Helper.format'}",␊ + });␊ + ␊ + const oButton = new Button({␊ + text: "Press Me!",␊ + press: "Box.show('Hello!', {verticalScrolling: true})",␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oLabel,␊ + oButton,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'XMLRequire.view.js', + mappings: 'AAGC,mCAIE;AAGF,kCAAgF;AAPhF,kDAIE;AAEF,gCAA+E;AAN/E,0CAIE;AAPH,wCAQC;eACA,WAA+E;IAAxE,wEAAsE;;;gBAC7E,YAAgF;IAAxE,kBAAgB;IAAC,uDAAqD;;;6BAV/E,UAQC;IACA,OAA+E', + names: [], + sources: [ + 'XMLRequire.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLTemplatingRequire.view.xml + +> Snapshot 1 + + `import AnnotationHelper from "sap/ui/model/odata/AnnotationHelper";␊ + import HBox from "sap/m/HBox";␊ + import Icon from "sap/ui/core/Icon";␊ + import Message from "sap/ui/core/Message";␊ + import sap_ui_model_odata_ODataModel from "sap/ui/model/odata/ODataModel";␊ + import sap_ui_model_odata_ODataUtils from "sap/ui/model/odata/ODataUtils";␊ + import Text from "sap/m/Text";␊ + import View from "sap/ui/core/mvc/View";␊ + const oIcon = new Icon({␊ + src: "sap-icon://phone",␊ + width: "2em",␊ + });␊ + ␊ + const oText = new Text({␊ + text: "{path: 'field>Value', formatter: 'AH.format'}",␊ + });␊ + ␊ + const oHBox = new HBox({␊ + items: [␊ + oIcon,␊ + oText,␊ + ],␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oHBox,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'XMLTemplatingRequire.view.js', + mappings: 'AAKC,mEAA2G;AAG3G,8BAAqF;AAGlF,oCAAgD;AANnD,0CAA2G;AAGrG,0EAA8E;AAA9E,0EAA8E;AAMnF,8BAA4D;AAd9D,wCAMC;cAKG,UAAgD;IAArC,wBAAsB;IAAC,aAAW;;;cAG/C,UAA4D;IAAtD,sDAAoD;;;cAN3D,UAAqF;IAGlF,KAAgD;;;;;;6BAXpD,UAMC;IAEA,OAAqF', + names: [], + sources: [ + 'XMLTemplatingRequire.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLView.view.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import Button2 from "sap/m/Button";␊ + import DateTimeInput from "sap/m/DateTimeInput";␊ + import MultiSelectionPlugin from "sap/ui/table/plugins/MultiSelectionPlugin";␊ + import SegmentedButton from "sap/m/SegmentedButton";␊ + import Table from "sap/ui/table/Table";␊ + import View from "sap/ui/core/mvc/View";␊ + const oDateTimeInput = new DateTimeInput({␊ + });␊ + ␊ + const oButton = new Button({␊ + blocked: "true",␊ + });␊ + ␊ + const oMultiSelectionPlugin = new MultiSelectionPlugin({␊ + });␊ + ␊ + const oTable = new Table({␊ + groupBy: "some-column",␊ + plugins: [␊ + oMultiSelectionPlugin,␊ + ],␊ + });␊ + ␊ + const oButton2 = new Button2({␊ + tap: ".onButtonTap",␊ + });␊ + ␊ + const oSegmentedButton = new SegmentedButton({␊ + buttons: [␊ + oButton2,␊ + ],␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oDateTimeInput,␊ + oButton,␊ + oTable,␊ + oSegmentedButton,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'XMLView.view.js', + mappings: 'AAQC,kCAAyB;AASxB,mCAA4B;AAX7B,gDAAiB;AAMb,6EAAqC;AAIzC,oDAAiB;AANjB,uCAAmC;AAVpC,wCAIC;uBAEA,mBAAiB;;;gBAEjB,YAAyB;IAAjB,gBAAc;;;8BAIlB,0BAAqC;;;eAFzC,WAAmC;IAAtB,uBAAqB;IAChC,OAAe;;;;;iBAMhB,aAA4B;IAApB,oBAAkB;;;yBAD3B,qBAAiB;IAChB,OAA4B;;;;;6BAjB9B,UAIC;IAEA,OAAiB', + names: [], + sources: [ + 'XMLView.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLViewNamespacePrefix.view.xml + +> Snapshot 1 + + `import MultiSelectionPlugin from "sap/ui/table/plugins/MultiSelectionPlugin";␊ + import Table from "sap/ui/table/Table";␊ + import View from "sap/ui/core/mvc/View";␊ + const oMultiSelectionPlugin = new MultiSelectionPlugin({␊ + });␊ + ␊ + const oTable = new Table({␊ + groupBy: "some-column",␊ + plugins: [␊ + oMultiSelectionPlugin,␊ + ],␊ + });␊ + ␊ + export default const oView = new View({␊ + content: [␊ + oTable,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'XMLViewNamespacePrefix.view.js', + mappings: 'AAKK,6EAAyC;AAF7C,uCAAsC;AAHvC,wCAEC;8BAGI,0BAAyC;;;eAF7C,WAAsC;IAAtB,uBAAqB;IACnC,OAAkB;;;;;6BAJrB,UAEC;IACA,OAAsC', + names: [], + sources: [ + 'XMLViewNamespacePrefix.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] + +## Transpile XMLViewWithLowerCaseControl.view.xml + +> Snapshot 1 + + `import Button from "sap/m/Button";␊ + import Icon from "sap/ui/core/Icon";␊ + import View from "sap/ui/core/mvc/View";␊ + const oButton = new Button({␊ + text: "Press me",␊ + });␊ + ␊ + const oIcon = new Icon({␊ + src: "sap-icon://search",␊ + });␊ + ␊ + export default const oView = new View({␊ + panel: [␊ + oButton,␊ + ],␊ + content: [␊ + oIcon,␊ + ],␊ + });␊ + ␊ + ` + +> Snapshot 2 + + { + file: 'XMLViewWithLowerCaseControl.view.js', + mappings: 'AAEE,kCAAwB;AAEzB,oCAAwC;AAJzC,wCAA+F;gBAE7F,YAAwB;IAAhB,iBAAe;;;cAExB,UAAwC;IAA1B,yBAAuB;;;6BAJtC,UAA+F;IAC9F,KAAgC;;;IAGhC,OAAwC', + names: [], + sources: [ + 'XMLViewWithLowerCaseControl.view.xml', + ], + version: 3, + } + +> Snapshot 3 + + [] diff --git a/test/lib/detectors/transpilers/xml/snapshots/transpiler.ts.snap b/test/lib/detectors/transpilers/xml/snapshots/transpiler.ts.snap new file mode 100644 index 000000000..33cb3f6fc Binary files /dev/null and b/test/lib/detectors/transpilers/xml/snapshots/transpiler.ts.snap differ diff --git a/test/lib/detectors/transpilers/xml/transpiler.ts b/test/lib/detectors/transpilers/xml/transpiler.ts new file mode 100644 index 000000000..dc4e6389e --- /dev/null +++ b/test/lib/detectors/transpilers/xml/transpiler.ts @@ -0,0 +1,8 @@ +import path from "node:path"; +import {fileURLToPath} from "node:url"; +import {createTestsForFixtures} from "./_helper.js"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixtures = path.join(__dirname, "..", "..", "..", "..", "fixtures", "transpiler", "xml"); + +createTestsForFixtures(fixtures); diff --git a/test/lib/formatter/json.ts b/test/lib/formatter/json.ts new file mode 100644 index 000000000..8ed9b12f7 --- /dev/null +++ b/test/lib/formatter/json.ts @@ -0,0 +1,59 @@ +import anyTest, { TestFn } from "ava"; +import { Json } from "../../../src/formatter/json.ts"; +import { LintResult } from "../../../src/detectors/AbstractDetector.ts"; + +const test = anyTest as TestFn<{ + lintResults: LintResult[]; +}>; + +test.beforeEach((t) => { + t.context.lintResults = [{ + filePath: "", + messages: [{ + ruleId: "ui5-linter-no-deprecated-api", + severity: 2, + line: 5, + column: 1, + message: "Call to deprecated function 'attachInit' of class 'Core'", + messageDetails: "(since 1.118) - Please use {@link sap.ui.core.Core.ready Core.ready} instead." + },], + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + warningCount: 0, + }]; +}); + +test("Test Json Formatter (with '--details true')", (t) => { + const { lintResults } = t.context; + const jsonFormatter = new Json(); + const jsonResult = jsonFormatter.format(lintResults, true); + const parsedJson = JSON.parse(jsonResult); // fails if no valid JSON is returned + + t.notDeepEqual(parsedJson,lintResults, + "Original lintResults and JSON-formatted ones have different structure"); + t.true(Object.prototype.hasOwnProperty.call(parsedJson[0], "filePath"), + "The JSON-formatted lintResults contain the filePath property"); + t.true(Object.prototype.hasOwnProperty.call(parsedJson[0], "messages"), + "The JSON-formatted lintResults contain the messages property"); + t.false(Object.prototype.hasOwnProperty.call(parsedJson[0], "coverageInfo"), + "The JSON-formatted lintResults do NOT contain coverageInfo"); + t.true(Object.prototype.hasOwnProperty.call(parsedJson[0], "errorCount"), + "The JSON-formatted lintResults contain the errorCount property"); + t.true(Object.prototype.hasOwnProperty.call(parsedJson[0], "fatalErrorCount"), + "The JSON-formatted lintResults contain the fatalErrorCount property"); + t.true(Object.prototype.hasOwnProperty.call(parsedJson[0], "warningCount"), + "The JSON-formatted lintResults contain the warningCount property"); + t.true(Object.prototype.hasOwnProperty.call(parsedJson[0].messages[0], "messageDetails"), + "The messages property of the JSON-formatted lintResults contain the messageDetails property"); +}); + +test("Test Json Formatter (with '--details false')", (t) => { + const { lintResults } = t.context; + const jsonFormatter = new Json(); + const jsonResult = jsonFormatter.format(lintResults, false); + const parsedJson = JSON.parse(jsonResult); // fails if no valid JSON is returned + + t.false(Object.prototype.hasOwnProperty.call(parsedJson[0].messages[0], "messageDetails"), + "The messages of the JSON-formatted lintResults do NOT contain the messageDetails property"); +}); diff --git a/test/lib/formatter/lib/resolveLinks.ts b/test/lib/formatter/lib/resolveLinks.ts new file mode 100644 index 000000000..d84536888 --- /dev/null +++ b/test/lib/formatter/lib/resolveLinks.ts @@ -0,0 +1,23 @@ +import anyTest, { TestFn } from "ava"; +import { resolveLinks } from "../../../../src/formatter/lib/resolveLinks.js"; + +const test = anyTest as TestFn; + +test("Test links", (t) => { + const input = [ + "(since 1.120) - Please use {@link sap.ui.core.message.MessageType } instead.", + "(since 1.119) - Please use {@link sap.ui.core.Lib.getResourceBundleFor Lib.getResourceBundleFor }instead.", + "(since 1.118) - See {@link module :sap/ui/core/Theming.attachApplied Theming.attachApplied }instead.", + "(since 1.56) - Use {@link module :sap/ui/VersionInfo.load} instead", + ]; + const expected = [ + "(since 1.120) - Please use sap.ui.core.message.MessageType (https://ui5.sap.com/1.120/#/api/sap.ui.core.message.MessageType) instead.", + "(since 1.119) - Please use Lib.getResourceBundleFor (https://ui5.sap.com/1.120/#/api/sap.ui.core.Lib)instead.", + "(since 1.118) - See Theming.attachApplied (https://ui5.sap.com/1.120/#/api/module:sap/ui/core/Theming%23methods/sap/ui/core/Theming.attachApplied)instead.", + "(since 1.56) - Use sap/ui/VersionInfo.load (https://ui5.sap.com/1.120/#/api/module:sap/ui/VersionInfo%23methods/sap/ui/VersionInfo.load) instead" + ]; + + input.forEach((text, index) => { + t.is(resolveLinks(text), expected[index], "Correct resolution of links"); + }); +}); diff --git a/test/lib/linter/_linterHelper.ts b/test/lib/linter/_linterHelper.ts new file mode 100644 index 000000000..e5bc23f96 --- /dev/null +++ b/test/lib/linter/_linterHelper.ts @@ -0,0 +1,99 @@ +import anyTest, {ExecutionContext, TestFn} from "ava"; +import sinonGlobal, {SinonStub} from "sinon"; +import util from "util"; +import {readdirSync} from "node:fs"; +import esmock from "esmock"; +import {LintResult} from "../../../src/detectors/AbstractDetector.js"; +import FileLinter from "../../../src/detectors/typeChecker/FileLinter.ts"; + +util.inspect.defaultOptions.depth = 4; // Increase AVA's printing depth since coverageInfo objects are on level 4 + +const test = anyTest as TestFn<{ + sinon: sinonGlobal.SinonSandbox, + lintFile: SinonStub +}>; + +test.before(async (t) => { + const {lintModule: {lintFile}} = await esmockMessageDetails(); + t.context.lintFile = lintFile; +}); + +// Mock messageDetails as we do not have control over the deprecated texts and they could +// change anytime creating false positive failing tests. That way is ensured consistent and testable behavior. +export async function esmockMessageDetails() { + const checkerModule = await esmock("../../../src/detectors/typeChecker/index.js", { + "../../../src/detectors/typeChecker/FileLinter.js": + function (rootDir, filePath, sourceFile, sourceMap, checker) { + // Don't use sinon's stubs as it's hard to clean after them in this case and it leaks memory. + const linter = new FileLinter(rootDir, filePath, sourceFile, sourceMap, checker); + linter.extractDeprecatedMessage = () => "Deprecated test message"; + return linter; + } + }); + + const lintModule = await esmock("../../../src/linter/linter.js", { + "../../../src/detectors/typeChecker/index.js": checkerModule + }); + + return {lintModule, checkerModule}; +} + +// Helper function to compare file paths since we don't want to store those in the snapshots +export function assertExpectedLintResults( + t: ExecutionContext, res: LintResult[], basePath: string, filePaths: string[]) { + res.forEach((lintResult) => { + if (!filePaths.includes(lintResult.filePath)) { + t.fail(`Unexpected lint result for file ${lintResult.filePath}. Expected: ${filePaths.join(", ")}`); + } + }); +} + +// Helper function to create linting tests for all files in a directory +export function createTestsForFixtures(fixturesPath: string) { + try { + const testFiles = readdirSync(fixturesPath); + if (!testFiles.length) { + throw new Error(`Failed to find any fixtures in directory ${fixturesPath}`); + } + for (const fileName of testFiles) { + if (!fileName.endsWith(".js") && !fileName.endsWith(".xml") && !fileName.endsWith(".json")) { + // Ignore non-JavaScript, non-XML and non-JSON files + continue; + } + + let testName = fileName; + let defineTest = test.serial; + if (fileName.startsWith("_")) { + // Skip tests for files starting with underscore + defineTest = defineTest.skip as typeof test; + testName = fileName.slice(1); + } else if (fileName.startsWith("only_")) { + // Only run test when file starts with only_ + defineTest = defineTest.only as typeof test; + testName = fileName.slice(5); + } + // Executing linting in parallel might lead to OOM errors in the CI + // Therefore always use serial + defineTest(`General: ${testName}`, async (t) => { + const filePaths = [fileName]; + const {lintFile} = t.context; + + const res = await lintFile({ + rootDir: fixturesPath, + filePaths + }); + assertExpectedLintResults(t, res, fixturesPath, filePaths); + res.forEach((results) => { + results.filePath = testName; + }); + t.snapshot(res); + }); + } + } catch (err) { + if (err instanceof Error) { + throw new Error( + `Failed to list files of directory ${fixturesPath}: ${err.message}`); + } + throw err; + } +} diff --git a/test/lib/linter/linter.ts b/test/lib/linter/linter.ts new file mode 100644 index 000000000..eca0d6abb --- /dev/null +++ b/test/lib/linter/linter.ts @@ -0,0 +1,87 @@ +import anyTest, {TestFn} from "ava"; +import sinonGlobal, {SinonStub} from "sinon"; +import path from "node:path"; +import {fileURLToPath} from "node:url"; +import {createTestsForFixtures, assertExpectedLintResults, esmockMessageDetails} from "./_linterHelper.js"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const fixturesBasePath = path.join(__dirname, "..", "..", "fixtures", "linter"); +const fixturesGeneralPath = path.join(fixturesBasePath, "general"); +const fixturesProjectsPath = path.join(fixturesBasePath, "projects"); + +const test = anyTest as TestFn<{ + sinon: sinonGlobal.SinonSandbox, + lintProject: SinonStub +}>; + +test.before(async (t) => { + t.context.sinon = sinonGlobal.createSandbox(); + + const {lintModule: {lintProject}} = await esmockMessageDetails(); + t.context.lintProject = lintProject; +}); +test.after.always((t) => { + t.context.sinon.restore(); +}); + +// Define tests for reach file in the fixtures/linter/general directory +createTestsForFixtures(fixturesGeneralPath); + +// Test project fixtures individually +test.serial("lint: All files of com.ui5.troublesome.app", async (t) => { + const projectPath = path.join(fixturesProjectsPath, "com.ui5.troublesome.app"); + const {lintProject} = t.context; + + let res = await lintProject({ + rootDir: projectPath, + filePaths: [] + }); + + res = res.sort((a, b) => { + return a.filePath.localeCompare(b.filePath); + }); + + t.snapshot(res); +}); + +test.serial("lint: Some files of com.ui5.troublesome.app", async (t) => { + const projectPath = path.join(fixturesProjectsPath, "com.ui5.troublesome.app"); + const filePaths = [ + path.join("webapp", "controller", "BaseController.js"), + path.join("webapp", "controller", "App.controller.js"), + path.join("webapp", "Component.js"), + ]; + const {lintProject} = t.context; + + let res = await lintProject({ + rootDir: projectPath, + filePaths + }); + + res = res.sort((a, b) => { + return a.filePath.localeCompare(b.filePath); + }); + + assertExpectedLintResults(t, res, projectPath, [ + path.join("webapp", "model", "models.js"), + ...filePaths + ]); + + t.snapshot(res); +}); + +test.serial("lint: All files of library.with.custom.paths", async (t) => { + const projectPath = path.join(fixturesProjectsPath, "library.with.custom.paths"); + const {lintProject} = t.context; + + let res = await lintProject({ + rootDir: projectPath, + filePaths: [] + }); + + res = res.sort((a, b) => { + return a.filePath.localeCompare(b.filePath); + }); + + t.snapshot(res); +}); diff --git a/test/lib/linter/rules/NoDeprecatedApi.ts b/test/lib/linter/rules/NoDeprecatedApi.ts new file mode 100644 index 000000000..57b18a4f6 --- /dev/null +++ b/test/lib/linter/rules/NoDeprecatedApi.ts @@ -0,0 +1,10 @@ +import path from "node:path"; +import {fileURLToPath} from "node:url"; +import {createTestsForFixtures} from "../_linterHelper.js"; + +const filePath = fileURLToPath(import.meta.url); +const __dirname = path.dirname(filePath); +const fileName = path.basename(filePath, ".ts"); +const fixturesPath = path.join(__dirname, "..", "..", "..", "fixtures", "linter", "rules", fileName); + +createTestsForFixtures(fixturesPath); diff --git a/test/lib/linter/rules/NoGlobals.ts b/test/lib/linter/rules/NoGlobals.ts new file mode 100644 index 000000000..57b18a4f6 --- /dev/null +++ b/test/lib/linter/rules/NoGlobals.ts @@ -0,0 +1,10 @@ +import path from "node:path"; +import {fileURLToPath} from "node:url"; +import {createTestsForFixtures} from "../_linterHelper.js"; + +const filePath = fileURLToPath(import.meta.url); +const __dirname = path.dirname(filePath); +const fileName = path.basename(filePath, ".ts"); +const fixturesPath = path.join(__dirname, "..", "..", "..", "fixtures", "linter", "rules", fileName); + +createTestsForFixtures(fixturesPath); diff --git a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md new file mode 100644 index 000000000..4e5cc8f9d --- /dev/null +++ b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md @@ -0,0 +1,873 @@ +# Snapshot report for `test/lib/linter/rules/NoDeprecatedApi.ts` + +The actual snapshot is saved in `NoDeprecatedApi.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## General: ModuleImport.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'ModuleImport.js', + messages: [ + { + column: 16, + fatal: undefined, + line: 1, + message: 'Import of deprecated module \'sap/ui/model/odata/ODataModel\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: NoDeprecatedApi.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 15, + fatalErrorCount: 0, + filePath: 'NoDeprecatedApi.js', + messages: [ + { + column: 18, + fatal: undefined, + line: 2, + message: 'Import of deprecated module \'sap/m/DateTimeInput\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 41, + fatal: undefined, + line: 2, + message: 'Import of deprecated module \'sap/base/util/includes\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 9, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 10, + message: 'Use of deprecated property \'tap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 13, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 18, + message: 'Use of deprecated property \'plugins\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 21, + message: 'Use of deprecated property \'groupBy\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 24, + message: 'Call to deprecated function \'includes\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 26, + message: 'Call to deprecated function \'getCompatibilityVersion\' of class \'Configuration\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 27, + message: 'Call to deprecated function \'getCompatibilityVersion\' of class \'Configuration\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 29, + message: 'Access of deprecated property \'webview\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 30, + message: 'Access of deprecated property \'webview\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 32, + message: 'Access of deprecated property \'AnimationMode\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 34, + message: 'Access of deprecated property \'MessageType\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 36, + message: 'Access of deprecated property \'Date\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: NoDeprecatedApi_negative.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'NoDeprecatedApi_negative.js', + messages: [], + warningCount: 0, + }, + ] + +## General: PartialDeprecation.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'PartialDeprecation.js', + messages: [], + warningCount: 0, + }, + ] + +## General: PrototypeClass.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'PrototypeClass.js', + messages: [ + { + column: 3, + fatal: undefined, + line: 10, + message: 'Call to deprecated function \'setVisibleRowCount\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: XMLFragment.fragment.xml + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 6, + fatalErrorCount: 0, + filePath: 'XMLFragment.fragment.xml', + messages: [ + { + column: 2, + fatal: undefined, + line: 6, + message: 'Import of deprecated module \'sap/m/DateTimeInput\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 10, + fatal: undefined, + line: 8, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 15, + fatal: undefined, + line: 10, + message: 'Use of deprecated property \'groupBy\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 11, + message: 'Use of deprecated property \'plugins\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 11, + fatal: undefined, + line: 17, + message: 'Use of deprecated property \'tap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 17, + message: 'Use of deprecated property \'buttons\' of class \'SegmentedButton\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: XMLFragmentDefinition.fragment.xml + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 6, + fatalErrorCount: 0, + filePath: 'XMLFragmentDefinition.fragment.xml', + messages: [ + { + column: 2, + fatal: undefined, + line: 7, + message: 'Import of deprecated module \'sap/m/DateTimeInput\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 10, + fatal: undefined, + line: 9, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 15, + fatal: undefined, + line: 11, + message: 'Use of deprecated property \'groupBy\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 12, + message: 'Use of deprecated property \'plugins\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 11, + fatal: undefined, + line: 18, + message: 'Use of deprecated property \'tap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 18, + message: 'Use of deprecated property \'buttons\' of class \'SegmentedButton\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: XMLHtmlSvg.view.xml + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 4, + fatalErrorCount: 0, + filePath: 'XMLHtmlSvg.view.xml', + messages: [ + { + column: 1, + line: 6, + message: 'Usage of native HTML in XML Views/Fragments is deprecated', + messageDetails: '{@link topic:be54950cae1041f59d4aa97a6bade2d8 Using Native HTML in XML Views (deprecated)}', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + line: 8, + message: 'Usage of SVG in XML Views/Fragments is deprecated', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + line: 9, + message: 'Usage of SVG in XML Views/Fragments is deprecated', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + line: 10, + message: 'Usage of SVG in XML Views/Fragments is deprecated', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: XMLRequire.view.xml + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'XMLRequire.view.xml', + messages: [ + { + column: 2, + fatal: undefined, + line: 4, + message: 'Import of deprecated module \'sap/ui/core/Message\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: XMLTemplatingRequire.view.xml + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'XMLTemplatingRequire.view.xml', + messages: [ + { + column: 2, + fatal: undefined, + line: 6, + message: 'Import of deprecated module \'sap/ui/core/Message\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 8, + fatal: undefined, + line: 9, + message: 'Import of deprecated module \'sap/ui/model/odata/ODataModel\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: XMLView.view.xml + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 6, + fatalErrorCount: 0, + filePath: 'XMLView.view.xml', + messages: [ + { + column: 2, + fatal: undefined, + line: 7, + message: 'Import of deprecated module \'sap/m/DateTimeInput\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 10, + fatal: undefined, + line: 9, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 15, + fatal: undefined, + line: 11, + message: 'Use of deprecated property \'groupBy\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 12, + message: 'Use of deprecated property \'plugins\' of class \'Table\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 11, + fatal: undefined, + line: 18, + message: 'Use of deprecated property \'tap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 18, + message: 'Use of deprecated property \'buttons\' of class \'SegmentedButton\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: jQuery-device.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'jQuery-device.js', + messages: [ + { + column: 15, + fatal: undefined, + line: 2, + message: 'Access of deprecated property \'device\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + { + column: 11, + fatal: undefined, + line: 3, + message: 'Access of deprecated property \'os\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + { + column: 18, + fatal: undefined, + line: 4, + message: 'Access of deprecated property \'os\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-property', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: jQuery-plugins.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 18, + line: 3, + message: 'Unable to analyze this method call because the type of identifier "outerHTML" in "jQuery("#button").outerHTML()"" could not be determined', + }, + { + category: 1, + column: 2, + line: 4, + message: 'Unable to analyze this method call because the type of identifier "root" in "jQuery("#content").root({})"" could not be determined', + }, + { + category: 1, + column: 15, + line: 5, + message: 'Unable to analyze this method call because the type of identifier "uiarea" in "jQuery("#content").uiarea(0)"" could not be determined', + }, + ], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'jQuery-plugins.js', + messages: [ + { + column: 16, + fatal: undefined, + line: 2, + message: 'Call to deprecated function \'control\' of class \'JQueryStatic\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: jQuery.sap-global.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 20, + line: 2, + message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery.sap.properties()"" could not be determined', + }, + ], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'jQuery.sap-global.js', + messages: [ + { + column: 20, + fatal: undefined, + line: 2, + message: 'Access of global variable \'jQuery\' (jQuery.sap.properties)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: jQuery.sap-jquery.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 20, + line: 2, + message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery.sap.properties()"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'jQuery.sap-jquery.js', + messages: [], + warningCount: 0, + }, + ] + +## General: jQuery.sap-module.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 20, + line: 2, + message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery.sap.properties()"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'jQuery.sap-module.js', + messages: [], + warningCount: 0, + }, + ] + +## General: manifest.json + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 4, + fatalErrorCount: 0, + filePath: 'manifest.json', + messages: [ + { + column: 13, + fatal: undefined, + line: 58, + message: 'Use of deprecated property \'sap.ui5/resources/js\'', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 71, + message: 'Use of deprecated property \'sap.ui5/models/odata-v4/settings/synchronizationMode\' of sap.ui.model.odata.v4.ODataModel', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 77, + message: 'Use of deprecated property \'sap.ui5/models/odata-v4-via-dataSource/settings/synchronizationMode\' of sap.ui.model.odata.v4.ODataModel', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 17, + fatal: undefined, + line: 81, + message: 'Use of deprecated model type \'sap.ui5/models/odata/type="sap.ui.model.odata.ODataModel"\'', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: manifest_negative.json + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'manifest_negative.json', + messages: [], + warningCount: 0, + }, + ] + +## General: manifest_negative_empty.json + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'manifest_negative_empty.json', + messages: [], + warningCount: 0, + }, + ] + +## General: sap.ui.jsview.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'sap.ui.jsview.js', + messages: [ + { + column: 1, + fatal: undefined, + line: 1, + message: 'Call to deprecated function \'jsview\' (sap.ui.jsview)', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + fatal: undefined, + line: 1, + message: 'Access of global variable \'sap\' (sap.ui.jsview)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: sap.ui.require-nested.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'sap.ui.require-nested.js', + messages: [ + { + column: 6, + fatal: undefined, + line: 6, + message: 'Use of deprecated property \'tap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: sap.ui.require-toplevel.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'sap.ui.require-toplevel.js', + messages: [ + { + column: 3, + fatal: undefined, + line: 3, + message: 'Use of deprecated property \'tap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] diff --git a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap new file mode 100644 index 000000000..36268a04f Binary files /dev/null and b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap differ diff --git a/test/lib/linter/rules/snapshots/NoGlobals.ts.md b/test/lib/linter/rules/snapshots/NoGlobals.ts.md new file mode 100644 index 000000000..5b61b0c72 --- /dev/null +++ b/test/lib/linter/rules/snapshots/NoGlobals.ts.md @@ -0,0 +1,179 @@ +# Snapshot report for `test/lib/linter/rules/NoGlobals.ts` + +The actual snapshot is saved in `NoGlobals.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## General: NoGlobals.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 4, + line: 9, + message: 'Unable to analyze this method call because the type of identifier "helperFunction" in "cust.lib.helperFunction()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 14, + message: 'Unable to analyze this method call because the type of identifier "requireSync" in "sap.ui.requireSync()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 15, + message: 'Unable to analyze this method call because the type of identifier "requireSync" in "window["sap"].ui.requireSync()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 16, + message: 'Unable to analyze this method call because the type of identifier "requireSync" in "window.sap.ui.requireSync()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 17, + message: 'Unable to analyze this method call because the type of identifier "requireSync" in "globalThis.sap.ui.requireSync()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 18, + message: 'Unable to analyze this method call because the type of identifier "requireSync" in "self.sap.ui.requireSync()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 20, + message: 'Unable to analyze this method call because the type of identifier "requireSync" in "that.sap.ui.requireSync()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 29, + message: 'Unable to analyze this method call because the type of identifier "require" in "jQuery.sap.require()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 32, + message: 'Unable to analyze this method call because the type of identifier "stub" in "sinon.stub()"" could not be determined', + }, + ], + errorCount: 11, + fatalErrorCount: 0, + filePath: 'NoGlobals.js', + messages: [ + { + column: 8, + fatal: undefined, + line: 8, + message: 'Access of global variable \'sap\' (sap.m.Button)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 19, + fatal: undefined, + line: 11, + message: 'Access of global variable \'sap\' (sap.m)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 14, + message: 'Access of global variable \'sap\' (sap.ui.requireSync)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 15, + message: 'Access of global variable \'sap\' (window)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 16, + message: 'Access of global variable \'sap\' (window.sap.ui.requireSync)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 18, + message: 'Access of global variable \'sap\' (self.sap.ui.requireSync)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 20, + message: 'Access of global variable \'sap\' (that.sap.ui.requireSync)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 25, + message: 'Access of global variable \'sap\' (window)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 27, + message: 'Access of global variable \'jQuery\' (jQuery.ajax)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 28, + message: 'Access of global variable \'jQuery\' (jQuery)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 29, + message: 'Access of global variable \'jQuery\' (jQuery.sap.require)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: NoGlobals_Negative.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'NoGlobals_Negative.js', + messages: [], + warningCount: 0, + }, + ] diff --git a/test/lib/linter/rules/snapshots/NoGlobals.ts.snap b/test/lib/linter/rules/snapshots/NoGlobals.ts.snap new file mode 100644 index 000000000..c8de38df7 Binary files /dev/null and b/test/lib/linter/rules/snapshots/NoGlobals.ts.snap differ diff --git a/test/lib/linter/snapshots/linter.ts.md b/test/lib/linter/snapshots/linter.ts.md new file mode 100644 index 000000000..21aee1ef0 --- /dev/null +++ b/test/lib/linter/snapshots/linter.ts.md @@ -0,0 +1,996 @@ +# Snapshot report for `test/lib/linter/linter.ts` + +The actual snapshot is saved in `linter.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## General: Coverage.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 35, + line: 3, + message: 'Unable to analyze this method call because the type of identifier "get" in "oVariantManagementMapDataSelector.get({ reference: sReference })"" could not be determined', + }, + { + category: 1, + column: 4, + line: 6, + message: `Unable to analyze this method call because the type of identifier "forEach" in "oVariantManagement.variants.forEach((oVariant) => {␊ + if (oVariant.visible === false) {␊ + aHiddenVariants.push(oVariant.key);␊ + }␊ + })"" could not be determined`, + }, + { + category: 1, + column: 10, + line: 12, + message: `Unable to analyze this method call because the type of identifier "filter" in "aFlexObjects.filter((oFilteredFlexObject) => {␊ + // The following block should produce a coverage message:␊ + // "Unable to analyze this method call because the type of identifier"␊ + // However, the following line will be transformed to "[...] = ({ [...]" with␊ + // no source map entry for the added brackets (since it does not exist in source).␊ + // This poses a challenge for Reporter.ts to map to the correct location in the source file␊ + const sVariantReference = {␊ + // eslint-disable-next-line camelcase␊ + ctrl_variant: () => (oFilteredFlexObject.getVariantId()),␊ + // eslint-disable-next-line camelcase␊ + ctrl_variant_change: () => (oFilteredFlexObject.getSelector().id),␊ + change: () => (oFilteredFlexObject.getVariantReference())␊ + }[oFilteredFlexObject.getFileType()]?.();␊ + return !aHiddenVariants.includes(sVariantReference);␊ + })"" could not be determined`, + }, + { + category: 1, + column: 30, + line: 18, + message: `Unable to analyze this method call because the type of identifier in "{␊ + // eslint-disable-next-line camelcase␊ + ctrl_variant: () => (oFilteredFlexObject.getVariantId()),␊ + // eslint-disable-next-line camelcase␊ + ctrl_variant_change: () => (oFilteredFlexObject.getSelector().id),␊ + change: () => (oFilteredFlexObject.getVariantReference())␊ + }[oFilteredFlexObject.getFileType()]?.()"" could not be determined`, + }, + { + category: 1, + column: 26, + line: 20, + message: 'Unable to analyze this method call because the type of identifier "getVariantId" in "oFilteredFlexObject.getVariantId()"" could not be determined', + }, + { + category: 1, + column: 33, + line: 22, + message: 'Unable to analyze this method call because the type of identifier "getSelector" in "oFilteredFlexObject.getSelector()"" could not be determined', + }, + { + category: 1, + column: 20, + line: 23, + message: 'Unable to analyze this method call because the type of identifier "getVariantReference" in "oFilteredFlexObject.getVariantReference()"" could not be determined', + }, + { + category: 1, + column: 6, + line: 24, + message: 'Unable to analyze this method call because the type of identifier "getFileType" in "oFilteredFlexObject.getFileType()"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'Coverage.js', + messages: [], + warningCount: 0, + }, + ] + +## General: JSDoc.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'JSDoc.js', + messages: [ + { + column: 5, + fatal: undefined, + line: 15, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 17, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: PlainJS.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'PlainJS.js', + messages: [ + { + column: 3, + fatal: undefined, + line: 6, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 3, + fatal: undefined, + line: 12, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 18, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: Raw.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'Raw.js', + messages: [ + { + column: 5, + fatal: undefined, + line: 9, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 11, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: TSLike.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'TSLike.js', + messages: [ + { + column: 5, + fatal: undefined, + line: 11, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 13, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: Undetected.js + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 3, + line: 5, + message: `Unable to analyze this method call because the type of identifier "attachTap" in "btn.attachTap(function () {␊ + console.log("Tapped");␊ + })"" could not be determined`, + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'Undetected.js', + messages: [], + warningCount: 0, + }, + ] + +## lint: All files of com.ui5.troublesome.app + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/Component.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 33, + line: 8, + message: 'Unable to analyze this method call because the type of identifier "getContentDensityClass" in "this.getOwnerComponent().getContentDensityClass()"" could not be determined', + }, + ], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'webapp/controller/App.controller.js', + messages: [ + { + column: 4, + fatal: undefined, + line: 10, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 17, + line: 38, + message: 'Unable to analyze this method call because the type of identifier "getModel" in "this.getOwnerComponent().getModel("i18n")"" could not be determined', + }, + { + category: 1, + column: 11, + line: 39, + message: 'Unable to analyze this method call because the type of identifier "getResourceBundle" in "oModel.getResourceBundle()"" could not be determined', + }, + ], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'webapp/controller/BaseController.js', + messages: [ + { + column: 5, + fatal: undefined, + line: 9, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 11, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/controller/Main.controller.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/emptyFile.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/helpers/ES6Class.helper.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 4, + fatalErrorCount: 0, + filePath: 'webapp/manifest.json', + messages: [ + { + column: 13, + fatal: undefined, + line: 58, + message: 'Use of deprecated property \'sap.ui5/resources/js\'', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 71, + message: 'Use of deprecated property \'sap.ui5/models/odata-v4/settings/synchronizationMode\' of sap.ui.model.odata.v4.ODataModel', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 77, + message: 'Use of deprecated property \'sap.ui5/models/odata-v4-via-dataSource/settings/synchronizationMode\' of sap.ui.model.odata.v4.ODataModel', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 17, + fatal: undefined, + line: 81, + message: 'Use of deprecated model type \'sap.ui5/models/odata/type="sap.ui.model.odata.ODataModel"\'', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 20, + line: 6, + message: 'Unable to analyze this method call because the type of identifier "toUpperCase" in "value.toUpperCase()"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/model/formatter.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/model/models.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 2, + line: 6, + message: `Unable to analyze this method call because the type of identifier in "opaTest("Should open the Hello dialog", function (Given, When, Then) {␊ + // Arrangements␊ + Given.iStartMyUIComponent({␊ + componentConfig: {␊ + name: "com.ui5.troublesome.app"␊ + }␊ + });␊ + // Actions␊ + When.onTheMainPage.iPressTheSayHelloButton();␊ + // Assertions␊ + Then.onTheMainPage.iShouldSeeTheHelloDialog();␊ + // Actions␊ + When.onTheMainPage.iPressTheOkButtonInTheDialog();␊ + // Assertions␊ + Then.onTheMainPage.iShouldNotSeeTheHelloDialog();␊ + // Cleanup␊ + Then.iTeardownMyApp();␊ + })"" could not be determined`, + }, + { + category: 1, + column: 3, + line: 8, + message: `Unable to analyze this method call because the type of identifier "iStartMyUIComponent" in "Given.iStartMyUIComponent({␊ + componentConfig: {␊ + name: "com.ui5.troublesome.app"␊ + }␊ + })"" could not be determined`, + }, + { + category: 1, + column: 3, + line: 15, + message: 'Unable to analyze this method call because the type of identifier "iPressTheSayHelloButton" in "When.onTheMainPage.iPressTheSayHelloButton()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 18, + message: 'Unable to analyze this method call because the type of identifier "iShouldSeeTheHelloDialog" in "Then.onTheMainPage.iShouldSeeTheHelloDialog()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 21, + message: 'Unable to analyze this method call because the type of identifier "iPressTheOkButtonInTheDialog" in "When.onTheMainPage.iPressTheOkButtonInTheDialog()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 24, + message: 'Unable to analyze this method call because the type of identifier "iShouldNotSeeTheHelloDialog" in "Then.onTheMainPage.iShouldNotSeeTheHelloDialog()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 27, + message: 'Unable to analyze this method call because the type of identifier "iTeardownMyApp" in "Then.iTeardownMyApp()"" could not be determined', + }, + { + category: 1, + column: 2, + line: 30, + message: `Unable to analyze this method call because the type of identifier in "opaTest("Should close the Hello dialog", function (Given, When, Then) {␊ + // Arrangements␊ + Given.iStartMyUIComponent({␊ + componentConfig: {␊ + name: "com.ui5.troublesome.app"␊ + }␊ + });␊ + // Actions␊ + When.onTheMainPage.iPressTheSayHelloButton();␊ + When.onTheMainPage.iPressTheOkButtonInTheDialog();␊ + // Assertions␊ + Then.onTheMainPage.iShouldNotSeeTheHelloDialog();␊ + // Cleanup␊ + Then.iTeardownMyApp();␊ + })"" could not be determined`, + }, + { + category: 1, + column: 3, + line: 32, + message: `Unable to analyze this method call because the type of identifier "iStartMyUIComponent" in "Given.iStartMyUIComponent({␊ + componentConfig: {␊ + name: "com.ui5.troublesome.app"␊ + }␊ + })"" could not be determined`, + }, + { + category: 1, + column: 3, + line: 39, + message: 'Unable to analyze this method call because the type of identifier "iPressTheSayHelloButton" in "When.onTheMainPage.iPressTheSayHelloButton()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 40, + message: 'Unable to analyze this method call because the type of identifier "iPressTheOkButtonInTheDialog" in "When.onTheMainPage.iPressTheOkButtonInTheDialog()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 43, + message: 'Unable to analyze this method call because the type of identifier "iShouldNotSeeTheHelloDialog" in "Then.onTheMainPage.iShouldNotSeeTheHelloDialog()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 46, + message: 'Unable to analyze this method call because the type of identifier "iTeardownMyApp" in "Then.iTeardownMyApp()"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/test/integration/HelloJourney.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'webapp/test/integration/opaTests.qunit.js', + messages: [ + { + column: 1, + fatal: undefined, + line: 4, + message: 'Call to deprecated function \'attachInit\' of class \'Core\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + fatal: undefined, + line: 4, + message: 'Call to deprecated function \'getCore\' (sap.ui.getCore)', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + fatal: undefined, + line: 4, + message: 'Access of global variable \'sap\' (sap.ui.getCore)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 13, + line: 8, + message: `Unable to analyze this method call because the type of identifier "waitFor" in "this.waitFor({␊ + id: "helloButton",␊ + viewName: "com.ui5.troublesome.app.view.Main",␊ + actions: new Press(),␊ + errorMessage: "Did not find the 'Say Hello With Dialog' button on the App view"␊ + })"" could not be determined`, + }, + { + category: 1, + column: 13, + line: 17, + message: `Unable to analyze this method call because the type of identifier "waitFor" in "this.waitFor({␊ + controlType: "sap.m.Button",␊ + searchOpenDialogs: true,␊ + viewName: "com.ui5.troublesome.app.view.Main",␊ + actions: new Press(),␊ + errorMessage: "Did not find the 'OK' button in the Dialog"␊ + })"" could not be determined`, + }, + { + category: 1, + column: 13, + line: 29, + message: `Unable to analyze this method call because the type of identifier "waitFor" in "this.waitFor({␊ + controlType: "sap.m.Dialog",␊ + success: function () {␊ + // we set the view busy, so we need to query the parent of the app␊ + Opa5.assert.ok(true, "The dialog is open");␊ + },␊ + errorMessage: "Did not find the dialog control"␊ + })"" could not be determined`, + }, + { + category: 1, + column: 13, + line: 40, + message: `Unable to analyze this method call because the type of identifier "waitFor" in "this.waitFor({␊ + controlType: "sap.m.App", // dummy, I just want a check function, where I can search the DOM. Probably there is a better way for a NEGATIVE test (NO dialog).␊ + check: function () {␊ + return document.querySelectorAll(".sapMDialog").length === 0;␊ + },␊ + success: function () {␊ + Opa5.assert.ok(true, "No dialog is open");␊ + }␊ + })"" could not be determined`, + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/test/integration/pages/Main.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 2, + line: 6, + message: 'Unable to analyze this method call because the type of identifier "addTestPage" in "suite.addTestPage(sContextPath + "unit/unitTests.qunit.html")"" could not be determined', + }, + { + category: 1, + column: 2, + line: 7, + message: 'Unable to analyze this method call because the type of identifier "addTestPage" in "suite.addTestPage(sContextPath + "integration/opaTests.qunit.html")"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/test/testsuite.qunit.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/test/unit/controller/App.qunit.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'webapp/test/unit/unitTests.qunit.js', + messages: [ + { + column: 1, + fatal: undefined, + line: 6, + message: 'Call to deprecated function \'attachInit\' of class \'Core\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + fatal: undefined, + line: 6, + message: 'Call to deprecated function \'getCore\' (sap.ui.getCore)', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 1, + fatal: undefined, + line: 6, + message: 'Access of global variable \'sap\' (sap.ui.getCore)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/view/App.view.xml', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'webapp/view/Main.view.xml', + messages: [ + { + column: 2, + fatal: undefined, + line: 11, + message: 'Import of deprecated module \'sap/m/MessagePage\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 5, + fatal: undefined, + line: 22, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## lint: Some files of com.ui5.troublesome.app + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'webapp/Component.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 33, + line: 8, + message: 'Unable to analyze this method call because the type of identifier "getContentDensityClass" in "this.getOwnerComponent().getContentDensityClass()"" could not be determined', + }, + ], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'webapp/controller/App.controller.js', + messages: [ + { + column: 4, + fatal: undefined, + line: 10, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 17, + line: 38, + message: 'Unable to analyze this method call because the type of identifier "getModel" in "this.getOwnerComponent().getModel("i18n")"" could not be determined', + }, + { + category: 1, + column: 11, + line: 39, + message: 'Unable to analyze this method call because the type of identifier "getResourceBundle" in "oModel.getResourceBundle()"" could not be determined', + }, + ], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'webapp/controller/BaseController.js', + messages: [ + { + column: 5, + fatal: undefined, + line: 9, + message: 'Use of deprecated property \'blocked\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 4, + fatal: undefined, + line: 11, + message: 'Call to deprecated function \'attachTap\' of class \'Button\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## lint: All files of library.with.custom.paths + +> Snapshot 1 + + [ + { + coverageInfo: [ + { + category: 1, + column: 5, + line: 61, + message: 'Unable to analyze this method call because the type of identifier "firePress" in "this.firePress()"" could not be determined', + }, + ], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'src/main/js/Example.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 3, + line: 29, + message: 'Unable to analyze this method call because the type of identifier "openStart" in "rm.openStart("div", control)"" could not be determined', + }, + { + category: 1, + column: 7, + line: 30, + message: 'Unable to analyze this method call because the type of identifier "getColor" in "control.getColor()"" could not be determined', + }, + { + category: 1, + column: 4, + line: 31, + message: 'Unable to analyze this method call because the type of identifier "class" in "rm.class("myLibPrefixExampleHighlight")"" could not be determined', + }, + { + category: 1, + column: 4, + line: 33, + message: 'Unable to analyze this method call because the type of identifier "class" in "rm.class("myLibPrefixExample")"" could not be determined', + }, + { + category: 1, + column: 3, + line: 35, + message: 'Unable to analyze this method call because the type of identifier "openEnd" in "rm.openEnd()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 36, + message: 'Unable to analyze this method call because the type of identifier "text" in "rm.text(i18n.getText("ANY_TEXT") + ": " + control.getText())"" could not be determined', + }, + { + category: 1, + column: 11, + line: 36, + message: 'Unable to analyze this method call because the type of identifier "getText" in "i18n.getText("ANY_TEXT")"" could not be determined', + }, + { + category: 1, + column: 45, + line: 36, + message: 'Unable to analyze this method call because the type of identifier "getText" in "control.getText()"" could not be determined', + }, + { + category: 1, + column: 3, + line: 37, + message: 'Unable to analyze this method call because the type of identifier "close" in "rm.close("div")"" could not be determined', + }, + ], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'src/main/js/ExampleRenderer.js', + messages: [ + { + column: 14, + fatal: undefined, + line: 27, + message: 'Call to deprecated function \'getLibraryResourceBundle\' of class \'Core\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'src/main/js/library.js', + messages: [ + { + column: 2, + fatal: undefined, + line: 15, + message: 'Call to deprecated function \'initLibrary\' of class \'Core\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 15, + message: 'Call to deprecated function \'getCore\' (sap.ui.getCore)', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 15, + message: 'Access of global variable \'sap\' (sap.ui.getCore)', + ruleId: 'ui5-linter-no-globals-js', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [ + { + category: 1, + column: 2, + line: 9, + message: `Unable to analyze this method call because the type of identifier "placeAt" in "new Example({␊ + text: "Example",␊ + color: ExampleColor.Highlight,␊ + press: function (event) {␊ + alert(event.getSource());␊ + }␊ + }).placeAt("content")"" could not be determined`, + }, + { + category: 1, + column: 10, + line: 13, + message: 'Unable to analyze this method call because the type of identifier "getSource" in "event.getSource()"" could not be determined', + }, + ], + errorCount: 1, + fatalErrorCount: 0, + filePath: 'src/test/js/Example.js', + messages: [ + { + column: 90, + fatal: undefined, + line: 1, + message: 'Import of deprecated module \'sap/ui/model/odata/ODataModel\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] diff --git a/test/lib/linter/snapshots/linter.ts.snap b/test/lib/linter/snapshots/linter.ts.snap new file mode 100644 index 000000000..994497e2d Binary files /dev/null and b/test/lib/linter/snapshots/linter.ts.snap differ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..c20e935f5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "include": ["src/**/*"], + "compilerOptions": { + "outDir": "./lib", + "moduleResolution": "node16", + "module": "node16", + "target": "es2022", + "lib": ["ES2022"], + "skipLibCheck": true, + "strict": true, + "sourceMap": true, + "allowJs": true, // required for JSTokenizer + }, + "typeAcquisition": { + // Ignore UI5 types, they are only required for linting + "exclude": ["@sapui5/types"] + } +}