├── .eslintrc.json
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── pull_request_template.md
└── workflows
│ ├── release-version.yml
│ └── vscode-extension-ci.yml
├── .gitignore
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── media
├── critical.svg
├── high.svg
├── informational.svg
├── low.svg
├── medium.svg
├── spectral-demo.gif
├── spectral.png
└── spectral.svg
├── package.json
├── resources
└── images
│ └── spectral.svg
├── spectral.config.json
├── src
├── common
│ ├── configuration.ts
│ ├── constants.ts
│ ├── persistence-context.ts
│ ├── spectral-utils.ts
│ ├── types.ts
│ ├── utils.ts
│ └── vs-code.ts
├── extension.ts
├── services
│ ├── analytics-service.ts
│ ├── context-service.ts
│ ├── logger-service.ts
│ ├── secret-storage-service.ts
│ └── spectral-agent-service.ts
├── spectral
│ ├── commands.ts
│ ├── extension.ts
│ ├── results-items.ts
│ ├── results-view-decorations.ts
│ └── results-view.ts
└── test
│ ├── mocks
│ └── scan-results.mock.ts
│ └── unit
│ └── services
│ └── spectral-agent-service.test.ts
├── tsconfig.json
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "parserOptions": {
4 | "parser": "@typescript-eslint/parser"
5 | },
6 | "extends": [
7 | "prettier"
8 | ],
9 | "plugins": [
10 | "@typescript-eslint",
11 | "prettier"
12 | ],
13 | "rules": {
14 | "arrow-parens": 2,
15 | "no-param-reassign": 0,
16 | "@typescript-eslint/ban-ts-ignore": 0,
17 | "import/extensions": 0,
18 | "@typescript-eslint/camelcase": 0,
19 | "@typescript-eslint/no-var-requires": 0,
20 | "@typescript-eslint/type-annotation-spacing": 0,
21 | "import/prefer-default-export": 0,
22 | "class-methods-use-this": 0,
23 | "@typescript-eslint/explicit-member-accessibility": 0,
24 | "@typescript-eslint/explicit-function-return-type": 0,
25 | "@typescript-eslint/member-delimiter-style": 0,
26 | "@typescript-eslint/no-unused-vars": [
27 | 2,
28 | {
29 | "argsIgnorePattern": "^_",
30 | "varsIgnorePattern": "^_"
31 | }
32 | ],
33 | "@typescript-eslint/indent": 0,
34 | "space-before-function-paren": 0,
35 | "comma-dangle": 0,
36 | "prettier/prettier": [
37 | 2,
38 | {
39 | "semi": false,
40 | "singleQuote": true,
41 | "arrowParens": "always",
42 | "trailingComma": "es5",
43 | "endOfLine": "auto"
44 | }
45 | ]
46 | },
47 | "env": {
48 | "es6": true
49 | }
50 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Expected Behavior
11 |
12 |
13 | ## Current Behavior
14 |
15 |
16 | ## Possible Solution
17 |
18 |
19 | ## Steps to Reproduce
20 |
21 | 1.
22 | 2.
23 | 3.
24 | 4.
25 |
26 | ## Context
27 |
28 |
29 | ## Specifications
30 | - Version: `$ vs code extension version`
31 | - Platform:
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Feature Request
11 |
12 | **Is your feature request related to a problem? Please describe.**
13 |
14 |
15 | **Describe the solution you'd like**
16 |
17 |
18 | **Describe alternatives you've considered**
19 |
20 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Related Issues
2 |
3 |
4 | ## Description
5 |
6 |
7 | ## Motivation and Context
8 |
9 |
10 |
11 | ## How Has This Been Tested?
12 |
13 |
14 |
15 |
16 | # Checklist
17 | - [ ] Tests
18 | - [ ] Documentation
19 | - [ ] Linting
20 | - [ ] Change log
--------------------------------------------------------------------------------
/.github/workflows/release-version.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | custom_tag:
7 | description: "If not patch specifiy release tag"
8 | required: false
9 |
10 | jobs:
11 | publish:
12 | runs-on: ubuntu-latest
13 | name: Publish extension
14 | outputs:
15 | new-version: ${{ steps.patched-tag.outputs.new_version }}
16 | new-tag: ${{ steps.patched-tag.outputs.new_tag }}
17 | steps:
18 | - uses: actions/checkout@v2
19 | - uses: actions/setup-node@v1
20 | with:
21 | node-version: 16
22 |
23 | - name: Install dependencies
24 | run: yarn
25 |
26 | - name: Bump version
27 | id: patched-tag
28 | uses: mathieudutour/github-tag-action@v6.0
29 | with:
30 | github_token: ${{ secrets.GITHUB_TOKEN }}
31 | release_branches: main
32 | default_bump: patch
33 | custom_tag: ${{ github.event.inputs.custom_tag }}
34 |
35 | - name: Update package.json version
36 | run: jq '.version = "${{ steps.patched-tag.outputs.new_version }}"' package.json > tmp.package.json && mv tmp.package.json package.json
37 |
38 | - name: Add Credentials
39 | uses: cschleiden/replace-tokens@v1
40 | with:
41 | tokenPrefix: '{'
42 | tokenSuffix: '}'
43 | files: 'spectral.config.json'
44 | env:
45 | BUILD_MIX_PANEL_KEY: ${{ secrets.MIX_PANEL_KEY }}
46 |
47 | - name: Build
48 | run: yarn vscode:prepublish
49 |
50 | - name: Setup VSCE
51 | run: yarn global add @vscode/vsce@2.21.0
52 |
53 | - name: Publish to Marketplace
54 | run: vsce publish -p ${{ secrets.MARKETPLACE_TOKEN }}
55 |
56 | release:
57 | runs-on: ubuntu-latest
58 | needs: publish
59 | environment: Stable
60 | name: Release
61 | steps:
62 | - name: Fetch sources
63 | uses: actions/checkout@v2
64 |
65 | - name: Install dependencies
66 | run: yarn
67 |
68 | - name: Setup VSCE
69 | run: yarn global add vsce@2.11.0
70 |
71 | - name: Package VSIX
72 | run: echo y | vsce package
73 |
74 | - name: Extract release notes
75 | id: extract-release-notes
76 | uses: ffurrer2/extract-release-notes@v1
77 |
78 | - name: Create release
79 | uses: softprops/action-gh-release@v1
80 | env:
81 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
82 | with:
83 | name: ${{ needs.publish.outputs.new-tag }}
84 | tag_name: ${{ needs.publish.outputs.new-tag }}
85 | body: "${{ steps.extract-release-notes.outputs.release_notes }}"
86 | draft: false
87 | prerelease: false
88 | fail_on_unmatched_files: true
89 | files: |
90 | **/*.vsix
91 |
--------------------------------------------------------------------------------
/.github/workflows/vscode-extension-ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | env:
4 | SPECTRAL_DSN: ${{ secrets.SPECTRAL_DSN }}
5 |
6 | on:
7 | push:
8 | jobs:
9 | spectral-scan:
10 | name: Spectral Scan
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: spectralops/spectral-github-action@v2
15 | with:
16 | spectral-dsn: ${{ secrets.SPECTRAL_DSN }}
17 | spectral-args: scan --include-tags base,iac
18 | code-analysis:
19 | runs-on: ubuntu-latest
20 | container:
21 | image: sourceguard/sourceguard-cli
22 | steps:
23 | - name: SourceGuard Scan
24 | uses: CheckPointSW/sourceguard-action@v1.0.0
25 | continue-on-error: false
26 | with:
27 | SG_CLIENT_ID: ${{ secrets.SG_CLIENT_ID }}
28 | SG_SECRET_KEY: ${{ secrets.SG_SECRET_KEY }}
29 | - name: Detect done
30 | run: echo done
31 | tests:
32 | name: Tests
33 | runs-on: ubuntu-latest
34 | steps:
35 | - uses: actions/checkout@v2
36 | - run: yarn && yarn test:unit
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out/
2 | node_modules/
3 | .vscode-test/
4 | *.vsix
5 | tmp/
6 | yarn-error.log
7 | .dccache
8 | .DS_Store
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "dbaeumer.vscode-eslint"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "args": [
13 | "--extensionDevelopmentPath=${workspaceFolder}"
14 | ],
15 | "outFiles": [
16 | "${workspaceFolder}/out/**/*.js"
17 | ],
18 | "preLaunchTask": "${defaultBuildTask}"
19 | },
20 | {
21 | "name": "Extension Tests",
22 | "type": "extensionHost",
23 | "request": "launch",
24 | "args": [
25 | "--extensionDevelopmentPath=${workspaceFolder}",
26 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
27 | ],
28 | "outFiles": [
29 | "${workspaceFolder}/out/test/**/*.js"
30 | ],
31 | "preLaunchTask": "${defaultBuildTask}"
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10 | "typescript.tsc.autoDetect": "off"
11 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": "$tsc-watch",
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/test/**
4 | node_modules/**
5 |
6 | src/**
7 | .gitignore
8 | .yarnrc
9 | tsconfig.json
10 | .eslintrc.json
11 |
12 | README.md
13 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # SpectralOps - Automated Code Security Change Log
2 | ## [1.1.2]
3 |
4 | - Fix Spectral installtion notification bug
5 | ## [1.1.1]
6 |
7 | - Install Spectral from the extension
8 | - Auto update Spectral
9 | ## [1.1.0]
10 |
11 | - Support user configuration for 'engines' and 'includesTags' flags
12 | - Support OSS scanning
13 |
14 | ## [1.0.18]
15 |
16 | - Remove the usage of --ok flag
17 | - Reset issues before scanning workspace folders
18 | - fix action button bug
19 |
20 | ## [1.0.14]
21 |
22 | - Support spectral yaml
23 |
24 | ## [1.0.8]
25 |
26 | - Analytics event added
27 |
28 | ## [1.0.7]
29 |
30 | - initial release
31 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to the SpectralOps VS code extension
2 |
3 | SpectralOps VS code extension is open source and we love to receive contributions from our community — you!
4 |
5 | There are many ways to contribute,
6 | from writing tutorials or blog posts,
7 | improving the documentation,
8 | submitting bug reports and feature requests or writing code.
9 | feedback and ideas are always welcome.
10 |
11 | ## Code contributions
12 |
13 | If you have a bugfix or new feature that you would like to contribute,
14 | please find or open an issue about it first.
15 | Talk about what you would like to do.
16 | It may be that somebody is already working on it,
17 | or that there are particular issues that you should know about before implementing the change.
18 |
19 | ### Submitting your changes
20 |
21 | Generally, we require that you test any code you are adding or modifying.
22 | Once your changes are ready , submit for review and we will make sure will review it , your effort is much appreciated!
23 |
24 | ### Workflow
25 |
26 | All feature development and most bug fixes hit the master branch first.
27 | Pull requests should be reviewed by someone with commit access.
28 | Once approved, the author of the pull request,
29 | or reviewer if the author does not have commit access,
30 | should "Squash and merge".
31 |
32 | ## Run extension and debug
33 |
34 | Clone the repository, then run `yarn` in the directory.
35 |
36 | - Open repository directory in VS Code run `yarn esbuild` and press `F5` to run extension in a new VS Code window.
37 | - This allows extension debugging within VS Code.
38 | - You can find output from your extension in the debug console and output channel.
39 |
40 | Please install all recommended extension that are suggested by VS Code when first opening the cloned directory. You can also do install them manually with the list of extensions defined in `.vscode/extensions.json`. This will ensure consistent formatting with the current codebase.
41 |
42 | ## Make changes
43 |
44 | Code changes require extension reload when run in debug.
45 |
46 | - You can relaunch the extension from the debug toolbar after changing code.
47 | - You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
48 |
49 | ## Run tests and debug
50 |
51 | - Unit tests
52 |
53 | - Run `yarn test:unit` for a single execution.
54 | - Make sure to re-run the command to pick up new files, if new `**.test.ts` is added.
55 |
56 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 SpectralOps
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | # Spectral VS Code extension
16 |
17 | The Spectral VS Code extension is a tool for developers that want to catch security issues (such as credentials, tokens and IaC misconfigurations) while still coding.
18 |
19 |
20 |
21 |
22 |
23 | ## What is Spectral?
24 |
25 | Monitor, classify, and protect your code, assets, and infrastructure for exposed API keys, tokens, credentials, and high-risk IaC security misconfigurations simply, without noise. Spectral comes with an industry's leading detector coverage with over 2500 different detectors built-in, including machine learning based detectors.
26 |
27 | What this means in the context of a developer, working in VS Code, is that while you write your code, we're actively scanning it to make sure you don't accidentally enter sensitive data, which can be used against you if breached.
28 |
29 | Spectral scans your code locally, sending only metadata back to our servers. No actual data (like credentials or tokens we may find) is transmitted outside your computer. This ensures we're never going to be a part of a supply-chain attack.
30 |
31 | Read more about our mission statement [here](https://spectralops.io/).
32 |
33 | ## Install the extension
34 |
35 | After you've installed the extension, you'll see a new icon in the activity bar.
36 |
37 | First, you'll now need to download Spectral binary. Additionally, you'll need to fill in your Spectral DSN. The extension will guide you through those steps - read on to learn more.
38 |
39 | ## Configuration
40 |
41 | - Sign up and get your SpectralOps account [here.](https://get.spectralops.io/signup) If you already have an account, sign in and do the next step.
42 | - From Settings -> Organization, copy your DSN.
43 | - Set your DSN in the SpectralOps extension.
44 | - In the extension configuration set the engines you would like to run and tags to include.
45 |
46 | ## Usage
47 |
48 | - Open a workspace you wish to scan with the SpectralOps extension.
49 | - Click Scan now
50 | - Scan results should appear in the SpectralOps extension and your editor.
51 |
52 | #### Spectral DSN
53 |
54 | The Spectral DSN (Data Source Name) is your personal key to communicate with Spectral. While the extension does not transmit data to our servers, you still need a DSN for Spectral to operate.
55 |
56 | #### Spectral binary
57 |
58 | This extension requires the Spectral binary to be present and available. You can install it from the extension or by following the instructions in our docs. The extension will automatically update Spectral agent, if you wish to disable it you can do it from the extension configuration.
59 |
60 | ### How to Contribute
61 |
62 | We welcome [issues](https://github.com/SpectralOps/vscode-extension/issues) to and [pull requests](https://github.com/SpectralOps/vscode-extension/pulls) against this repository!
63 |
64 | ## License
65 |
66 | This project is licensed under the MIT License. See [LICENSE](LICENSE) for further details.
67 |
68 |
69 |
--------------------------------------------------------------------------------
/media/critical.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/media/high.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/media/informational.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/media/low.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/media/medium.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/media/spectral-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SpectralOps/vscode-extension/f4e1ed7b1f363b8bcbfc9db69ef88b618a36c0f9/media/spectral-demo.gif
--------------------------------------------------------------------------------
/media/spectral.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SpectralOps/vscode-extension/f4e1ed7b1f363b8bcbfc9db69ef88b618a36c0f9/media/spectral.png
--------------------------------------------------------------------------------
/media/spectral.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spectral-checkpoint-vscode-extension",
3 | "displayName": "SpectralOps - A CheckPoint Solution",
4 | "description": "Monitor your code for exposed API keys, tokens, credentials, and high-risk security misconfigurations",
5 | "version": "1.1.2",
6 | "publisher": "CheckPoint",
7 | "icon": "media/spectral.png",
8 | "homepage": "https://spectralops.io/",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/SpectralOps/vscode-extension"
12 | },
13 | "engines": {
14 | "vscode": "^1.59.0"
15 | },
16 | "license": "MIT",
17 | "categories": [
18 | "Linters",
19 | "Programming Languages",
20 | "Other"
21 | ],
22 | "keywords": [
23 | "Code Analysis",
24 | "JavaScript",
25 | "Java",
26 | "TypeScript",
27 | "ts",
28 | "Vue",
29 | "Angular",
30 | "React",
31 | "Static Code Analysis",
32 | "Code security",
33 | "Python"
34 | ],
35 | "activationEvents": [
36 | "onStartupFinished"
37 | ],
38 | "main": "./out/extension.js",
39 | "types": "./out/extension.d.ts",
40 | "contributes": {
41 | "commands": [
42 | {
43 | "command": "spectral.scan",
44 | "title": "Spectral scan",
45 | "icon": "$(refresh)",
46 | "category": "Spectral"
47 | },
48 | {
49 | "command": "spectral.install",
50 | "title": "Install Spectral"
51 | },
52 | {
53 | "command": "spectral.showOutput",
54 | "title": "Show Output Channel"
55 | },
56 | {
57 | "command": "spectral.setDsn",
58 | "title": "Spectral Set DSN",
59 | "icon": "$(settings-gear)",
60 | "category": "Spectral"
61 | }
62 | ],
63 | "viewsContainers": {
64 | "activitybar": [
65 | {
66 | "id": "spectral",
67 | "title": "Spectral",
68 | "icon": "media/spectral.svg"
69 | }
70 | ]
71 | },
72 | "views": {
73 | "spectral": [
74 | {
75 | "id": "spectral.views.welcome",
76 | "name": "Spectral",
77 | "when": "spectral:preScan && !spectral:scanState"
78 | },
79 | {
80 | "id": "spectral.views.scanState",
81 | "name": "",
82 | "when": "spectral:scanState && spectral:scanState == 'failed' || spectral:scanState == 'inProgress' && spectral:preScan"
83 | },
84 | {
85 | "id": "spectral.views.secrets",
86 | "name": "Secrets",
87 | "when": "spectral:scanState == 'success' || spectral:scanState == 'inProgress' && !spectral:preScan"
88 | },
89 | {
90 | "id": "spectral.views.iac",
91 | "name": "IaC",
92 | "when": "spectral:scanState == 'success' || spectral:scanState == 'inProgress' && !spectral:preScan"
93 | },
94 | {
95 | "id": "spectral.views.oss",
96 | "name": "Open Source",
97 | "when": "spectral:scanState == 'success' || spectral:scanState == 'inProgress' && !spectral:preScan"
98 | }
99 | ]
100 | },
101 | "viewsWelcome": [
102 | {
103 | "view": "spectral.views.welcome",
104 | "contents": "Welcome to Spectral for Visual Studio Code. \nOpen a workspace or a folder to start scanning by clicking on the button below to perform a scan on your workspace. \n[Scan now](command:spectral.scan)\n",
105 | "when": "spectral:hasSpectralInstalled && spectral:hasDsn || spectral:hasLicense"
106 | },
107 | {
108 | "view": "spectral.views.welcome",
109 | "contents": "Welcome to Spectral for Visual Studio Code. We noticed that Spectral is not installed on your machine. \n[Install Spectral](command:spectral.install)\n \nYou can also refer to our docs for more details on [how to install Spectral manually](https://guides.spectralops.io/docs/how-to-get-started)",
110 | "when": "!spectral:hasSpectralInstalled"
111 | },
112 | {
113 | "view": "spectral.views.welcome",
114 | "contents": "Welcome to Spectral for Visual Studio Code.\n Grab your Spectral DSN from SpectralOps platform and set it here: \n [Set DSN](command:spectral.setDsn)\n",
115 | "when": "!spectral:hasDsn && !spectral:hasLicense && spectral:hasSpectralInstalled"
116 | },
117 | {
118 | "view": "spectral.views.scanState",
119 | "contents": "Something went wrong, please refer to output for more details. \n [Show Output Channel](command:spectral.showOutput)\n",
120 | "when": "spectral:scanState == 'failed'"
121 | },
122 | {
123 | "view": "spectral.views.scanState",
124 | "contents": "Spectral is performing a scan on your workspace",
125 | "when": "spectral:scanState == 'inProgress' && spectral:preScan"
126 | }
127 | ],
128 | "menus": {
129 | "view/title": [
130 | {
131 | "command": "spectral.scan",
132 | "when": "view == spectral.views.secrets || view == spectral.views.scanState",
133 | "group": "navigation"
134 | },
135 | {
136 | "command": "spectral.setDsn",
137 | "when": "view == spectral.views.secrets || view == spectral.views.welcome || view == spectral.views.scanState && spectral:hasSpectralInstalled || spectral:hasLicense",
138 | "group": "navigation"
139 | }
140 | ],
141 | "commandPalette": [
142 | {
143 | "command": "spectral.scan",
144 | "when": "spectral:hasSpectralInstalled && spectral:hasDsn || spectral:hasLicense"
145 | },
146 | {
147 | "command": "spectral.setDsn",
148 | "when": "spectral:hasSpectralInstalled"
149 | }
150 | ]
151 | },
152 | "configuration": {
153 | "type": "object",
154 | "title": "Spectral",
155 | "properties": {
156 | "spectral.scan.engines.useSecretsEngine": {
157 | "type": "boolean",
158 | "default": true,
159 | "description": "Scan for secrets",
160 | "scope": "window"
161 | },
162 | "spectral.scan.engines.useIacEngine": {
163 | "type": "boolean",
164 | "default": false,
165 | "description": "Scan for infrastructure as code",
166 | "scope": "window"
167 | },
168 | "spectral.scan.engines.useOssEngine": {
169 | "type": "boolean",
170 | "default": false,
171 | "description": "Scan open source packages",
172 | "scope": "window"
173 | },
174 | "spectral.scan.includeTags": {
175 | "type": "array",
176 | "items": {
177 | "type": "string"
178 | },
179 | "maxItems": 100,
180 | "default": [],
181 | "description": "Scan include tags",
182 | "scope": "window"
183 | },
184 | "spectral.install.autoUpdate": {
185 | "type": "boolean",
186 | "default": true,
187 | "description": "Auto update Spectral agent",
188 | "scope": "window"
189 | }
190 | }
191 | }
192 | },
193 | "scripts": {
194 | "vscode:prepublish": "yarn esbuild-base --minify",
195 | "esbuild-base": "rimraf out && esbuild ./src/extension.ts --bundle --outfile=out/extension.js --external:vscode --format=cjs --platform=node",
196 | "esbuild": "yarn esbuild-base --sourcemap",
197 | "esbuild-watch": "yarn esbuild-base --sourcemap --watch",
198 | "build": "rimraf out && tsc -p ./",
199 | "pretest": "yarn run build && yarn run lint",
200 | "lint": "eslint src --ext ts",
201 | "test:unit": "yarn build && mocha --ui tdd -c 'out/src/test/unit/**/*.test.js'",
202 | "test:integration": "node ./out/test/integration/runTest.js"
203 | },
204 | "devDependencies": {
205 | "@types/glob": "^7.1.3",
206 | "@types/lodash": "^4.14.184",
207 | "@types/mocha": "8.2.2",
208 | "@types/node": "14.x",
209 | "@types/vscode": "^1.59.0",
210 | "@typescript-eslint/eslint-plugin": "^5.37.0",
211 | "@typescript-eslint/parser": "^4.26.0",
212 | "esbuild": "^0.15.7",
213 | "eslint": "^8.44.0",
214 | "eslint-config-prettier": "^8.5.0",
215 | "eslint-plugin-prettier": "^4.2.1",
216 | "glob": "^7.1.7",
217 | "mocha": "^10.0.0",
218 | "prettier": "^2.7.1",
219 | "rimraf": "^3.0.2",
220 | "typescript": "^4.3.2"
221 | },
222 | "dependencies": {
223 | "lodash": "^4.17.21",
224 | "mixpanel": "^0.17.0"
225 | }
226 | }
--------------------------------------------------------------------------------
/resources/images/spectral.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
9 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/spectral.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "mixPanelKey": "{BUILD_MIX_PANEL_KEY}"
3 | }
--------------------------------------------------------------------------------
/src/common/configuration.ts:
--------------------------------------------------------------------------------
1 | import { WorkspaceConfiguration } from 'vscode'
2 | import {
3 | AUTO_UPDATE_SETTINGS,
4 | CONFIGURATION_IDENTIFIER,
5 | INCLUDE_TAGS_SETTING,
6 | ScanEngine,
7 | USE_IAC_ENGINE_SETTING,
8 | USE_OSS_ENGINE_SETTING,
9 | USE_SECRET_ENGINE_SETTING,
10 | } from './constants'
11 |
12 | export class Configuration {
13 | private extensionConfig: WorkspaceConfiguration
14 | static instance: Configuration
15 | constructor(workspace) {
16 | this.extensionConfig = workspace.getConfiguration(CONFIGURATION_IDENTIFIER)
17 | }
18 |
19 | public static getInstance(workspace?) {
20 | if (!this.instance) {
21 | this.instance = new Configuration(workspace)
22 | }
23 | return this.instance
24 | }
25 |
26 | get engines() {
27 | const engines = []
28 | const useSecretsEngine = this.extensionConfig.get(
29 | USE_SECRET_ENGINE_SETTING
30 | )
31 | if (useSecretsEngine) {
32 | engines.push(ScanEngine.secrets)
33 | }
34 | const useIacEngine = this.extensionConfig.get(
35 | USE_IAC_ENGINE_SETTING
36 | )
37 | if (useIacEngine) {
38 | engines.push(ScanEngine.iac)
39 | }
40 | const useOssEngine = this.extensionConfig.get(
41 | USE_OSS_ENGINE_SETTING
42 | )
43 | if (useOssEngine) {
44 | engines.push(ScanEngine.oss)
45 | }
46 | return engines.join(',')
47 | }
48 |
49 | get includeTags() {
50 | return this.extensionConfig
51 | .get>(INCLUDE_TAGS_SETTING, [])
52 | .join(',')
53 | }
54 |
55 | get isAutoUpdateEnabled() {
56 | return this.extensionConfig.get(AUTO_UPDATE_SETTINGS)
57 | }
58 |
59 | public updateConfiguration = (workspace) => {
60 | const extensionConfig = workspace.getConfiguration(CONFIGURATION_IDENTIFIER)
61 | this.extensionConfig = extensionConfig
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/common/constants.ts:
--------------------------------------------------------------------------------
1 | export const SPECTRAL_SCAN = 'spectral.scan'
2 | export const SPECTRAL_INSTALL = 'spectral.install'
3 | export const SPECTRAL_SHOW_OUTPUT = 'spectral.showOutput'
4 | export const SPECTRAL_SET_DSN = 'spectral.setDsn'
5 | export const CONTEXT_PREFIX = 'spectral:'
6 | export const HAS_SPECTRAL_INSTALLED = 'hasSpectralInstalled'
7 | export const HAS_DSN = 'hasDsn'
8 | export const HAS_LICENSE = 'hasLicense'
9 | export const SCAN_STATE = 'scanState'
10 | export const ENABLE_INSTALL_AGENT = 'enableInstallAgent'
11 | export const PRE_SCAN = 'preScan'
12 | export const SPECTRAL_VIEW_SECRETS = 'spectral.views.secrets'
13 | export const SPECTRAL_VIEW_IAC = 'spectral.views.iac'
14 | export const SPECTRAL_VIEW_OSS = 'spectral.views.oss'
15 |
16 | export enum ScanState {
17 | preScan = 'preScan',
18 | inProgress = 'inProgress',
19 | success = 'success',
20 | failed = 'failed',
21 | }
22 |
23 | export enum FindingSeverity {
24 | error = 'error',
25 | warning = 'warning',
26 | info = 'info',
27 | critical = 'critical',
28 | high = 'high',
29 | medium = 'medium',
30 | low = 'low',
31 | informational = 'informational',
32 | }
33 |
34 | export enum FindingSeverityLevel {
35 | critical = 1,
36 | high = 2,
37 | medium = 3,
38 | low = 4,
39 | informational = 5,
40 | }
41 |
42 | export enum FindingType {
43 | secret = 'secret',
44 | iac = 'iac',
45 | oss = 'oss',
46 | }
47 |
48 | export enum ScanEngine {
49 | secrets = 'secrets',
50 | iac = 'iac',
51 | oss = 'oss',
52 | }
53 |
54 | export const severityMapping = {
55 | [FindingSeverity.error]: FindingSeverity.high,
56 | [FindingSeverity.warning]: FindingSeverity.medium,
57 | [FindingSeverity.info]: FindingSeverity.informational,
58 | }
59 |
60 | export const SPECTRAL_FOLDER = `${process.env.HOME}/.spectral`
61 | export const SPECTRAL_DSN = 'SPECTRAL_DSN'
62 | export const FINDING_POSITION_LINE_INDEX = 0
63 | export const FINDING_POSITION_COL_INDEX = 1
64 | export const SPECTRAL_BASE_URL = 'https://get.spectralops.io'
65 | export const PLAYBOOKS_URL = `${SPECTRAL_BASE_URL}/api/v1/issues/playbooks`
66 | export const AGENT_LAST_UPDATE_DATE = 'spectral.agentLastUpdateDate'
67 | export const CONFIGURATION_IDENTIFIER = 'spectral'
68 | export const USE_IAC_ENGINE_SETTING = 'scan.engines.useIacEngine'
69 | export const USE_OSS_ENGINE_SETTING = 'scan.engines.useOssEngine'
70 | export const USE_SECRET_ENGINE_SETTING = 'scan.engines.useSecretsEngine'
71 | export const INCLUDE_TAGS_SETTING = 'scan.includeTags'
72 | export const AUTO_UPDATE_SETTINGS = 'install.autoUpdate'
73 |
--------------------------------------------------------------------------------
/src/common/persistence-context.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode'
2 |
3 | export class PersistenceContext {
4 | private context?: vscode.ExtensionContext
5 | private static instance: PersistenceContext
6 |
7 | public static getInstance() {
8 | if (!this.instance) {
9 | this.instance = new PersistenceContext()
10 | }
11 |
12 | return this.instance
13 | }
14 |
15 | setContext(context: vscode.ExtensionContext): void {
16 | this.context = context
17 | }
18 |
19 | getGlobalStateValue(key: string): T | undefined {
20 | return this.acquireContext().globalState.get(key)
21 | }
22 |
23 | updateGlobalStateValue(key: string, value: unknown): Thenable {
24 | return this.acquireContext().globalState.update(key, value)
25 | }
26 |
27 | private acquireContext(): vscode.ExtensionContext {
28 | if (!this.context) throw new Error('VS Code extension context not set.')
29 | return this.context
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/common/spectral-utils.ts:
--------------------------------------------------------------------------------
1 | import { Configuration } from './configuration'
2 | import { AGENT_LAST_UPDATE_DATE } from './constants'
3 | import { PersistenceContext } from './persistence-context'
4 |
5 | export const shouldUpdateSpectralAgent = (): boolean => {
6 | return (
7 | isOverUpdateThreshold() && Configuration.getInstance().isAutoUpdateEnabled
8 | )
9 | }
10 |
11 | const isOverUpdateThreshold = (): boolean => {
12 | const lastUpdateDate =
13 | PersistenceContext.getInstance().getGlobalStateValue(
14 | AGENT_LAST_UPDATE_DATE
15 | )
16 | if (!lastUpdateDate) {
17 | return true
18 | }
19 | const oneWeekInMs = 7 * 24 * 3600 * 1000
20 | return Date.now() - lastUpdateDate > oneWeekInMs
21 | }
22 |
--------------------------------------------------------------------------------
/src/common/types.ts:
--------------------------------------------------------------------------------
1 | import { FindingSeverity, FindingType } from './constants'
2 |
3 | export type LogLevel = 'Info' | 'Warn' | 'Error' | 'Debug'
4 | export type Findings = Record
5 |
6 | export type FindingsTypeResults = Record>
7 |
8 | export type FindingsAggregations = Record
9 |
10 | export type ScanResult = {
11 | items: Array
12 | }
13 |
14 | export interface ScanFinding {
15 | finding: string
16 | rule: Rule
17 | position: FindingPosition
18 | metadata: FindingMetadata
19 | }
20 |
21 | export interface ScanFindingView extends ScanFinding {
22 | rootPath: string
23 | labelDisplayName: string
24 | }
25 |
26 | type FindingMetadata = {
27 | tags: Array
28 | }
29 |
30 | export type Rule = {
31 | id: string
32 | name: string
33 | description: string
34 | severity: FindingSeverity
35 | }
36 |
37 | type FindingPosition = {
38 | start: Array
39 | end: Array
40 | }
41 |
--------------------------------------------------------------------------------
/src/common/utils.ts:
--------------------------------------------------------------------------------
1 | export const formatWindowsPath = (path: string): string => {
2 | const stringToReplace = new RegExp(/\\/, 'g')
3 | return `/${path.replace(stringToReplace, '/')}`
4 | }
5 |
6 | export const isWindows = (): boolean => process.platform === 'win32'
7 |
--------------------------------------------------------------------------------
/src/common/vs-code.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Diagnostic,
3 | DiagnosticSeverity,
4 | DiagnosticCollection,
5 | languages,
6 | DecorationRenderOptions,
7 | TextEditorDecorationType,
8 | window,
9 | TreeDataProvider,
10 | TreeView,
11 | StatusBarItem,
12 | StatusBarAlignment,
13 | Uri,
14 | workspace,
15 | Range,
16 | commands,
17 | } from 'vscode'
18 | import {
19 | CONTEXT_PREFIX,
20 | FindingSeverity,
21 | FINDING_POSITION_COL_INDEX,
22 | FINDING_POSITION_LINE_INDEX,
23 | PLAYBOOKS_URL,
24 | } from './constants'
25 | import { Findings, ScanFinding, ScanFindingView } from './types'
26 |
27 | export const setContext = (key: string, value: any): void => {
28 | commands.executeCommand('setContext', `${CONTEXT_PREFIX}${key}`, value)
29 | }
30 |
31 | export const getActiveTextEditor = () => window.activeTextEditor
32 |
33 | export const createTextDecoration = (
34 | options: DecorationRenderOptions
35 | ): TextEditorDecorationType => window.createTextEditorDecorationType(options)
36 |
37 | export const ShowNotificationMessage = ({
38 | messageType,
39 | messageText,
40 | items = [],
41 | }: {
42 | messageType: 'error' | 'warning' | 'info'
43 | messageText: string
44 | items?: Array
45 | }): Thenable => {
46 | switch (messageType) {
47 | case 'error':
48 | return window.showErrorMessage(messageText, ...items)
49 | case 'warning':
50 | return window.showWarningMessage(messageText, ...items)
51 | case 'info':
52 | return window.showInformationMessage(messageText, ...items)
53 | default:
54 | return window.showInformationMessage(messageText, ...items)
55 | }
56 | }
57 |
58 | type TreeOptions = {
59 | treeDataProvider: TreeDataProvider
60 | }
61 |
62 | export const createTree = ({
63 | viewId,
64 | options,
65 | }: {
66 | viewId: string
67 | options: TreeOptions
68 | }): TreeView => {
69 | return window.createTreeView(viewId, options)
70 | }
71 |
72 | type StatusBarSettings = {
73 | location: 'right' | 'left'
74 | //The larger the number the more left the item will be
75 | priority: number
76 | text: string
77 | tooltip: string
78 | }
79 |
80 | export const createStatusBarItem = (
81 | settings: StatusBarSettings
82 | ): StatusBarItem => {
83 | const item = window.createStatusBarItem(
84 | settings.location == 'right'
85 | ? StatusBarAlignment.Right
86 | : StatusBarAlignment.Left,
87 | settings.priority
88 | )
89 |
90 | item.text = settings.text
91 | if (settings.tooltip) {
92 | item.tooltip = settings.tooltip
93 | }
94 | return item
95 | }
96 |
97 | export const runWithLoaderOnView = async ({
98 | viewId,
99 | action,
100 | }: {
101 | viewId: string
102 | action: () => Promise
103 | }) => {
104 | await window.withProgress(
105 | {
106 | location: { viewId },
107 | },
108 | async () => {
109 | await action()
110 | }
111 | )
112 | }
113 |
114 | type InputBoxOptions = {
115 | password: boolean
116 | placeHolder: string
117 | title: string
118 | }
119 |
120 | export const showInputBox = (
121 | options: InputBoxOptions,
122 | task: (value) => Promise,
123 | inputValidation?: (value) => boolean,
124 | validationMessage?: string
125 | ) => {
126 | window
127 | .showInputBox({
128 | password: options.password,
129 | placeHolder: options.placeHolder,
130 | title: options.title,
131 | validateInput(value) {
132 | if (inputValidation) {
133 | const isValid = inputValidation(value)
134 | if (!isValid) {
135 | return validationMessage
136 | }
137 | }
138 | return null
139 | },
140 | })
141 | .then(async (value) => {
142 | if (value) {
143 | await task(value)
144 | }
145 | })
146 | }
147 |
148 | const severityToDiagnosticSeverity = {
149 | [FindingSeverity.critical]: DiagnosticSeverity.Error,
150 | [FindingSeverity.high]: DiagnosticSeverity.Error,
151 | [FindingSeverity.medium]: DiagnosticSeverity.Warning,
152 | [FindingSeverity.low]: DiagnosticSeverity.Warning,
153 | [FindingSeverity.informational]: DiagnosticSeverity.Information,
154 | }
155 |
156 | export const appendFindingsToProblemsChannel = (
157 | findings: Findings
158 | ): DiagnosticCollection => {
159 | const collection = languages.createDiagnosticCollection('Spectral')
160 |
161 | const diagnosticItemsPerFile = Object.values(findings).reduce(
162 | (acc: Record, findingTypeItems) => {
163 | Object.entries(findingTypeItems).forEach(
164 | ([filePath, items]: [string, ScanFindingView[]]) => {
165 | const diagnosticItems = items.map((item: ScanFindingView) => {
166 | const diagnostic = createDiagnosticItem(item)
167 | diagnostic.code = {
168 | value: `Spectral ${item.rule.id}`,
169 | target: Uri.parse(`${PLAYBOOKS_URL}/${item.rule.id}`),
170 | }
171 | return diagnostic
172 | })
173 |
174 | if (acc[filePath]) {
175 | acc[filePath] = [...acc[filePath], ...diagnosticItems]
176 | } else {
177 | acc[filePath] = diagnosticItems
178 | }
179 | }
180 | )
181 | return acc
182 | },
183 | {}
184 | )
185 |
186 | const diagnosticCollection: Array<[Uri, Array]> = Object.entries(
187 | diagnosticItemsPerFile
188 | ).map(([filePath, diagnosticItems]) => [Uri.file(filePath), diagnosticItems])
189 |
190 | collection.set(diagnosticCollection)
191 | return collection
192 | }
193 |
194 | const createDiagnosticItem = (finding: ScanFindingView): Diagnostic => {
195 | return new Diagnostic(
196 | getFindingRange(finding),
197 | `${finding.rule.name} - ${finding.rule.description}`,
198 | severityToDiagnosticSeverity[finding.rule.severity]
199 | )
200 | }
201 |
202 | export const getWorkspaceFolders = (): Array =>
203 | workspace.workspaceFolders?.map((folder) => folder.uri.fsPath) || []
204 |
205 | export const getFindingRange = (finding: ScanFinding): Range => {
206 | const startRow = finding.position?.start[FINDING_POSITION_LINE_INDEX] || 0
207 | const startCol = finding.position?.start[FINDING_POSITION_COL_INDEX] || 0
208 | const endRow = finding.position?.end[FINDING_POSITION_LINE_INDEX] || 0
209 | const endCol = finding.position?.end[FINDING_POSITION_COL_INDEX] || 0
210 | const startLine = startRow > 0 ? startRow - 1 : 1
211 | const startChar = startCol <= 1 ? startCol : startCol - 1
212 | const endLine = endRow > 0 ? endRow - 1 : 1
213 | const endChar = endCol <= 1 ? endCol + 3 : endCol - 1
214 | return finding.position
215 | ? new Range(startLine, startChar, endLine, endChar)
216 | : null
217 | }
218 |
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode'
2 | import { SpectralExtension } from './spectral/extension'
3 |
4 | const extension = new SpectralExtension()
5 |
6 | export function activate(context: vscode.ExtensionContext): void {
7 | console.log('Activating Spectral extension')
8 | extension.activate(context)
9 | }
10 | export function deactivate(): void {
11 | console.log('Deactivating Spectral extension')
12 | }
13 |
--------------------------------------------------------------------------------
/src/services/analytics-service.ts:
--------------------------------------------------------------------------------
1 | import { LoggerService } from './logger-service'
2 | import Mixpanel from 'mixpanel'
3 | import spectralConfig from '../../spectral.config.json'
4 |
5 | export class AnalyticsService {
6 | private static mixpanel: Mixpanel.Mixpanel
7 | static init(): void {
8 | const logger = LoggerService.getInstance()
9 | try {
10 | if (!spectralConfig.mixPanelKey) {
11 | logger.warn('Analytics service not initialized - key not provided')
12 | return
13 | }
14 |
15 | this.mixpanel = Mixpanel.init(spectralConfig.mixPanelKey)
16 | } catch (error) {
17 | logger.warn(`Analytics service not initialized - ${error}`)
18 | }
19 | }
20 |
21 | static track(eventName: string, eventProperties: any = null): void {
22 | const logger = LoggerService.getInstance()
23 | try {
24 | this.mixpanel.track(eventName, eventProperties)
25 | } catch (error) {
26 | logger.warn(`Analytics service event not tracked - ${error}`)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/services/context-service.ts:
--------------------------------------------------------------------------------
1 | import { SCAN_STATE } from '../common/constants'
2 | import { setContext } from '../common/vs-code'
3 |
4 | export class ContextService {
5 | private readonly viewContext: { [key: string]: any }
6 | private static instance: ContextService
7 | constructor() {
8 | this.viewContext = {}
9 | }
10 |
11 | public static getInstance() {
12 | if (!this.instance) {
13 | this.instance = new ContextService()
14 | }
15 |
16 | return this.instance
17 | }
18 |
19 | public getContext(key: string): any {
20 | return this.viewContext[key]
21 | }
22 |
23 | public setContext(key: string, value: any): void {
24 | this.viewContext[key] = value
25 | setContext(key, value)
26 | }
27 |
28 | get scanState(): string {
29 | return this.viewContext[SCAN_STATE]
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/services/logger-service.ts:
--------------------------------------------------------------------------------
1 | import { OutputChannel, window } from 'vscode'
2 | import { LogLevel } from '../common/types'
3 |
4 | export class LoggerService {
5 | private output: OutputChannel
6 | private static instance: LoggerService
7 |
8 | public static getInstance() {
9 | if (!this.instance) {
10 | this.instance = new LoggerService()
11 | }
12 |
13 | return this.instance
14 | }
15 |
16 | constructor() {
17 | this.output = window.createOutputChannel('Spectral')
18 | }
19 |
20 | info(message: string): void {
21 | this.log('Info', message)
22 | }
23 |
24 | warn(message: string): void {
25 | this.log('Warn', message)
26 | }
27 |
28 | error(message: string): void {
29 | this.log('Error', message)
30 | }
31 |
32 | debug(message: string): void {
33 | this.log('Debug', message)
34 | }
35 |
36 | log(level: LogLevel, message: string): void {
37 | if (level == 'Debug') {
38 | return console.log(message)
39 | }
40 |
41 | this.output.appendLine(`[${level}] ${message}`)
42 | }
43 |
44 | showOutput() {
45 | this.output.show()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/services/secret-storage-service.ts:
--------------------------------------------------------------------------------
1 | import { SecretStorage, ExtensionContext } from 'vscode'
2 |
3 | export default class SecretStorageService {
4 | private static instance: SecretStorageService
5 | constructor(private secretStorage: SecretStorage) {}
6 | static init(context: ExtensionContext): void {
7 | SecretStorageService.instance = new SecretStorageService(context.secrets)
8 | }
9 |
10 | static getInstance(): SecretStorageService {
11 | return SecretStorageService.instance
12 | }
13 |
14 | get(key: string): Promise {
15 | return this.secretStorage.get(key) as Promise
16 | }
17 |
18 | store(key: string, value: string): void {
19 | this.secretStorage.store(key, value) as Promise
20 | }
21 |
22 | delete(key: string): Promise {
23 | return this.secretStorage.delete(key) as Promise
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/services/spectral-agent-service.ts:
--------------------------------------------------------------------------------
1 | import { spawn } from 'child_process'
2 | import { readFileSync, unlinkSync } from 'fs'
3 | import isEmpty from 'lodash/isEmpty'
4 | import path from 'path'
5 | import {
6 | FindingSeverity,
7 | FindingType,
8 | severityMapping,
9 | SPECTRAL_BASE_URL,
10 | SPECTRAL_DSN,
11 | SPECTRAL_FOLDER,
12 | } from '../common/constants'
13 | import {
14 | Findings,
15 | FindingsAggregations,
16 | ScanFindingView,
17 | ScanResult,
18 | } from '../common/types'
19 | import { formatWindowsPath, isWindows } from '../common/utils'
20 | import SecretStorageService from './secret-storage-service'
21 | import { Configuration } from '../common/configuration'
22 |
23 | export class SpectralAgentService {
24 | public findings: Findings
25 | public findingsAggregations: FindingsAggregations
26 |
27 | constructor() {
28 | this.resetFindings()
29 | }
30 |
31 | public installSpectral(): Promise {
32 | return new Promise((resolve, reject) => {
33 | let child
34 | let command
35 | if (isWindows()) {
36 | command = `iwr ${SPECTRAL_BASE_URL}/latest/ps1 -useb | iex`
37 | child = spawn('powershell.exe', [command])
38 | } else {
39 | command = `curl -L '${SPECTRAL_BASE_URL}/latest/x/sh' | sh`
40 | child = spawn('/bin/sh', ['-c', command])
41 | }
42 |
43 | child.stderr.setEncoding('utf8')
44 | const stdOut: string[] = []
45 | const stderrChunks: string[] = []
46 | child.stdout.on('data', (data) => {
47 | stdOut.push(data.toString('utf8'))
48 | })
49 | child.stderr.on('data', (chunk) => {
50 | return stderrChunks.push(chunk)
51 | })
52 | child.on('error', async (err) => {
53 | reject(err)
54 | })
55 | child.on('close', (code) => {
56 | if (!isEmpty(stderrChunks) && code !== 0) {
57 | const error = stderrChunks.join('')
58 | return reject(error)
59 | }
60 | return resolve('')
61 | })
62 | })
63 | }
64 |
65 | public checkForSpectralBinary(): Promise {
66 | return new Promise((resolve) => {
67 | const child = spawn(this.getSpectralPath(), ['--nobanners', 'version'], {
68 | cwd: process.env.home,
69 | })
70 | child.on('error', () => {
71 | resolve(false)
72 | })
73 | child.on('close', (code) => {
74 | return resolve(code === 0)
75 | })
76 | })
77 | }
78 |
79 | public scan(scanPath: string): Promise {
80 | return new Promise(async (resolve, reject) => {
81 | const dsn = await SecretStorageService.getInstance().get(SPECTRAL_DSN)
82 | const outputFileName = 'output.txt'
83 | const spectralArgs = [
84 | '--nobanners',
85 | 'scan',
86 | '--nosend',
87 | '--internal-output',
88 | outputFileName,
89 | ]
90 | const options: any = {
91 | cwd: scanPath,
92 | }
93 | const engines = Configuration.getInstance().engines
94 | if (!isEmpty(engines)) {
95 | spectralArgs.push('--engines', engines)
96 | }
97 | const tags = Configuration.getInstance().includeTags
98 | if (!isEmpty(tags)) {
99 | spectralArgs.push('--include-tags', tags)
100 | }
101 | if (isWindows()) {
102 | spectralArgs.push('--dsn', dsn)
103 | } else {
104 | options.env = { ...process.env, [SPECTRAL_DSN]: dsn }
105 | }
106 |
107 | const child = spawn(this.getSpectralPath(), spectralArgs, options)
108 |
109 | child.stderr.setEncoding('utf8')
110 | const stderrChunks: string[] = []
111 | const stdOut: string[] = []
112 | child.stdout.on('data', (data) => {
113 | stdOut.push(data.toString('utf8'))
114 | })
115 | child.stderr.on('data', (chunk) => {
116 | return stderrChunks.push(chunk)
117 | })
118 | child.on('error', async (err) => {
119 | return reject(err)
120 | })
121 | child.on('close', async () => {
122 | if (!isEmpty(stderrChunks)) {
123 | const agentError = stderrChunks.join('')
124 | return reject(agentError)
125 | }
126 | try {
127 | const filePath = path.join(scanPath, outputFileName)
128 | const result = readFileSync(filePath, { encoding: 'utf8' })
129 | unlinkSync(filePath)
130 | const jsonOutput = JSON.parse(result)
131 | return resolve(jsonOutput)
132 | } catch (err) {
133 | return reject(err)
134 | }
135 | })
136 | })
137 | }
138 |
139 | public processResults(results: ScanResult, folderPath: string) {
140 | results?.items?.forEach((item: ScanFindingView) => {
141 | this.processFindingItem({ item, folderPath: folderPath.toLowerCase() })
142 | })
143 | }
144 |
145 | public resetFindings() {
146 | this.findings = Object.values(FindingType).reduce((acc, key) => {
147 | acc[key] = {}
148 | return acc
149 | }, {} as Findings)
150 | this.findingsAggregations = Object.values(FindingType).reduce(
151 | (acc, key) => {
152 | acc[key] = 0
153 | return acc
154 | },
155 | {} as FindingsAggregations
156 | )
157 | }
158 |
159 | private processFindingItem({
160 | item,
161 | folderPath,
162 | }: {
163 | item: ScanFindingView
164 | folderPath: string
165 | }): void {
166 | item.rootPath = folderPath
167 |
168 | if (isWindows()) {
169 | item.rootPath = formatWindowsPath(folderPath)
170 | item.finding = formatWindowsPath(item.finding.replace('\\\\?\\', ''))
171 | }
172 |
173 | item.rule.severity = this.mapToNewSeverity(item.rule.severity)
174 | item.finding = item.finding.toLowerCase()
175 | item.labelDisplayName = item.rule.name
176 |
177 | this.findingsAggregations[item.rule.severity] += 1
178 | const isIac = item.metadata.tags.includes(FindingType.iac)
179 | const isOss = item.metadata.tags.includes(FindingType.oss)
180 |
181 | let findingTypeResults
182 | if (isIac) {
183 | findingTypeResults = this.findings[FindingType.iac]
184 | this.findingsAggregations[FindingType.iac] += 1
185 | } else if (isOss) {
186 | item.labelDisplayName = `${item.rule.name} - ${item.rule.id}`
187 | findingTypeResults = this.findings[FindingType.oss]
188 | this.findingsAggregations[FindingType.oss] += 1
189 | } else {
190 | findingTypeResults = this.findings[FindingType.secret]
191 | this.findingsAggregations[FindingType.secret] += 1
192 | }
193 |
194 | if (!findingTypeResults[item.finding]) {
195 | findingTypeResults[item.finding] = []
196 | }
197 |
198 | findingTypeResults[item.finding].push(item)
199 | }
200 |
201 | private getSpectralPath(): string {
202 | if (isWindows()) {
203 | return 'spectral'
204 | }
205 |
206 | return `${SPECTRAL_FOLDER}/spectral`
207 | }
208 |
209 | private mapToNewSeverity(itemSeverity: FindingSeverity): FindingSeverity {
210 | if (severityMapping[itemSeverity]) {
211 | return severityMapping[itemSeverity]
212 | } else {
213 | return itemSeverity
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/src/spectral/commands.ts:
--------------------------------------------------------------------------------
1 | import { ContextService } from '../services/context-service'
2 | import { SpectralAgentService } from '../services/spectral-agent-service'
3 | import { updateFindingsDecorations } from './results-view-decorations'
4 | import {
5 | AGENT_LAST_UPDATE_DATE,
6 | ENABLE_INSTALL_AGENT,
7 | HAS_DSN,
8 | HAS_SPECTRAL_INSTALLED,
9 | PRE_SCAN,
10 | SCAN_STATE,
11 | } from '../common/constants'
12 | import { SPECTRAL_VIEW_SECRETS } from '../common/constants'
13 | import {
14 | createStatusBarItem,
15 | getActiveTextEditor,
16 | runWithLoaderOnView,
17 | showInputBox,
18 | ShowNotificationMessage,
19 | } from '../common/vs-code'
20 | import { ScanResult } from '../common/types'
21 | import { ScanState, SPECTRAL_DSN } from '../common/constants'
22 | import { LoggerService } from '../services/logger-service'
23 | import { ResultsView } from './results-view'
24 | import SecretStorageService from '../services/secret-storage-service'
25 | import { AnalyticsService } from '../services/analytics-service'
26 | import { PersistenceContext } from '../common/persistence-context'
27 |
28 | export const setDsn = () => {
29 | showInputBox(
30 | {
31 | password: true,
32 | placeHolder: 'https://spu-XXXXXXXXXXXXX@XXXXXX',
33 | title: 'Spectral DSN',
34 | },
35 | storeDsn,
36 | (value: string) => {
37 | const regex =
38 | /^https:\/\/spu-[a-zA-Z0-9]{32}@([a-zA-Z0-9_-]+\.)+[a-zA-Z]+$/
39 | return regex.test(value)
40 | },
41 | 'DSN structure is invalid'
42 | )
43 | }
44 |
45 | export const scanWorkSpaceFolders = async ({
46 | foldersPath,
47 | spectralAgentService,
48 | resultsView,
49 | }: {
50 | foldersPath: Array
51 | spectralAgentService: SpectralAgentService
52 | resultsView: ResultsView
53 | }): Promise => {
54 | const contextService = ContextService.getInstance()
55 | const logger = LoggerService.getInstance()
56 | const inProgressStatusBarItem = createStatusBarItem({
57 | location: 'right',
58 | priority: 1,
59 | text: `$(loading~spin)`,
60 | tooltip: 'Spectral is scanning',
61 | })
62 | contextService.setContext(SCAN_STATE, ScanState.inProgress)
63 | logger.debug('Scan start')
64 | AnalyticsService.track('vscode-scan')
65 | inProgressStatusBarItem.show()
66 | try {
67 | spectralAgentService.resetFindings()
68 | await runWithLoaderOnView({
69 | viewId: SPECTRAL_VIEW_SECRETS,
70 | action: () =>
71 | scanWorkspaces({ spectralAgentService, foldersPath, logger }),
72 | })
73 | } catch (error) {
74 | contextService.setContext(SCAN_STATE, 'failed')
75 | inProgressStatusBarItem.dispose()
76 | logger.error(error)
77 | ShowNotificationMessage({
78 | messageType: 'error',
79 | messageText: `Scan failed`,
80 | items: ['See output'],
81 | }).then(() => logger.showOutput())
82 | return
83 | }
84 |
85 | contextService.setContext(SCAN_STATE, ScanState.success)
86 | logger.debug('Scan finished')
87 | contextService.setContext(PRE_SCAN, false)
88 |
89 | inProgressStatusBarItem.dispose()
90 |
91 | resultsView.refresh({
92 | findings: spectralAgentService.findings,
93 | findingsAggregations: spectralAgentService.findingsAggregations,
94 | })
95 |
96 | updateFindingsDecorations(
97 | getActiveTextEditor(),
98 | spectralAgentService.findings
99 | )
100 | }
101 |
102 | export const setupSpectral = async (
103 | spectralAgentService: SpectralAgentService
104 | ): Promise => {
105 | const inProgressStatusBarItem = createStatusBarItem({
106 | location: 'right',
107 | priority: 1,
108 | text: `$(loading~spin)`,
109 | tooltip: 'Installing Spectral',
110 | })
111 | const contextService = ContextService.getInstance()
112 | try {
113 | contextService.setContext(ENABLE_INSTALL_AGENT, false)
114 | inProgressStatusBarItem.show()
115 | ShowNotificationMessage({
116 | messageType: 'info',
117 | messageText: `Spectral installation is in progress`,
118 | })
119 | await spectralAgentService.installSpectral()
120 | inProgressStatusBarItem.dispose()
121 | contextService.setContext(HAS_SPECTRAL_INSTALLED, true)
122 | const extensionContext = PersistenceContext.getInstance()
123 | extensionContext.updateGlobalStateValue(AGENT_LAST_UPDATE_DATE, Date.now())
124 | } catch (error) {
125 | inProgressStatusBarItem.dispose()
126 | const logger = LoggerService.getInstance()
127 | logger.error(error)
128 | ShowNotificationMessage({
129 | messageType: 'error',
130 | messageText: `Spectral installation failed`,
131 | items: ['See output'],
132 | }).then(() => logger.showOutput())
133 | }
134 | ShowNotificationMessage({
135 | messageType: 'info',
136 | messageText: `Spectral installation completed`,
137 | })
138 | }
139 |
140 | const scanWorkspaces = async ({
141 | spectralAgentService,
142 | foldersPath,
143 | logger,
144 | }: {
145 | spectralAgentService: SpectralAgentService
146 | foldersPath: Array
147 | logger: LoggerService
148 | }) => {
149 | await Promise.all(
150 | foldersPath.map(async (folderPath) => {
151 | logger.debug(`Scanning workspace folder: ${folderPath}`)
152 | const results: ScanResult = await spectralAgentService.scan(folderPath)
153 | logger.debug(`Found: ${results.items.length} findings`)
154 | spectralAgentService.processResults(results, folderPath)
155 | })
156 | )
157 | }
158 |
159 | const storeDsn = async (dsn: string): Promise => {
160 | const secretStorageService = SecretStorageService.getInstance()
161 | secretStorageService.store(SPECTRAL_DSN, dsn)
162 | const contextService = ContextService.getInstance()
163 | contextService.setContext(HAS_DSN, true)
164 | }
165 |
--------------------------------------------------------------------------------
/src/spectral/extension.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ExtensionContext,
3 | commands,
4 | window,
5 | workspace,
6 | WorkspaceFoldersChangeEvent,
7 | TextEditor,
8 | ConfigurationChangeEvent,
9 | } from 'vscode'
10 | import {
11 | ENABLE_INSTALL_AGENT,
12 | SPECTRAL_INSTALL,
13 | CONFIGURATION_IDENTIFIER,
14 | INCLUDE_TAGS_SETTING,
15 | SPECTRAL_SCAN,
16 | SPECTRAL_SET_DSN,
17 | SPECTRAL_SHOW_OUTPUT,
18 | USE_IAC_ENGINE_SETTING,
19 | USE_OSS_ENGINE_SETTING,
20 | USE_SECRET_ENGINE_SETTING,
21 | } from '../common/constants'
22 | import {
23 | HAS_DSN,
24 | PRE_SCAN,
25 | HAS_SPECTRAL_INSTALLED,
26 | HAS_LICENSE,
27 | } from '../common/constants'
28 | import { ContextService } from '../services/context-service'
29 | import { SpectralAgentService } from '../services/spectral-agent-service'
30 | import { scanWorkSpaceFolders, setDsn, setupSpectral } from './commands'
31 | import concat from 'lodash/concat'
32 | import pullAll from 'lodash/pullAll'
33 | import { updateFindingsDecorations } from './results-view-decorations'
34 | import { SPECTRAL_DSN, SPECTRAL_FOLDER } from '../common/constants'
35 | import { accessSync } from 'fs'
36 | import path from 'path'
37 | import { LoggerService } from '../services/logger-service'
38 | import { ResultsView } from './results-view'
39 | import SecretStorageService from '../services/secret-storage-service'
40 | import { getWorkspaceFolders } from '../common/vs-code'
41 | import { AnalyticsService } from '../services/analytics-service'
42 | import { PersistenceContext } from '../common/persistence-context'
43 | import { Configuration } from '../common/configuration'
44 | import { shouldUpdateSpectralAgent } from '../common/spectral-utils'
45 |
46 | export class SpectralExtension {
47 | private workspaceFolders: Array = getWorkspaceFolders()
48 | private readonly contextService: ContextService
49 | private readonly persistenceContext: PersistenceContext
50 | private readonly logger: LoggerService
51 | private readonly configuration: Configuration
52 | private readonly spectralAgentService: SpectralAgentService
53 | private readonly resultsView: ResultsView
54 |
55 | constructor() {
56 | this.contextService = ContextService.getInstance()
57 | this.logger = LoggerService.getInstance()
58 | this.persistenceContext = PersistenceContext.getInstance()
59 | this.configuration = Configuration.getInstance(workspace)
60 | this.spectralAgentService = new SpectralAgentService()
61 | this.resultsView = new ResultsView()
62 | }
63 |
64 | public async activate(vsCodeContext: ExtensionContext): Promise {
65 | try {
66 | this.persistenceContext.setContext(vsCodeContext)
67 | this.initializeExtension(vsCodeContext)
68 | const isSpectralInstalled =
69 | await this.spectralAgentService.checkForSpectralBinary()
70 |
71 | this.setSpectralInstallationContext(isSpectralInstalled)
72 | if (isSpectralInstalled && shouldUpdateSpectralAgent()) {
73 | await setupSpectral(this.spectralAgentService)
74 | }
75 | AnalyticsService.init()
76 | } catch (error) {
77 | this.logger.error(error)
78 | }
79 | }
80 |
81 | private async initializeExtension(
82 | vsCodeContext: ExtensionContext
83 | ): Promise {
84 | SecretStorageService.init(vsCodeContext)
85 | this.contextService.setContext(PRE_SCAN, true)
86 | this.registerCommands(vsCodeContext)
87 | this.registerEvents()
88 | }
89 |
90 | public async setSpectralInstallationContext(
91 | isSpectralInstalled: Boolean
92 | ): Promise {
93 | this.contextService.setContext(ENABLE_INSTALL_AGENT, true)
94 | if (!isSpectralInstalled) {
95 | this.contextService.setContext(HAS_SPECTRAL_INSTALLED, false)
96 | return
97 | }
98 | this.contextService.setContext(HAS_SPECTRAL_INSTALLED, true)
99 | const secretStorageService = SecretStorageService.getInstance()
100 | const dsn = await secretStorageService.get(SPECTRAL_DSN)
101 | if (!dsn) {
102 | this.contextService.setContext(HAS_DSN, false)
103 | } else {
104 | this.contextService.setContext(HAS_DSN, true)
105 | }
106 | try {
107 | accessSync(path.join(`${SPECTRAL_FOLDER}/license`))
108 | this.contextService.setContext(HAS_LICENSE, true)
109 | } catch (error) {
110 | this.contextService.setContext(HAS_LICENSE, false)
111 | }
112 | }
113 |
114 | private registerCommands(vsCodeContext: ExtensionContext): void {
115 | vsCodeContext.subscriptions.push(
116 | commands.registerCommand(SPECTRAL_INSTALL, () =>
117 | setupSpectral(this.spectralAgentService)
118 | ),
119 | commands.registerCommand(SPECTRAL_SCAN, () =>
120 | scanWorkSpaceFolders({
121 | foldersPath: this.workspaceFolders,
122 | spectralAgentService: this.spectralAgentService,
123 | resultsView: this.resultsView,
124 | })
125 | ),
126 | commands.registerCommand(SPECTRAL_SHOW_OUTPUT, () =>
127 | this.logger.showOutput()
128 | ),
129 | commands.registerCommand(SPECTRAL_SET_DSN, async () => {
130 | setDsn()
131 | })
132 | )
133 | }
134 |
135 | private registerEvents(): void {
136 | workspace.onDidChangeWorkspaceFolders(
137 | (workspaceFoldersChangeEvent: WorkspaceFoldersChangeEvent) => {
138 | this.workspaceFolders = concat(
139 | this.workspaceFolders,
140 | workspaceFoldersChangeEvent.added.map((folder) => folder.uri.path)
141 | )
142 | pullAll(
143 | this.workspaceFolders,
144 | workspaceFoldersChangeEvent.removed.map((folder) => folder.uri.path)
145 | )
146 | }
147 | )
148 | window.onDidChangeActiveTextEditor((event: TextEditor | undefined) => {
149 | updateFindingsDecorations(event, this.spectralAgentService.findings)
150 | })
151 | workspace.onDidChangeConfiguration(
152 | async (event: ConfigurationChangeEvent): Promise => {
153 | const changed = [
154 | `${CONFIGURATION_IDENTIFIER}.${USE_SECRET_ENGINE_SETTING}`,
155 | `${CONFIGURATION_IDENTIFIER}.${USE_IAC_ENGINE_SETTING}`,
156 | `${CONFIGURATION_IDENTIFIER}.${USE_OSS_ENGINE_SETTING}`,
157 | `${CONFIGURATION_IDENTIFIER}.${INCLUDE_TAGS_SETTING}`,
158 | ].find((setting) => event.affectsConfiguration(setting))
159 | if (changed) {
160 | workspace.getConfiguration(CONFIGURATION_IDENTIFIER)
161 | this.configuration.updateConfiguration(workspace)
162 | }
163 | }
164 | )
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/spectral/results-items.ts:
--------------------------------------------------------------------------------
1 | import {
2 | TreeItem,
3 | TreeDataProvider,
4 | ProviderResult,
5 | TreeItemCollapsibleState,
6 | Uri,
7 | ThemeIcon,
8 | } from 'vscode'
9 | import L from 'lodash'
10 | import { basename, dirname, join } from 'path'
11 | import isEmpty from 'lodash/isEmpty'
12 | import { getFindingRange } from '../common/vs-code'
13 | import { FindingsTypeResults, ScanFindingView } from '../common/types'
14 | import { FindingSeverity, FindingSeverityLevel } from '../common/constants'
15 |
16 | export class FindingsProvider implements TreeDataProvider {
17 | private readonly findings: FindingsTypeResults
18 | constructor(findings: FindingsTypeResults) {
19 | this.findings = findings
20 | }
21 | getTreeItem(element: TreeItem): TreeItem | Thenable {
22 | return element
23 | }
24 | getChildren(element?: TreeItem): ProviderResult {
25 | if (!element) {
26 | if (!isEmpty(this.findings)) {
27 | return Promise.resolve(new WorkspaceItem(this.findings).fileNodes)
28 | } else {
29 | return Promise.resolve([
30 | new EmptyItem('Great job! no issues were found.'),
31 | ])
32 | }
33 | } else {
34 | return Promise.resolve((element).findingNodes)
35 | }
36 | }
37 | }
38 |
39 | export class WorkspaceItem extends TreeItem {
40 | fileNodes: Array
41 | constructor(findings: FindingsTypeResults) {
42 | super('', TreeItemCollapsibleState.Collapsed)
43 | this.fileNodes = this.getFilesNodes(findings)
44 | }
45 |
46 | private getFilesNodes(findings: FindingsTypeResults) {
47 | const orderedFindings = L(findings)
48 | .toPairs()
49 | .orderBy([0], ['asc'])
50 | .fromPairs()
51 | .value()
52 | return Object.entries(orderedFindings).map(
53 | ([filePath, fileFindings]: [string, Array]) => {
54 | const rootPath = fileFindings[0].rootPath
55 | const path = filePath.startsWith(rootPath)
56 | ? filePath.substring(rootPath.length)
57 | : filePath
58 | return new FileItem(path, fileFindings)
59 | }
60 | )
61 | }
62 | }
63 |
64 | export class FindingItem extends TreeItem {
65 | private iconsPath = {
66 | [FindingSeverity.critical]: join(
67 | __filename,
68 | '..',
69 | '..',
70 | 'media',
71 | 'critical.svg'
72 | ),
73 | [FindingSeverity.high]: join(__filename, '..', '..', 'media', 'high.svg'),
74 | [FindingSeverity.medium]: join(
75 | __filename,
76 | '..',
77 | '..',
78 | 'media',
79 | 'medium.svg'
80 | ),
81 | [FindingSeverity.low]: join(__filename, '..', '..', 'media', 'low.svg'),
82 | [FindingSeverity.informational]: join(
83 | __filename,
84 | '..',
85 | '..',
86 | 'media',
87 | 'informational.svg'
88 | ),
89 | }
90 | constructor(finding: ScanFindingView) {
91 | super(finding.labelDisplayName, TreeItemCollapsibleState.None)
92 | const findingPosition = getFindingRange(finding)
93 | this.tooltip = L.capitalize(finding.rule.severity)
94 | this.iconPath = {
95 | light: this.iconsPath[finding.rule.severity],
96 | dark: this.iconsPath[finding.rule.severity],
97 | }
98 | this.command = {
99 | title: 'Open',
100 | command: 'vscode.open',
101 | arguments: [Uri.parse(finding.finding), { selection: findingPosition }],
102 | }
103 | }
104 | }
105 |
106 | export class FileItem extends TreeItem {
107 | findingNodes: Array
108 |
109 | constructor(filePath: string, findings: Array) {
110 | super(basename(filePath), TreeItemCollapsibleState.Collapsed)
111 | this.resourceUri = Uri.file(filePath)
112 | this.iconPath = ThemeIcon.File
113 | this.description = dirname(filePath).substring(1)
114 | this.findingNodes = findings
115 | .sort((a, b) => {
116 | if (
117 | FindingSeverityLevel[a.rule.severity] <
118 | FindingSeverityLevel[b.rule.severity]
119 | ) {
120 | return -1
121 | }
122 | if (
123 | FindingSeverityLevel[a.rule.severity] >
124 | FindingSeverityLevel[b.rule.severity]
125 | ) {
126 | return 1
127 | }
128 | return 0
129 | })
130 | .map((finding) => new FindingItem(finding))
131 | }
132 | }
133 |
134 | export class EmptyItem extends TreeItem {
135 | constructor(message: string) {
136 | super(message, TreeItemCollapsibleState.None)
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/spectral/results-view-decorations.ts:
--------------------------------------------------------------------------------
1 | import { TextEditor, TextEditorDecorationType, OverviewRulerLane } from 'vscode'
2 | import { Findings, ScanFinding } from '../common/types'
3 | import { formatWindowsPath, isWindows } from '../common/utils'
4 | import { FindingSeverity, FindingType } from '../common/constants'
5 | import { createTextDecoration, getFindingRange } from '../common/vs-code'
6 | import concat from 'lodash/concat'
7 | import compact from 'lodash/compact'
8 | import isEmpty from 'lodash/isEmpty'
9 |
10 | export const updateFindingsDecorations = (
11 | editor: TextEditor | undefined,
12 | findings: Findings
13 | ) => {
14 | if (!editor) {
15 | return
16 | }
17 |
18 | const docFilePath = isWindows()
19 | ? formatWindowsPath(editor.document.fileName.toLowerCase())
20 | : editor.document.fileName.toLowerCase()
21 |
22 | const fileFindings: any = concat(
23 | findings[FindingType.secret][docFilePath],
24 | findings[FindingType.iac][docFilePath]
25 | )
26 |
27 | if (isEmpty(fileFindings)) {
28 | // clean all decorations from the current file, if any
29 | Object.keys(severityDecorationsColors).forEach(
30 | (severity: FindingSeverity) => {
31 | editor.setDecorations(createDecorationTypeBySeverity(severity), [])
32 | }
33 | )
34 | return
35 | }
36 |
37 | Object.keys(severityDecorationsColors).forEach(
38 | (severity: FindingSeverity) => {
39 | decorateBySeverity({
40 | editor,
41 | severity,
42 | fileFindings: compact(fileFindings),
43 | })
44 | }
45 | )
46 | }
47 |
48 | const decorateBySeverity = ({
49 | editor,
50 | severity,
51 | fileFindings,
52 | }: {
53 | editor: TextEditor
54 | severity: FindingSeverity
55 | fileFindings: Array
56 | }): void => {
57 | const findingsBySeverity: any = fileFindings.filter(
58 | (finding) => finding.rule.severity === severity
59 | )
60 |
61 | if (isEmpty(findingsBySeverity)) {
62 | return
63 | }
64 |
65 | const rangesToDecorate = findingsBySeverity
66 | .map((finding: ScanFinding) => {
67 | const findingPosition = getFindingRange(finding)
68 | return findingPosition
69 | ? {
70 | range: findingPosition,
71 | }
72 | : false
73 | })
74 | .filter(Boolean)
75 | editor.setDecorations(
76 | createDecorationTypeBySeverity(severity),
77 | rangesToDecorate
78 | )
79 | }
80 |
81 | const severityDecorationsColors = {
82 | [FindingSeverity.critical]: '#f24e4e',
83 | [FindingSeverity.high]: '#ff8000',
84 | [FindingSeverity.medium]: '#ffb72d',
85 | [FindingSeverity.low]: '#ffdb66',
86 | [FindingSeverity.informational]: '#80c3ff',
87 | }
88 |
89 | const createDecorationTypeBySeverity = (
90 | severity: FindingSeverity
91 | ): TextEditorDecorationType =>
92 | createTextDecoration({
93 | cursor: 'pointer',
94 | borderWidth: '0px 0px 1px 0px',
95 | borderStyle: 'solid',
96 | overviewRulerColor: severityDecorationsColors[severity],
97 | overviewRulerLane: OverviewRulerLane.Right,
98 | light: {
99 | borderColor: severityDecorationsColors[severity],
100 | },
101 | dark: {
102 | borderColor: severityDecorationsColors[severity],
103 | },
104 | })
105 |
--------------------------------------------------------------------------------
/src/spectral/results-view.ts:
--------------------------------------------------------------------------------
1 | import { DiagnosticCollection, TreeItem } from 'vscode'
2 | import gt from 'lodash/gt'
3 | import {
4 | appendFindingsToProblemsChannel,
5 | createTree,
6 | ShowNotificationMessage,
7 | } from '../common/vs-code'
8 | import {
9 | Findings,
10 | FindingsAggregations,
11 | FindingsTypeResults,
12 | } from '../common/types'
13 | import {
14 | SPECTRAL_VIEW_IAC,
15 | SPECTRAL_VIEW_OSS,
16 | SPECTRAL_VIEW_SECRETS,
17 | } from '../common/constants'
18 | import { FindingsProvider } from './results-items'
19 |
20 | export class ResultsView {
21 | private problemsCollection: DiagnosticCollection
22 |
23 | public refresh({
24 | findings,
25 | findingsAggregations,
26 | }: {
27 | findings: Findings
28 | findingsAggregations: FindingsAggregations
29 | }) {
30 | this.createResultsViews({
31 | results: findings.secret,
32 | viewId: SPECTRAL_VIEW_SECRETS,
33 | viewTitle: `Secrets (${findingsAggregations.secret})`,
34 | })
35 |
36 | this.createResultsViews({
37 | results: findings.iac,
38 | viewId: SPECTRAL_VIEW_IAC,
39 | viewTitle: `IaC (${findingsAggregations.iac})`,
40 | })
41 |
42 | this.createResultsViews({
43 | results: findings.oss,
44 | viewId: SPECTRAL_VIEW_OSS,
45 | viewTitle: `Open Source (${findingsAggregations.oss})`,
46 | })
47 |
48 | if (this.problemsCollection) {
49 | this.problemsCollection.clear()
50 | }
51 | this.problemsCollection = appendFindingsToProblemsChannel(findings)
52 |
53 | this.showResultNotification(findingsAggregations)
54 | }
55 |
56 | private createResultsViews({
57 | results,
58 | viewId,
59 | viewTitle,
60 | }: {
61 | results: FindingsTypeResults
62 | viewId: string
63 | viewTitle: string
64 | }): void {
65 | const findingsTree = createTree({
66 | viewId: viewId,
67 | options: {
68 | treeDataProvider: new FindingsProvider(results),
69 | },
70 | })
71 |
72 | findingsTree.title = viewTitle
73 | }
74 |
75 | private showResultNotification(
76 | findingsAggregations: FindingsAggregations
77 | ): void {
78 | if (gt(findingsAggregations.iac, 0) || gt(findingsAggregations.secret, 0)) {
79 | const totalFindings =
80 | findingsAggregations.iac + findingsAggregations.secret
81 |
82 | ShowNotificationMessage({
83 | messageType: 'info',
84 | messageText: `Scan finished. Found ${totalFindings} issue${
85 | totalFindings > 1 ? 's' : ''
86 | }`,
87 | })
88 | } else {
89 | ShowNotificationMessage({
90 | messageType: 'info',
91 | messageText: 'Great job! No issue were found',
92 | })
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/test/mocks/scan-results.mock.ts:
--------------------------------------------------------------------------------
1 | import { concat } from 'lodash'
2 | import { FindingSeverity } from '../../common/constants'
3 | import { ScanResult } from '../../common/types'
4 |
5 | export const scanSecretsSingleFinding: ScanResult = {
6 | items: [
7 | {
8 | finding: '/Users/testUser/git/vscode-extension/src/common/state.ts',
9 | position: {
10 | start: [1, 5],
11 | end: [1, 2],
12 | },
13 | rule: {
14 | id: 'CLD001',
15 | name: 'Visible AWS Key',
16 | severity: FindingSeverity.error,
17 | description: 'Found a visible AWS Key',
18 | },
19 | metadata: {
20 | tags: ['base', 'amazon'],
21 | },
22 | },
23 | ],
24 | }
25 |
26 | export const scanIacSingleFinding: ScanResult = {
27 | items: [
28 | {
29 | finding: '/Users/testUser/git/vscode-extension/src/common/state.ts',
30 | position: {
31 | start: [1, 5],
32 | end: [1, 2],
33 | },
34 | rule: {
35 | id: 'AZURE001',
36 | name: 'Missing email account admins for security alerts',
37 | severity: FindingSeverity.warning,
38 | description: 'Missing email account admins for security alerts',
39 | },
40 | metadata: {
41 | tags: ['azure', 'iac'],
42 | },
43 | },
44 | ],
45 | }
46 |
47 | export const scanOssSingleFinding: ScanResult = {
48 | items: [
49 | {
50 | finding: '/Users/testUser/git/vscode-extension/package-lock.json',
51 | position: {
52 | start: [1, 1],
53 | end: [1, 1],
54 | },
55 | rule: {
56 | id: 'CVE-2018-20834',
57 | name: 'CVE-2018-20834',
58 | severity: FindingSeverity.high,
59 | description:
60 | 'A vulnerability was found in node-tar before version 4.4.2 (excluding version 2.2.2). An Arbitrary File Overwrite issue exists when extracting a tarball containing a hardlink to a file that already exists on the system, in conjunction with a later plain file with the same name as the hardlink. This plain file content replaces the existing file content. A patch has been applied to node-tar v2.2.2).',
61 | },
62 | metadata: {
63 | tags: ['oss'],
64 | },
65 | },
66 | ],
67 | }
68 |
69 | export const scanSingleFindingEachType: ScanResult = {
70 | items: concat(
71 | scanSecretsSingleFinding.items,
72 | scanIacSingleFinding.items,
73 | scanOssSingleFinding.items
74 | ),
75 | }
76 |
77 | export const scanMultipleSecrets: ScanResult = {
78 | items: [
79 | {
80 | finding: '/Users/testUser/git/vscode-extension/src/common/state.ts',
81 | position: {
82 | start: [1, 5],
83 | end: [1, 2],
84 | },
85 | rule: {
86 | id: 'CLD001',
87 | name: 'Visible AWS Key',
88 | severity: FindingSeverity.error,
89 | description: 'Found a visible AWS Key',
90 | },
91 | metadata: {
92 | tags: ['base', 'amazon'],
93 | },
94 | },
95 | {
96 | finding:
97 | '/Users/testUser/git/vscode-extension/src/services/context-service.ts',
98 | position: {
99 | start: [1, 5],
100 | end: [1, 2],
101 | },
102 | rule: {
103 | id: 'CLD001',
104 | name: 'Visible AWS Key',
105 | severity: FindingSeverity.error,
106 | description: 'Found a visible AWS Key',
107 | },
108 | metadata: {
109 | tags: ['base', 'amazon'],
110 | },
111 | },
112 | ],
113 | }
114 |
--------------------------------------------------------------------------------
/src/test/unit/services/spectral-agent-service.test.ts:
--------------------------------------------------------------------------------
1 | import assert from 'assert'
2 | import { SpectralAgentService } from '../../../services/spectral-agent-service'
3 | import {
4 | scanIacSingleFinding,
5 | scanMultipleSecrets,
6 | scanOssSingleFinding,
7 | scanSecretsSingleFinding,
8 | scanSingleFindingEachType,
9 | } from '../../mocks/scan-results.mock'
10 |
11 | suite('Spectral agent service', () => {
12 | test('[ok] - process only secrets - aggregations should be as items length', () => {
13 | const spectralAgentService = new SpectralAgentService()
14 | spectralAgentService.processResults(scanSecretsSingleFinding, 'somePath')
15 | assert.strictEqual(
16 | spectralAgentService.findingsAggregations.secret,
17 | scanSecretsSingleFinding.items.length
18 | )
19 | })
20 |
21 | test('[ok] - process only iac - aggregations should be as items length', () => {
22 | const spectralAgentService = new SpectralAgentService()
23 | spectralAgentService.processResults(scanIacSingleFinding, 'somePath')
24 | assert.strictEqual(
25 | spectralAgentService.findingsAggregations.iac,
26 | scanIacSingleFinding.items.length
27 | )
28 | })
29 |
30 | test('[ok] - process only oss - aggregations should be as items length', () => {
31 | const spectralAgentService = new SpectralAgentService()
32 | spectralAgentService.processResults(scanOssSingleFinding, 'somePath')
33 | assert.strictEqual(
34 | spectralAgentService.findingsAggregations.oss,
35 | scanOssSingleFinding.items.length
36 | )
37 | })
38 |
39 | test('[ok] - process both finding types - aggregations should be as items length', () => {
40 | const spectralAgentService = new SpectralAgentService()
41 | spectralAgentService.processResults(scanSingleFindingEachType, 'somePath')
42 | const expectedIacItems = 1
43 | const expectedOssItems = 1
44 | const expectedSecretsItems = 1
45 | assert.strictEqual(
46 | spectralAgentService.findingsAggregations.iac,
47 | expectedIacItems,
48 | 'iac validation failed'
49 | )
50 | assert.strictEqual(
51 | spectralAgentService.findingsAggregations.oss,
52 | expectedOssItems,
53 | 'oss validation failed'
54 | )
55 | assert.strictEqual(
56 | spectralAgentService.findingsAggregations.secret,
57 | expectedSecretsItems,
58 | 'secrets validation failed'
59 | )
60 | })
61 |
62 | test('[ok] - process finding - findings should be aggregated by the finding path', () => {
63 | const spectralAgentService = new SpectralAgentService()
64 | spectralAgentService.processResults(scanSecretsSingleFinding, 'somePath')
65 | const findingKey = Object.keys(spectralAgentService.findings.secret)[0]
66 | assert.strictEqual(findingKey, scanSecretsSingleFinding.items[0].finding)
67 | })
68 |
69 | test('[ok] - process finding - different findings should be aggregated by different finding path', () => {
70 | const spectralAgentService = new SpectralAgentService()
71 | spectralAgentService.processResults(scanMultipleSecrets, 'somePath')
72 | const expectedKeys = 2
73 | const actualKeys = Object.keys(spectralAgentService.findings.secret).length
74 | assert.strictEqual(actualKeys, expectedKeys)
75 | })
76 | })
77 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noImplicitAny": false,
4 | "resolveJsonModule": true,
5 | "esModuleInterop": true,
6 | "module": "commonjs",
7 | "target": "es2017",
8 | "outDir": "out",
9 | "sourceMap": true,
10 | },
11 | "exclude": [
12 | "node_modules",
13 | ".vscode-test",
14 | ]
15 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@aashutoshrathi/word-wrap@^1.2.3":
6 | version "1.2.6"
7 | resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
8 | integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
9 |
10 | "@esbuild/linux-loong64@0.15.7":
11 | version "0.15.7"
12 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz#1ec4af4a16c554cbd402cc557ccdd874e3f7be53"
13 | integrity sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==
14 |
15 | "@eslint-community/eslint-utils@^4.2.0":
16 | version "4.4.0"
17 | resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
18 | integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
19 | dependencies:
20 | eslint-visitor-keys "^3.3.0"
21 |
22 | "@eslint-community/regexpp@^4.4.0":
23 | version "4.5.1"
24 | resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884"
25 | integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==
26 |
27 | "@eslint/eslintrc@^2.1.0":
28 | version "2.1.0"
29 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.0.tgz#82256f164cc9e0b59669efc19d57f8092706841d"
30 | integrity sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==
31 | dependencies:
32 | ajv "^6.12.4"
33 | debug "^4.3.2"
34 | espree "^9.6.0"
35 | globals "^13.19.0"
36 | ignore "^5.2.0"
37 | import-fresh "^3.2.1"
38 | js-yaml "^4.1.0"
39 | minimatch "^3.1.2"
40 | strip-json-comments "^3.1.1"
41 |
42 | "@eslint/js@8.44.0":
43 | version "8.44.0"
44 | resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.44.0.tgz#961a5903c74139390478bdc808bcde3fc45ab7af"
45 | integrity sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==
46 |
47 | "@humanwhocodes/config-array@^0.11.10":
48 | version "0.11.10"
49 | resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
50 | integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==
51 | dependencies:
52 | "@humanwhocodes/object-schema" "^1.2.1"
53 | debug "^4.1.1"
54 | minimatch "^3.0.5"
55 |
56 | "@humanwhocodes/module-importer@^1.0.1":
57 | version "1.0.1"
58 | resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
59 | integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
60 |
61 | "@humanwhocodes/object-schema@^1.2.1":
62 | version "1.2.1"
63 | resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
64 | integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
65 |
66 | "@nodelib/fs.scandir@2.1.5":
67 | version "2.1.5"
68 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
69 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
70 | dependencies:
71 | "@nodelib/fs.stat" "2.0.5"
72 | run-parallel "^1.1.9"
73 |
74 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
75 | version "2.0.5"
76 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
77 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
78 |
79 | "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
80 | version "1.2.8"
81 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
82 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
83 | dependencies:
84 | "@nodelib/fs.scandir" "2.1.5"
85 | fastq "^1.6.0"
86 |
87 | "@types/glob@^7.1.3":
88 | version "7.1.4"
89 | resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672"
90 | integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==
91 | dependencies:
92 | "@types/minimatch" "*"
93 | "@types/node" "*"
94 |
95 | "@types/json-schema@^7.0.9":
96 | version "7.0.11"
97 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
98 | integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
99 |
100 | "@types/lodash@^4.14.184":
101 | version "4.14.184"
102 | resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.184.tgz#23f96cd2a21a28e106dc24d825d4aa966de7a9fe"
103 | integrity sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==
104 |
105 | "@types/minimatch@*":
106 | version "3.0.5"
107 | resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
108 | integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
109 |
110 | "@types/mocha@8.2.2":
111 | version "8.2.2"
112 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.2.tgz#91daa226eb8c2ff261e6a8cbf8c7304641e095e0"
113 | integrity sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==
114 |
115 | "@types/node@*":
116 | version "16.6.1"
117 | resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.1.tgz#aee62c7b966f55fc66c7b6dfa1d58db2a616da61"
118 | integrity sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==
119 |
120 | "@types/node@14.x":
121 | version "14.17.9"
122 | resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.9.tgz#b97c057e6138adb7b720df2bd0264b03c9f504fd"
123 | integrity sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==
124 |
125 | "@types/vscode@^1.59.0":
126 | version "1.59.0"
127 | resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.59.0.tgz#11c93f5016926126bf30b47b9ece3bd617eeef31"
128 | integrity sha512-Zg38rusx2nU6gy6QdF7v4iqgxNfxzlBlDhrRCjOiPQp+sfaNrp3f9J6OHIhpGNN1oOAca4+9Hq0+8u3jwzPMlQ==
129 |
130 | "@typescript-eslint/eslint-plugin@^5.37.0":
131 | version "5.37.0"
132 | resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.37.0.tgz#5ccdd5d9004120f28fc6e717fb4b5c9bddcfbc04"
133 | integrity sha512-Fde6W0IafXktz1UlnhGkrrmnnGpAo1kyX7dnyHHVrmwJOn72Oqm3eYtddrpOwwel2W8PAK9F3pIL5S+lfoM0og==
134 | dependencies:
135 | "@typescript-eslint/scope-manager" "5.37.0"
136 | "@typescript-eslint/type-utils" "5.37.0"
137 | "@typescript-eslint/utils" "5.37.0"
138 | debug "^4.3.4"
139 | functional-red-black-tree "^1.0.1"
140 | ignore "^5.2.0"
141 | regexpp "^3.2.0"
142 | semver "^7.3.7"
143 | tsutils "^3.21.0"
144 |
145 | "@typescript-eslint/parser@^4.26.0":
146 | version "4.29.1"
147 | resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.1.tgz#17dfbb45c9032ffa0fe15881d20fbc2a4bdeb02d"
148 | integrity sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==
149 | dependencies:
150 | "@typescript-eslint/scope-manager" "4.29.1"
151 | "@typescript-eslint/types" "4.29.1"
152 | "@typescript-eslint/typescript-estree" "4.29.1"
153 | debug "^4.3.1"
154 |
155 | "@typescript-eslint/scope-manager@4.29.1":
156 | version "4.29.1"
157 | resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz#f25da25bc6512812efa2ce5ebd36619d68e61358"
158 | integrity sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==
159 | dependencies:
160 | "@typescript-eslint/types" "4.29.1"
161 | "@typescript-eslint/visitor-keys" "4.29.1"
162 |
163 | "@typescript-eslint/scope-manager@5.37.0":
164 | version "5.37.0"
165 | resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.37.0.tgz#044980e4f1516a774a418dafe701a483a6c9f9ca"
166 | integrity sha512-F67MqrmSXGd/eZnujjtkPgBQzgespu/iCZ+54Ok9X5tALb9L2v3G+QBSoWkXG0p3lcTJsL+iXz5eLUEdSiJU9Q==
167 | dependencies:
168 | "@typescript-eslint/types" "5.37.0"
169 | "@typescript-eslint/visitor-keys" "5.37.0"
170 |
171 | "@typescript-eslint/type-utils@5.37.0":
172 | version "5.37.0"
173 | resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.37.0.tgz#43ed2f567ada49d7e33a6e4b6f9babd060445fe5"
174 | integrity sha512-BSx/O0Z0SXOF5tY0bNTBcDEKz2Ec20GVYvq/H/XNKiUorUFilH7NPbFUuiiyzWaSdN3PA8JV0OvYx0gH/5aFAQ==
175 | dependencies:
176 | "@typescript-eslint/typescript-estree" "5.37.0"
177 | "@typescript-eslint/utils" "5.37.0"
178 | debug "^4.3.4"
179 | tsutils "^3.21.0"
180 |
181 | "@typescript-eslint/types@4.29.1":
182 | version "4.29.1"
183 | resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.1.tgz#94cce6cf7cc83451df03339cda99d326be2feaf5"
184 | integrity sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==
185 |
186 | "@typescript-eslint/types@5.37.0":
187 | version "5.37.0"
188 | resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.37.0.tgz#09e4870a5f3af7af3f84e08d792644a87d232261"
189 | integrity sha512-3frIJiTa5+tCb2iqR/bf7XwU20lnU05r/sgPJnRpwvfZaqCJBrl8Q/mw9vr3NrNdB/XtVyMA0eppRMMBqdJ1bA==
190 |
191 | "@typescript-eslint/typescript-estree@4.29.1":
192 | version "4.29.1"
193 | resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz#7b32a25ff8e51f2671ccc6b26cdbee3b1e6c5e7f"
194 | integrity sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==
195 | dependencies:
196 | "@typescript-eslint/types" "4.29.1"
197 | "@typescript-eslint/visitor-keys" "4.29.1"
198 | debug "^4.3.1"
199 | globby "^11.0.3"
200 | is-glob "^4.0.1"
201 | semver "^7.3.5"
202 | tsutils "^3.21.0"
203 |
204 | "@typescript-eslint/typescript-estree@5.37.0":
205 | version "5.37.0"
206 | resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.37.0.tgz#956dcf5c98363bcb97bdd5463a0a86072ff79355"
207 | integrity sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA==
208 | dependencies:
209 | "@typescript-eslint/types" "5.37.0"
210 | "@typescript-eslint/visitor-keys" "5.37.0"
211 | debug "^4.3.4"
212 | globby "^11.1.0"
213 | is-glob "^4.0.3"
214 | semver "^7.3.7"
215 | tsutils "^3.21.0"
216 |
217 | "@typescript-eslint/utils@5.37.0":
218 | version "5.37.0"
219 | resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.37.0.tgz#7784cb8e91390c4f90ccaffd24a0cf9874df81b2"
220 | integrity sha512-jUEJoQrWbZhmikbcWSMDuUSxEE7ID2W/QCV/uz10WtQqfOuKZUqFGjqLJ+qhDd17rjgp+QJPqTdPIBWwoob2NQ==
221 | dependencies:
222 | "@types/json-schema" "^7.0.9"
223 | "@typescript-eslint/scope-manager" "5.37.0"
224 | "@typescript-eslint/types" "5.37.0"
225 | "@typescript-eslint/typescript-estree" "5.37.0"
226 | eslint-scope "^5.1.1"
227 | eslint-utils "^3.0.0"
228 |
229 | "@typescript-eslint/visitor-keys@4.29.1":
230 | version "4.29.1"
231 | resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz#0615be8b55721f5e854f3ee99f1a714f2d093e5d"
232 | integrity sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==
233 | dependencies:
234 | "@typescript-eslint/types" "4.29.1"
235 | eslint-visitor-keys "^2.0.0"
236 |
237 | "@typescript-eslint/visitor-keys@5.37.0":
238 | version "5.37.0"
239 | resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.37.0.tgz#7b72dd343295ea11e89b624995abc7103c554eee"
240 | integrity sha512-Hp7rT4cENBPIzMwrlehLW/28EVCOcE9U1Z1BQTc8EA8v5qpr7GRGuG+U58V5tTY48zvUOA3KHvw3rA8tY9fbdA==
241 | dependencies:
242 | "@typescript-eslint/types" "5.37.0"
243 | eslint-visitor-keys "^3.3.0"
244 |
245 | "@ungap/promise-all-settled@1.1.2":
246 | version "1.1.2"
247 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
248 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
249 |
250 | acorn-jsx@^5.3.2:
251 | version "5.3.2"
252 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
253 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
254 |
255 | acorn@^8.9.0:
256 | version "8.10.0"
257 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
258 | integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
259 |
260 | agent-base@6:
261 | version "6.0.2"
262 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
263 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
264 | dependencies:
265 | debug "4"
266 |
267 | ajv@^6.10.0, ajv@^6.12.4:
268 | version "6.12.6"
269 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
270 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
271 | dependencies:
272 | fast-deep-equal "^3.1.1"
273 | fast-json-stable-stringify "^2.0.0"
274 | json-schema-traverse "^0.4.1"
275 | uri-js "^4.2.2"
276 |
277 | ansi-colors@4.1.1:
278 | version "4.1.1"
279 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
280 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
281 |
282 | ansi-regex@^5.0.0, ansi-regex@^5.0.1:
283 | version "5.0.1"
284 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
285 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
286 |
287 | ansi-styles@^4.0.0, ansi-styles@^4.1.0:
288 | version "4.3.0"
289 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
290 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
291 | dependencies:
292 | color-convert "^2.0.1"
293 |
294 | anymatch@~3.1.2:
295 | version "3.1.2"
296 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
297 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
298 | dependencies:
299 | normalize-path "^3.0.0"
300 | picomatch "^2.0.4"
301 |
302 | argparse@^2.0.1:
303 | version "2.0.1"
304 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
305 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
306 |
307 | array-union@^2.1.0:
308 | version "2.1.0"
309 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
310 | integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
311 |
312 | balanced-match@^1.0.0:
313 | version "1.0.2"
314 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
315 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
316 |
317 | binary-extensions@^2.0.0:
318 | version "2.2.0"
319 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
320 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
321 |
322 | brace-expansion@^1.1.7:
323 | version "1.1.11"
324 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
325 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
326 | dependencies:
327 | balanced-match "^1.0.0"
328 | concat-map "0.0.1"
329 |
330 | brace-expansion@^2.0.1:
331 | version "2.0.1"
332 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
333 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
334 | dependencies:
335 | balanced-match "^1.0.0"
336 |
337 | braces@^3.0.1, braces@~3.0.2:
338 | version "3.0.2"
339 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
340 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
341 | dependencies:
342 | fill-range "^7.0.1"
343 |
344 | browser-stdout@1.3.1:
345 | version "1.3.1"
346 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
347 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
348 |
349 | callsites@^3.0.0:
350 | version "3.1.0"
351 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
352 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
353 |
354 | camelcase@^6.0.0:
355 | version "6.3.0"
356 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
357 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
358 |
359 | chalk@^4.0.0, chalk@^4.1.0:
360 | version "4.1.2"
361 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
362 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
363 | dependencies:
364 | ansi-styles "^4.1.0"
365 | supports-color "^7.1.0"
366 |
367 | chokidar@3.5.3:
368 | version "3.5.3"
369 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
370 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
371 | dependencies:
372 | anymatch "~3.1.2"
373 | braces "~3.0.2"
374 | glob-parent "~5.1.2"
375 | is-binary-path "~2.1.0"
376 | is-glob "~4.0.1"
377 | normalize-path "~3.0.0"
378 | readdirp "~3.6.0"
379 | optionalDependencies:
380 | fsevents "~2.3.2"
381 |
382 | cliui@^7.0.2:
383 | version "7.0.4"
384 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
385 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
386 | dependencies:
387 | string-width "^4.2.0"
388 | strip-ansi "^6.0.0"
389 | wrap-ansi "^7.0.0"
390 |
391 | color-convert@^2.0.1:
392 | version "2.0.1"
393 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
394 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
395 | dependencies:
396 | color-name "~1.1.4"
397 |
398 | color-name@~1.1.4:
399 | version "1.1.4"
400 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
401 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
402 |
403 | concat-map@0.0.1:
404 | version "0.0.1"
405 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
406 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
407 |
408 | cross-spawn@^7.0.2:
409 | version "7.0.3"
410 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
411 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
412 | dependencies:
413 | path-key "^3.1.0"
414 | shebang-command "^2.0.0"
415 | which "^2.0.1"
416 |
417 | debug@4, debug@4.3.4, debug@^4.3.2, debug@^4.3.4:
418 | version "4.3.4"
419 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
420 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
421 | dependencies:
422 | ms "2.1.2"
423 |
424 | debug@^4.1.1, debug@^4.3.1:
425 | version "4.3.2"
426 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
427 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
428 | dependencies:
429 | ms "2.1.2"
430 |
431 | decamelize@^4.0.0:
432 | version "4.0.0"
433 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
434 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
435 |
436 | deep-is@^0.1.3:
437 | version "0.1.3"
438 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
439 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
440 |
441 | diff@5.0.0:
442 | version "5.0.0"
443 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
444 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
445 |
446 | dir-glob@^3.0.1:
447 | version "3.0.1"
448 | resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
449 | integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
450 | dependencies:
451 | path-type "^4.0.0"
452 |
453 | doctrine@^3.0.0:
454 | version "3.0.0"
455 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
456 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
457 | dependencies:
458 | esutils "^2.0.2"
459 |
460 | emoji-regex@^8.0.0:
461 | version "8.0.0"
462 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
463 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
464 |
465 | esbuild-android-64@0.15.7:
466 | version "0.15.7"
467 | resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz#a521604d8c4c6befc7affedc897df8ccde189bea"
468 | integrity sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==
469 |
470 | esbuild-android-arm64@0.15.7:
471 | version "0.15.7"
472 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz#307b81f1088bf1e81dfe5f3d1d63a2d2a2e3e68e"
473 | integrity sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==
474 |
475 | esbuild-darwin-64@0.15.7:
476 | version "0.15.7"
477 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz#270117b0c4ec6bcbc5cf3a297a7d11954f007e11"
478 | integrity sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==
479 |
480 | esbuild-darwin-arm64@0.15.7:
481 | version "0.15.7"
482 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz#97851eacd11dacb7719713602e3319e16202fc77"
483 | integrity sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==
484 |
485 | esbuild-freebsd-64@0.15.7:
486 | version "0.15.7"
487 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz#1de15ffaf5ae916aa925800aa6d02579960dd8c4"
488 | integrity sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==
489 |
490 | esbuild-freebsd-arm64@0.15.7:
491 | version "0.15.7"
492 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz#0f160dbf5c9a31a1d8dd87acbbcb1a04b7031594"
493 | integrity sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==
494 |
495 | esbuild-linux-32@0.15.7:
496 | version "0.15.7"
497 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz#422eb853370a5e40bdce8b39525380de11ccadec"
498 | integrity sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==
499 |
500 | esbuild-linux-64@0.15.7:
501 | version "0.15.7"
502 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz#f89c468453bb3194b14f19dc32e0b99612e81d2b"
503 | integrity sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==
504 |
505 | esbuild-linux-arm64@0.15.7:
506 | version "0.15.7"
507 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz#68a79d6eb5e032efb9168a0f340ccfd33d6350a1"
508 | integrity sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==
509 |
510 | esbuild-linux-arm@0.15.7:
511 | version "0.15.7"
512 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz#2b7c784d0b3339878013dfa82bf5eaf82c7ce7d3"
513 | integrity sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==
514 |
515 | esbuild-linux-mips64le@0.15.7:
516 | version "0.15.7"
517 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz#bb8330a50b14aa84673816cb63cc6c8b9beb62cc"
518 | integrity sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==
519 |
520 | esbuild-linux-ppc64le@0.15.7:
521 | version "0.15.7"
522 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz#52544e7fa992811eb996674090d0bc41f067a14b"
523 | integrity sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==
524 |
525 | esbuild-linux-riscv64@0.15.7:
526 | version "0.15.7"
527 | resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz#a43ae60697992b957e454cbb622f7ee5297e8159"
528 | integrity sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==
529 |
530 | esbuild-linux-s390x@0.15.7:
531 | version "0.15.7"
532 | resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz#8c76a125dd10a84c166294d77416caaf5e1c7b64"
533 | integrity sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==
534 |
535 | esbuild-netbsd-64@0.15.7:
536 | version "0.15.7"
537 | resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz#19b2e75449d7d9c32b5d8a222bac2f1e0c3b08fd"
538 | integrity sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==
539 |
540 | esbuild-openbsd-64@0.15.7:
541 | version "0.15.7"
542 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz#1357b2bf72fd037d9150e751420a1fe4c8618ad7"
543 | integrity sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==
544 |
545 | esbuild-sunos-64@0.15.7:
546 | version "0.15.7"
547 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz#87ab2c604592a9c3c763e72969da0d72bcde91d2"
548 | integrity sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==
549 |
550 | esbuild-windows-32@0.15.7:
551 | version "0.15.7"
552 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz#c81e688c0457665a8d463a669e5bf60870323e99"
553 | integrity sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==
554 |
555 | esbuild-windows-64@0.15.7:
556 | version "0.15.7"
557 | resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz#2421d1ae34b0561a9d6767346b381961266c4eff"
558 | integrity sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==
559 |
560 | esbuild-windows-arm64@0.15.7:
561 | version "0.15.7"
562 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz#7d5e9e060a7b454cb2f57f84a3f3c23c8f30b7d2"
563 | integrity sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==
564 |
565 | esbuild@^0.15.7:
566 | version "0.15.7"
567 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.7.tgz#8a1f1aff58671a3199dd24df95314122fc1ddee8"
568 | integrity sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==
569 | optionalDependencies:
570 | "@esbuild/linux-loong64" "0.15.7"
571 | esbuild-android-64 "0.15.7"
572 | esbuild-android-arm64 "0.15.7"
573 | esbuild-darwin-64 "0.15.7"
574 | esbuild-darwin-arm64 "0.15.7"
575 | esbuild-freebsd-64 "0.15.7"
576 | esbuild-freebsd-arm64 "0.15.7"
577 | esbuild-linux-32 "0.15.7"
578 | esbuild-linux-64 "0.15.7"
579 | esbuild-linux-arm "0.15.7"
580 | esbuild-linux-arm64 "0.15.7"
581 | esbuild-linux-mips64le "0.15.7"
582 | esbuild-linux-ppc64le "0.15.7"
583 | esbuild-linux-riscv64 "0.15.7"
584 | esbuild-linux-s390x "0.15.7"
585 | esbuild-netbsd-64 "0.15.7"
586 | esbuild-openbsd-64 "0.15.7"
587 | esbuild-sunos-64 "0.15.7"
588 | esbuild-windows-32 "0.15.7"
589 | esbuild-windows-64 "0.15.7"
590 | esbuild-windows-arm64 "0.15.7"
591 |
592 | escalade@^3.1.1:
593 | version "3.1.1"
594 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
595 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
596 |
597 | escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0:
598 | version "4.0.0"
599 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
600 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
601 |
602 | eslint-config-prettier@^8.5.0:
603 | version "8.5.0"
604 | resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
605 | integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
606 |
607 | eslint-plugin-prettier@^4.2.1:
608 | version "4.2.1"
609 | resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b"
610 | integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==
611 | dependencies:
612 | prettier-linter-helpers "^1.0.0"
613 |
614 | eslint-scope@^5.1.1:
615 | version "5.1.1"
616 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
617 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
618 | dependencies:
619 | esrecurse "^4.3.0"
620 | estraverse "^4.1.1"
621 |
622 | eslint-scope@^7.2.0:
623 | version "7.2.0"
624 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b"
625 | integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==
626 | dependencies:
627 | esrecurse "^4.3.0"
628 | estraverse "^5.2.0"
629 |
630 | eslint-utils@^3.0.0:
631 | version "3.0.0"
632 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
633 | integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
634 | dependencies:
635 | eslint-visitor-keys "^2.0.0"
636 |
637 | eslint-visitor-keys@^2.0.0:
638 | version "2.1.0"
639 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
640 | integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
641 |
642 | eslint-visitor-keys@^3.3.0:
643 | version "3.3.0"
644 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
645 | integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
646 |
647 | eslint-visitor-keys@^3.4.1:
648 | version "3.4.1"
649 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
650 | integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
651 |
652 | eslint@^8.44.0:
653 | version "8.44.0"
654 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.44.0.tgz#51246e3889b259bbcd1d7d736a0c10add4f0e500"
655 | integrity sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==
656 | dependencies:
657 | "@eslint-community/eslint-utils" "^4.2.0"
658 | "@eslint-community/regexpp" "^4.4.0"
659 | "@eslint/eslintrc" "^2.1.0"
660 | "@eslint/js" "8.44.0"
661 | "@humanwhocodes/config-array" "^0.11.10"
662 | "@humanwhocodes/module-importer" "^1.0.1"
663 | "@nodelib/fs.walk" "^1.2.8"
664 | ajv "^6.10.0"
665 | chalk "^4.0.0"
666 | cross-spawn "^7.0.2"
667 | debug "^4.3.2"
668 | doctrine "^3.0.0"
669 | escape-string-regexp "^4.0.0"
670 | eslint-scope "^7.2.0"
671 | eslint-visitor-keys "^3.4.1"
672 | espree "^9.6.0"
673 | esquery "^1.4.2"
674 | esutils "^2.0.2"
675 | fast-deep-equal "^3.1.3"
676 | file-entry-cache "^6.0.1"
677 | find-up "^5.0.0"
678 | glob-parent "^6.0.2"
679 | globals "^13.19.0"
680 | graphemer "^1.4.0"
681 | ignore "^5.2.0"
682 | import-fresh "^3.0.0"
683 | imurmurhash "^0.1.4"
684 | is-glob "^4.0.0"
685 | is-path-inside "^3.0.3"
686 | js-yaml "^4.1.0"
687 | json-stable-stringify-without-jsonify "^1.0.1"
688 | levn "^0.4.1"
689 | lodash.merge "^4.6.2"
690 | minimatch "^3.1.2"
691 | natural-compare "^1.4.0"
692 | optionator "^0.9.3"
693 | strip-ansi "^6.0.1"
694 | strip-json-comments "^3.1.0"
695 | text-table "^0.2.0"
696 |
697 | espree@^9.6.0:
698 | version "9.6.0"
699 | resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f"
700 | integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==
701 | dependencies:
702 | acorn "^8.9.0"
703 | acorn-jsx "^5.3.2"
704 | eslint-visitor-keys "^3.4.1"
705 |
706 | esquery@^1.4.2:
707 | version "1.5.0"
708 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
709 | integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
710 | dependencies:
711 | estraverse "^5.1.0"
712 |
713 | esrecurse@^4.3.0:
714 | version "4.3.0"
715 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
716 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
717 | dependencies:
718 | estraverse "^5.2.0"
719 |
720 | estraverse@^4.1.1:
721 | version "4.3.0"
722 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
723 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
724 |
725 | estraverse@^5.1.0, estraverse@^5.2.0:
726 | version "5.2.0"
727 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
728 | integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
729 |
730 | esutils@^2.0.2:
731 | version "2.0.3"
732 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
733 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
734 |
735 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
736 | version "3.1.3"
737 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
738 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
739 |
740 | fast-diff@^1.1.2:
741 | version "1.2.0"
742 | resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
743 | integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
744 |
745 | fast-glob@^3.1.1:
746 | version "3.2.7"
747 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
748 | integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
749 | dependencies:
750 | "@nodelib/fs.stat" "^2.0.2"
751 | "@nodelib/fs.walk" "^1.2.3"
752 | glob-parent "^5.1.2"
753 | merge2 "^1.3.0"
754 | micromatch "^4.0.4"
755 |
756 | fast-glob@^3.2.9:
757 | version "3.2.12"
758 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
759 | integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
760 | dependencies:
761 | "@nodelib/fs.stat" "^2.0.2"
762 | "@nodelib/fs.walk" "^1.2.3"
763 | glob-parent "^5.1.2"
764 | merge2 "^1.3.0"
765 | micromatch "^4.0.4"
766 |
767 | fast-json-stable-stringify@^2.0.0:
768 | version "2.1.0"
769 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
770 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
771 |
772 | fast-levenshtein@^2.0.6:
773 | version "2.0.6"
774 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
775 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
776 |
777 | fastq@^1.6.0:
778 | version "1.11.1"
779 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807"
780 | integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==
781 | dependencies:
782 | reusify "^1.0.4"
783 |
784 | file-entry-cache@^6.0.1:
785 | version "6.0.1"
786 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
787 | integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
788 | dependencies:
789 | flat-cache "^3.0.4"
790 |
791 | fill-range@^7.0.1:
792 | version "7.0.1"
793 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
794 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
795 | dependencies:
796 | to-regex-range "^5.0.1"
797 |
798 | find-up@5.0.0, find-up@^5.0.0:
799 | version "5.0.0"
800 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
801 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
802 | dependencies:
803 | locate-path "^6.0.0"
804 | path-exists "^4.0.0"
805 |
806 | flat-cache@^3.0.4:
807 | version "3.0.4"
808 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
809 | integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
810 | dependencies:
811 | flatted "^3.1.0"
812 | rimraf "^3.0.2"
813 |
814 | flat@^5.0.2:
815 | version "5.0.2"
816 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
817 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
818 |
819 | flatted@^3.1.0:
820 | version "3.2.2"
821 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561"
822 | integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==
823 |
824 | fs.realpath@^1.0.0:
825 | version "1.0.0"
826 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
827 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
828 |
829 | fsevents@~2.3.2:
830 | version "2.3.2"
831 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
832 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
833 |
834 | functional-red-black-tree@^1.0.1:
835 | version "1.0.1"
836 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
837 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
838 |
839 | get-caller-file@^2.0.5:
840 | version "2.0.5"
841 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
842 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
843 |
844 | glob-parent@^5.1.2, glob-parent@~5.1.2:
845 | version "5.1.2"
846 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
847 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
848 | dependencies:
849 | is-glob "^4.0.1"
850 |
851 | glob-parent@^6.0.2:
852 | version "6.0.2"
853 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
854 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
855 | dependencies:
856 | is-glob "^4.0.3"
857 |
858 | glob@7.2.0:
859 | version "7.2.0"
860 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
861 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
862 | dependencies:
863 | fs.realpath "^1.0.0"
864 | inflight "^1.0.4"
865 | inherits "2"
866 | minimatch "^3.0.4"
867 | once "^1.3.0"
868 | path-is-absolute "^1.0.0"
869 |
870 | glob@^7.1.3, glob@^7.1.7:
871 | version "7.1.7"
872 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
873 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
874 | dependencies:
875 | fs.realpath "^1.0.0"
876 | inflight "^1.0.4"
877 | inherits "2"
878 | minimatch "^3.0.4"
879 | once "^1.3.0"
880 | path-is-absolute "^1.0.0"
881 |
882 | globals@^13.19.0:
883 | version "13.20.0"
884 | resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
885 | integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
886 | dependencies:
887 | type-fest "^0.20.2"
888 |
889 | globby@^11.0.3:
890 | version "11.0.4"
891 | resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
892 | integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
893 | dependencies:
894 | array-union "^2.1.0"
895 | dir-glob "^3.0.1"
896 | fast-glob "^3.1.1"
897 | ignore "^5.1.4"
898 | merge2 "^1.3.0"
899 | slash "^3.0.0"
900 |
901 | globby@^11.1.0:
902 | version "11.1.0"
903 | resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
904 | integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
905 | dependencies:
906 | array-union "^2.1.0"
907 | dir-glob "^3.0.1"
908 | fast-glob "^3.2.9"
909 | ignore "^5.2.0"
910 | merge2 "^1.4.1"
911 | slash "^3.0.0"
912 |
913 | graphemer@^1.4.0:
914 | version "1.4.0"
915 | resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
916 | integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
917 |
918 | has-flag@^4.0.0:
919 | version "4.0.0"
920 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
921 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
922 |
923 | he@1.2.0:
924 | version "1.2.0"
925 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
926 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
927 |
928 | https-proxy-agent@5.0.0:
929 | version "5.0.0"
930 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
931 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
932 | dependencies:
933 | agent-base "6"
934 | debug "4"
935 |
936 | ignore@^5.1.4:
937 | version "5.1.8"
938 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
939 | integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
940 |
941 | ignore@^5.2.0:
942 | version "5.2.0"
943 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
944 | integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
945 |
946 | import-fresh@^3.0.0, import-fresh@^3.2.1:
947 | version "3.3.0"
948 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
949 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
950 | dependencies:
951 | parent-module "^1.0.0"
952 | resolve-from "^4.0.0"
953 |
954 | imurmurhash@^0.1.4:
955 | version "0.1.4"
956 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
957 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
958 |
959 | inflight@^1.0.4:
960 | version "1.0.6"
961 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
962 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
963 | dependencies:
964 | once "^1.3.0"
965 | wrappy "1"
966 |
967 | inherits@2:
968 | version "2.0.4"
969 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
970 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
971 |
972 | is-binary-path@~2.1.0:
973 | version "2.1.0"
974 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
975 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
976 | dependencies:
977 | binary-extensions "^2.0.0"
978 |
979 | is-extglob@^2.1.1:
980 | version "2.1.1"
981 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
982 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
983 |
984 | is-fullwidth-code-point@^3.0.0:
985 | version "3.0.0"
986 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
987 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
988 |
989 | is-glob@^4.0.0, is-glob@^4.0.1:
990 | version "4.0.1"
991 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
992 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
993 | dependencies:
994 | is-extglob "^2.1.1"
995 |
996 | is-glob@^4.0.3, is-glob@~4.0.1:
997 | version "4.0.3"
998 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
999 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
1000 | dependencies:
1001 | is-extglob "^2.1.1"
1002 |
1003 | is-number@^7.0.0:
1004 | version "7.0.0"
1005 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
1006 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
1007 |
1008 | is-path-inside@^3.0.3:
1009 | version "3.0.3"
1010 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
1011 | integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
1012 |
1013 | is-plain-obj@^2.1.0:
1014 | version "2.1.0"
1015 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
1016 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
1017 |
1018 | is-unicode-supported@^0.1.0:
1019 | version "0.1.0"
1020 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
1021 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
1022 |
1023 | isexe@^2.0.0:
1024 | version "2.0.0"
1025 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
1026 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
1027 |
1028 | js-yaml@4.1.0, js-yaml@^4.1.0:
1029 | version "4.1.0"
1030 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
1031 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
1032 | dependencies:
1033 | argparse "^2.0.1"
1034 |
1035 | json-schema-traverse@^0.4.1:
1036 | version "0.4.1"
1037 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
1038 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
1039 |
1040 | json-stable-stringify-without-jsonify@^1.0.1:
1041 | version "1.0.1"
1042 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
1043 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
1044 |
1045 | levn@^0.4.1:
1046 | version "0.4.1"
1047 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
1048 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
1049 | dependencies:
1050 | prelude-ls "^1.2.1"
1051 | type-check "~0.4.0"
1052 |
1053 | locate-path@^6.0.0:
1054 | version "6.0.0"
1055 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
1056 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
1057 | dependencies:
1058 | p-locate "^5.0.0"
1059 |
1060 | lodash.merge@^4.6.2:
1061 | version "4.6.2"
1062 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
1063 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
1064 |
1065 | lodash@^4.17.21:
1066 | version "4.17.21"
1067 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
1068 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
1069 |
1070 | log-symbols@4.1.0:
1071 | version "4.1.0"
1072 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
1073 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
1074 | dependencies:
1075 | chalk "^4.1.0"
1076 | is-unicode-supported "^0.1.0"
1077 |
1078 | lru-cache@^6.0.0:
1079 | version "6.0.0"
1080 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
1081 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
1082 | dependencies:
1083 | yallist "^4.0.0"
1084 |
1085 | merge2@^1.3.0, merge2@^1.4.1:
1086 | version "1.4.1"
1087 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
1088 | integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
1089 |
1090 | micromatch@^4.0.4:
1091 | version "4.0.4"
1092 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
1093 | integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
1094 | dependencies:
1095 | braces "^3.0.1"
1096 | picomatch "^2.2.3"
1097 |
1098 | minimatch@5.0.1:
1099 | version "5.0.1"
1100 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b"
1101 | integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==
1102 | dependencies:
1103 | brace-expansion "^2.0.1"
1104 |
1105 | minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2:
1106 | version "3.1.2"
1107 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
1108 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
1109 | dependencies:
1110 | brace-expansion "^1.1.7"
1111 |
1112 | mixpanel@^0.17.0:
1113 | version "0.17.0"
1114 | resolved "https://registry.yarnpkg.com/mixpanel/-/mixpanel-0.17.0.tgz#ec57b068598c620cf039a5e504fb37c97ebfe8ce"
1115 | integrity sha512-DY5WeOy/hmkPrNiiZugJpWR0iMuOwuj1a3u0bgwB2eUFRV6oIew/pIahhpawdbNjb+Bye4a8ID3gefeNPvL81g==
1116 | dependencies:
1117 | https-proxy-agent "5.0.0"
1118 |
1119 | mocha@^10.0.0:
1120 | version "10.0.0"
1121 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9"
1122 | integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==
1123 | dependencies:
1124 | "@ungap/promise-all-settled" "1.1.2"
1125 | ansi-colors "4.1.1"
1126 | browser-stdout "1.3.1"
1127 | chokidar "3.5.3"
1128 | debug "4.3.4"
1129 | diff "5.0.0"
1130 | escape-string-regexp "4.0.0"
1131 | find-up "5.0.0"
1132 | glob "7.2.0"
1133 | he "1.2.0"
1134 | js-yaml "4.1.0"
1135 | log-symbols "4.1.0"
1136 | minimatch "5.0.1"
1137 | ms "2.1.3"
1138 | nanoid "3.3.3"
1139 | serialize-javascript "6.0.0"
1140 | strip-json-comments "3.1.1"
1141 | supports-color "8.1.1"
1142 | workerpool "6.2.1"
1143 | yargs "16.2.0"
1144 | yargs-parser "20.2.4"
1145 | yargs-unparser "2.0.0"
1146 |
1147 | ms@2.1.2:
1148 | version "2.1.2"
1149 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
1150 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
1151 |
1152 | ms@2.1.3:
1153 | version "2.1.3"
1154 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
1155 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
1156 |
1157 | nanoid@3.3.3:
1158 | version "3.3.3"
1159 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25"
1160 | integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
1161 |
1162 | natural-compare@^1.4.0:
1163 | version "1.4.0"
1164 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
1165 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
1166 |
1167 | normalize-path@^3.0.0, normalize-path@~3.0.0:
1168 | version "3.0.0"
1169 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
1170 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
1171 |
1172 | once@^1.3.0:
1173 | version "1.4.0"
1174 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
1175 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
1176 | dependencies:
1177 | wrappy "1"
1178 |
1179 | optionator@^0.9.3:
1180 | version "0.9.3"
1181 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
1182 | integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==
1183 | dependencies:
1184 | "@aashutoshrathi/word-wrap" "^1.2.3"
1185 | deep-is "^0.1.3"
1186 | fast-levenshtein "^2.0.6"
1187 | levn "^0.4.1"
1188 | prelude-ls "^1.2.1"
1189 | type-check "^0.4.0"
1190 |
1191 | p-limit@^3.0.2:
1192 | version "3.1.0"
1193 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
1194 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
1195 | dependencies:
1196 | yocto-queue "^0.1.0"
1197 |
1198 | p-locate@^5.0.0:
1199 | version "5.0.0"
1200 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
1201 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
1202 | dependencies:
1203 | p-limit "^3.0.2"
1204 |
1205 | parent-module@^1.0.0:
1206 | version "1.0.1"
1207 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
1208 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
1209 | dependencies:
1210 | callsites "^3.0.0"
1211 |
1212 | path-exists@^4.0.0:
1213 | version "4.0.0"
1214 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
1215 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
1216 |
1217 | path-is-absolute@^1.0.0:
1218 | version "1.0.1"
1219 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
1220 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
1221 |
1222 | path-key@^3.1.0:
1223 | version "3.1.1"
1224 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
1225 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
1226 |
1227 | path-type@^4.0.0:
1228 | version "4.0.0"
1229 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
1230 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
1231 |
1232 | picomatch@^2.0.4, picomatch@^2.2.1:
1233 | version "2.3.1"
1234 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
1235 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
1236 |
1237 | picomatch@^2.2.3:
1238 | version "2.3.0"
1239 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
1240 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
1241 |
1242 | prelude-ls@^1.2.1:
1243 | version "1.2.1"
1244 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
1245 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
1246 |
1247 | prettier-linter-helpers@^1.0.0:
1248 | version "1.0.0"
1249 | resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
1250 | integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
1251 | dependencies:
1252 | fast-diff "^1.1.2"
1253 |
1254 | prettier@^2.7.1:
1255 | version "2.7.1"
1256 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64"
1257 | integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
1258 |
1259 | punycode@^2.1.0:
1260 | version "2.1.1"
1261 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
1262 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
1263 |
1264 | queue-microtask@^1.2.2:
1265 | version "1.2.3"
1266 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
1267 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
1268 |
1269 | randombytes@^2.1.0:
1270 | version "2.1.0"
1271 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
1272 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
1273 | dependencies:
1274 | safe-buffer "^5.1.0"
1275 |
1276 | readdirp@~3.6.0:
1277 | version "3.6.0"
1278 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
1279 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
1280 | dependencies:
1281 | picomatch "^2.2.1"
1282 |
1283 | regexpp@^3.2.0:
1284 | version "3.2.0"
1285 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
1286 | integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
1287 |
1288 | require-directory@^2.1.1:
1289 | version "2.1.1"
1290 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
1291 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
1292 |
1293 | resolve-from@^4.0.0:
1294 | version "4.0.0"
1295 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
1296 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
1297 |
1298 | reusify@^1.0.4:
1299 | version "1.0.4"
1300 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
1301 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
1302 |
1303 | rimraf@^3.0.2:
1304 | version "3.0.2"
1305 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
1306 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
1307 | dependencies:
1308 | glob "^7.1.3"
1309 |
1310 | run-parallel@^1.1.9:
1311 | version "1.2.0"
1312 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
1313 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
1314 | dependencies:
1315 | queue-microtask "^1.2.2"
1316 |
1317 | safe-buffer@^5.1.0:
1318 | version "5.2.1"
1319 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
1320 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
1321 |
1322 | semver@^7.3.5:
1323 | version "7.3.5"
1324 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
1325 | integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
1326 | dependencies:
1327 | lru-cache "^6.0.0"
1328 |
1329 | semver@^7.3.7:
1330 | version "7.3.7"
1331 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
1332 | integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
1333 | dependencies:
1334 | lru-cache "^6.0.0"
1335 |
1336 | serialize-javascript@6.0.0:
1337 | version "6.0.0"
1338 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
1339 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
1340 | dependencies:
1341 | randombytes "^2.1.0"
1342 |
1343 | shebang-command@^2.0.0:
1344 | version "2.0.0"
1345 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
1346 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
1347 | dependencies:
1348 | shebang-regex "^3.0.0"
1349 |
1350 | shebang-regex@^3.0.0:
1351 | version "3.0.0"
1352 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
1353 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
1354 |
1355 | slash@^3.0.0:
1356 | version "3.0.0"
1357 | resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
1358 | integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
1359 |
1360 | string-width@^4.1.0, string-width@^4.2.0:
1361 | version "4.2.3"
1362 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
1363 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
1364 | dependencies:
1365 | emoji-regex "^8.0.0"
1366 | is-fullwidth-code-point "^3.0.0"
1367 | strip-ansi "^6.0.1"
1368 |
1369 | strip-ansi@^6.0.0:
1370 | version "6.0.0"
1371 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
1372 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
1373 | dependencies:
1374 | ansi-regex "^5.0.0"
1375 |
1376 | strip-ansi@^6.0.1:
1377 | version "6.0.1"
1378 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
1379 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
1380 | dependencies:
1381 | ansi-regex "^5.0.1"
1382 |
1383 | strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
1384 | version "3.1.1"
1385 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
1386 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
1387 |
1388 | supports-color@8.1.1:
1389 | version "8.1.1"
1390 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
1391 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
1392 | dependencies:
1393 | has-flag "^4.0.0"
1394 |
1395 | supports-color@^7.1.0:
1396 | version "7.2.0"
1397 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
1398 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
1399 | dependencies:
1400 | has-flag "^4.0.0"
1401 |
1402 | text-table@^0.2.0:
1403 | version "0.2.0"
1404 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
1405 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
1406 |
1407 | to-regex-range@^5.0.1:
1408 | version "5.0.1"
1409 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
1410 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
1411 | dependencies:
1412 | is-number "^7.0.0"
1413 |
1414 | tslib@^1.8.1:
1415 | version "1.14.1"
1416 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
1417 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
1418 |
1419 | tsutils@^3.21.0:
1420 | version "3.21.0"
1421 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
1422 | integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
1423 | dependencies:
1424 | tslib "^1.8.1"
1425 |
1426 | type-check@^0.4.0, type-check@~0.4.0:
1427 | version "0.4.0"
1428 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
1429 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
1430 | dependencies:
1431 | prelude-ls "^1.2.1"
1432 |
1433 | type-fest@^0.20.2:
1434 | version "0.20.2"
1435 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
1436 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
1437 |
1438 | typescript@^4.3.2:
1439 | version "4.3.5"
1440 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
1441 | integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
1442 |
1443 | uri-js@^4.2.2:
1444 | version "4.4.1"
1445 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
1446 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
1447 | dependencies:
1448 | punycode "^2.1.0"
1449 |
1450 | which@^2.0.1:
1451 | version "2.0.2"
1452 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
1453 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
1454 | dependencies:
1455 | isexe "^2.0.0"
1456 |
1457 | workerpool@6.2.1:
1458 | version "6.2.1"
1459 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
1460 | integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
1461 |
1462 | wrap-ansi@^7.0.0:
1463 | version "7.0.0"
1464 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
1465 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
1466 | dependencies:
1467 | ansi-styles "^4.0.0"
1468 | string-width "^4.1.0"
1469 | strip-ansi "^6.0.0"
1470 |
1471 | wrappy@1:
1472 | version "1.0.2"
1473 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
1474 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
1475 |
1476 | y18n@^5.0.5:
1477 | version "5.0.8"
1478 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
1479 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
1480 |
1481 | yallist@^4.0.0:
1482 | version "4.0.0"
1483 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
1484 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
1485 |
1486 | yargs-parser@20.2.4:
1487 | version "20.2.4"
1488 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
1489 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
1490 |
1491 | yargs-parser@^20.2.2:
1492 | version "20.2.9"
1493 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
1494 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
1495 |
1496 | yargs-unparser@2.0.0:
1497 | version "2.0.0"
1498 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb"
1499 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
1500 | dependencies:
1501 | camelcase "^6.0.0"
1502 | decamelize "^4.0.0"
1503 | flat "^5.0.2"
1504 | is-plain-obj "^2.1.0"
1505 |
1506 | yargs@16.2.0:
1507 | version "16.2.0"
1508 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
1509 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
1510 | dependencies:
1511 | cliui "^7.0.2"
1512 | escalade "^3.1.1"
1513 | get-caller-file "^2.0.5"
1514 | require-directory "^2.1.1"
1515 | string-width "^4.2.0"
1516 | y18n "^5.0.5"
1517 | yargs-parser "^20.2.2"
1518 |
1519 | yocto-queue@^0.1.0:
1520 | version "0.1.0"
1521 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
1522 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
1523 |
--------------------------------------------------------------------------------