From 2d8b983fd67f4a082e339484d344bf474f56a99c Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sat, 17 May 2025 01:51:10 +0100 Subject: [PATCH 01/31] rewrite in go --- .eslintrc.json | 20 - .gitignore | 95 -- .prettierrc | 12 - LICENSE | 2 +- README.md | 71 - go.mod | 7 + go.sum | 0 lib/README.md | 63 + lib/aws_import.go | 89 ++ lib/profile.go | 40 + lib/store.go | 39 + main.go | 29 + package.json | 56 - release.sh | 31 - src/AwsProfileManager.ts | 154 -- src/config.json | 5 - src/index.ts | 406 ------ src/utils/CliConfig.ts | 41 - src/utils/IniConfig.ts | 16 - src/utils/Print.ts | 18 - src/utils/index.ts | 9 - tests/config/config | 15 - tests/config/credentials | 15 - tests/utils/index.test.ts | 10 - tsconfig.json | 20 - utils/filepath.go | 27 + webpack.config.ts | 37 - yarn.lock | 2902 ------------------------------------- 28 files changed, 295 insertions(+), 3934 deletions(-) delete mode 100644 .eslintrc.json delete mode 100644 .gitignore delete mode 100644 .prettierrc delete mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 lib/README.md create mode 100644 lib/aws_import.go create mode 100644 lib/profile.go create mode 100644 lib/store.go create mode 100644 main.go delete mode 100644 package.json delete mode 100644 release.sh delete mode 100644 src/AwsProfileManager.ts delete mode 100644 src/config.json delete mode 100644 src/index.ts delete mode 100644 src/utils/CliConfig.ts delete mode 100644 src/utils/IniConfig.ts delete mode 100644 src/utils/Print.ts delete mode 100644 src/utils/index.ts delete mode 100644 tests/config/config delete mode 100644 tests/config/credentials delete mode 100644 tests/utils/index.test.ts delete mode 100644 tsconfig.json create mode 100644 utils/filepath.go delete mode 100644 webpack.config.ts delete mode 100644 yarn.lock diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a6242c7..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true - }, - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - "overrides": [], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": ["@typescript-eslint"], - "rules": { - "@typescript-eslint/indent": ["error", 2], - "linebreak-style": ["error", "unix"], - "quotes": ["error", "single", { "avoidEscape": true }], - "semi": ["error", "never"] - } -} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0ecb64b..0000000 --- a/.gitignore +++ /dev/null @@ -1,95 +0,0 @@ -# Temporary files generated by builds that point to our CSS/JS entrypoints. -src/site/_data/resource*.json - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -# next.js build output -.next - -# Lighthouse CI test output -.lighthouseci - -# build artifacts -dist - -# DS_Store -.DS_Store - -# IDEs -.idea -entrypoint.hashmanifest.json -.vscode - -# Temporary files -.cache -.tmp -.cache -.firebase -firebase.json -src/scss/_tokens.scss -src/scss/_themes.scss - -# Eleventy -# We generate our own .eleventyignore file dynamically during builds -.eleventyignore - -# release -package/ -build/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index f2d7ce3..0000000 --- a/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "trailingComma": "none", - "tabWidth": 2, - "semi": false, - "singleQuote": true, - "jsxSingleQuote": true, - "bracketSpacing": true, - "bracketSameLine": false, - "arrowParens": "avoid", - "endOfLine": "lf", - "printWidth": 80 -} \ No newline at end of file diff --git a/LICENSE b/LICENSE index b01cae7..a727ad1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2022 Patrick Rodrigues +Copyright 2025 Patrick Rodrigues (rodpadev) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md deleted file mode 100644 index eef94cc..0000000 --- a/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# AWS Profiles - -CLI to manage aws profiles by using `default` as the currently selected profiles. - -## Why? - -Many projects I work with use [Terraform](https://www.terraform.io/) and since many of the projects use different set of credentials, I find myself having to manually switch the profiles in `~/aws/credentials` and `~/aws/config`. - -I'm aware I can use named profiles and specify which profile I want to use but I simply don't want to because **I'm stubborn and I want it to work the way I want it to work**. - -## Installation - - -1. Go to release and download the zip matching your os & architecture -2. Unzip to `/usr/local/bin` or if you're on windows `C:\Program Files\aws-profiles` -3. If you're on windows you need to [add the program to path](https://gist.github.com/RodPaDev/e9365fbb6f0c5d8553ceb84ad87110b1) - - ->I intend on publishing these binaries on `homebrew`, `chocolatey`, & need to figure what the best option if for `linux`. - -## Usage - - -To select a profile run: - -``` -$ aws-profiles select -``` - -To display help and available commands run: - -``` -$ aws-profiles -``` - -This is the list of commands and their description: - -``` -list List all profiles -select Select a profile to select as the default aws profile -current Display the current Default Profile's name -choose Choose a profile from an interactive shell -add Add a new aws profile -delete Delete a aws profile -edit Edit an existing aws profile -help [command] display help for command -``` - -## How does this work? - -`aws-cli` uses ini files to store the credentials and configuration and uses named sections to group key-value pairs that belong to a profile. - -So I use the `Default` profile (initally configured by running `aws configure`), as the current/active profile and keep the credentials of named profiles in seperate sections. - -Example: - -```ini -[default] -aws_access_key_id=foo_id -aws_secret_access_key=foo_secret - -[foo] -aws_access_key_id=foo_id -aws_secret_access_key=foo_secret - -[foo] -aws_access_key_id=bar_id -aws_secret_access_key=bar_secret -``` - -As you can see above, the values of the profile foo are used in default as well, this means the foo profile is active and that's how you switch profiles by essentially setting the values of the intended profile to default. diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e1337fa --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module github.com/rodpadev/aws-profiles + +go 1.23.0 + +toolchain go1.23.9 + +replace github.com/rodpadev/aws-profiles => ./ \ No newline at end of file diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..c2155b9 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,63 @@ +# `lib` — AWS Profiles Library + +This package provides a programmatic interface for managing custom AWS profiles stored outside of `~/.aws`. It is designed to power the `aws-profiles v2` project, enabling secure and flexible profile management with first-class support for native encryption and CLI/TUI integration. + +--- + +## 🔧 Features + +- **Add, edit, remove** AWS profiles +- Store profiles in a **separate dotfile** (not `~/.aws`) +- Support the following fields per profile: + - `name` + - `region` + - `role_arn` + - `access_key_id` + - `secret_access_key` + +--- + +## 🔐 Security + +- Profiles can be **optionally encrypted**: + - Uses **system-native credential storage** (e.g., macOS Keychain, Windows Credential Manager) when available + - Falls back to **password-based encryption** if system keyring is not supported + +--- + +## 🔁 AWS Migration Support + +- One-time import of profiles from `~/.aws/config` and `~/.aws/credentials` + - A backup will be made and will require manual deletion. +- Imported profiles are moved into the new config file +- Leaves behind an **empty default profile** in `.aws` + +--- + +## ✅ Profile Activation + +- Set a profile as "active" to: + - Recreate and write a minimal `.aws/config` and `.aws/credentials` + - Overwrite the files cleanly without concern for legacy format + +--- + +## 📦 Usage + +TODO LATER + +--- + +## 📁 Storage + +Profiles are saved in: + +``` +~/.aws-profiles/config.json +``` + +Or, if encryption is enabled: + +``` +~/.aws-profiles/config-encrypted.bin +``` \ No newline at end of file diff --git a/lib/aws_import.go b/lib/aws_import.go new file mode 100644 index 0000000..496682d --- /dev/null +++ b/lib/aws_import.go @@ -0,0 +1,89 @@ +package lib + +import ( + "bytes" + "log" + "os" + "path" + "strings" + + "github.com/rodpadev/aws-profiles/utils" +) + +func LoadAWSProfileData() ([][]byte, error) { + homeDir, err := utils.GetHomePath() + + if err != nil { + log.Fatal(err) + } + + dirPath := path.Join(homeDir, ".aws") + + config, err := os.ReadFile(path.Join(dirPath, "config")) + if err != nil { + return nil, err + } + + credentials, err := os.ReadFile(path.Join(dirPath, "credentials")) + if err != nil { + return nil, err + } + + return [][]byte{config, credentials}, nil +} + +func ParseAWSProfileData(data [][]byte) map[string]map[string]string { + result := map[string]map[string]string{} + + combined := append(data[0], '\n') + combined = append(combined, data[1]...) + + lines := bytes.Split(combined, []byte{'\n'}) + + var currentSection string + for i, line := range lines { + + // remove comments and ignore empty liens + if len(line) == 0 || line[0] == '#' || line[0] == ';' { + continue + } + + // get current section + if line[0] == '[' && line[len(line)-1] == ']' { + currentSection = string(line[1 : len(line)-1]) + if _, exists := result[currentSection]; !exists { + result[currentSection] = make(map[string]string) + } + continue + } + + // key value + assignIndex := strings.IndexRune(string(line), '=') + + if assignIndex == -1 { + continue + } + + key := strings.TrimSpace(string(line[:assignIndex])) + value := strings.TrimSpace(string(line[assignIndex+1:])) + + if currentSection == "" { + currentSection = "no_category_" + string(i) + if _, exists := result[currentSection]; !exists { + result[currentSection] = map[string]string{} + } + } + + if key == "" { + key = "no_key" + } + + if value != "" { + result[currentSection][key] = value + } + + } + + return result + +} diff --git a/lib/profile.go b/lib/profile.go new file mode 100644 index 0000000..d6b44be --- /dev/null +++ b/lib/profile.go @@ -0,0 +1,40 @@ +package lib + +type ProfileCredential struct { + AccessKey string `json:"aws_access_key_id"` + SecretKey string `json:"aws_secret_access_key"` +} + +type ProfileConfig struct { + Region string `json:"region,omitempty"` + Output string `json:"output,omitempty"` +} + +type Profile struct { + Name string `json:"name"` + Credential ProfileCredential `json:"credential"` + Config ProfileConfig `json:"config"` +} + +type ProfileMap map[string]Profile + +func BuildProfileMap(data map[string]map[string]string) (ProfileMap, error) { + profiles := ProfileMap{} + + for section, kv := range data { + profiles[section] = Profile{ + Name: section, + Credential: ProfileCredential{ + AccessKey: kv["aws_access_key_id"], + SecretKey: kv["aws_secret_access_key"], + }, + Config: ProfileConfig{ + Region: kv["region"], + Output: kv["output"], + }, + } + + } + + return profiles, nil +} diff --git a/lib/store.go b/lib/store.go new file mode 100644 index 0000000..bc1f8b8 --- /dev/null +++ b/lib/store.go @@ -0,0 +1,39 @@ +package lib + +import ( + "encoding/json" + "os" +) + +func LoadStore(filePath string) (ProfileMap, error) { + data, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + + profileMap := ProfileMap{} + + err = json.Unmarshal(data, &profileMap) + + if err != nil { + return nil, err + } + + return profileMap, err + +} + +func SaveStore(profileMap ProfileMap, filePath string) error { + + data, err := json.Marshal(profileMap) + if err != nil { + return err + } + + err = os.WriteFile(filePath, data, 0644) + if err != nil { + return err + } + + return nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..efb856c --- /dev/null +++ b/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "encoding/json" + "log" + + "github.com/rodpadev/aws-profiles/lib" +) + +func main() { + data, err := lib.LoadAWSProfileData() + if err != nil { + log.Printf("ERR@LoadAWSProfileData") + log.Fatal(err) + } + + parsed := lib.ParseAWSProfileData(data) + + profileMap, err := lib.BuildProfileMap(parsed) + if err != nil { + log.Printf("ERR@BuildProfileMap") + log.Fatal(err) + } + + if jsonBytes, err := json.MarshalIndent(profileMap, "", " "); err == nil { + log.Println(string(jsonBytes)) + } + +} diff --git a/package.json b/package.json deleted file mode 100644 index 1ef7479..0000000 --- a/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "aws-profiles", - "description": "CLI to manage aws-cli profiles", - "version": "1.1.0", - "main": "src/index.ts", - "license": "MIT", - "scripts": { - "package": "yarn build && pkg build/main.js -c=package.json", - "build": "NODE_ENV=production webpack", - "test": "ava", - "release": "sh release.sh" - }, - "dependencies": { - "chalk": "^5.0.1", - "commander": "^9.4.0", - "ini": "^3.0.1", - "inquirer": "^9.1.2" - }, - "devDependencies": { - "@types/ini": "^1.3.31", - "@types/inquirer": "^9.0.1", - "@types/jest": "^29.0.3", - "@types/node": "^18.7.20", - "@typescript-eslint/eslint-plugin": "^5.38.1", - "@typescript-eslint/parser": "^5.38.1", - "ava": "^4.3.3", - "eslint": "^8.24.0", - "ts-jest": "^29.0.2", - "ts-loader": "^9.4.1", - "ts-node": "^10.9.1", - "typescript": "^4.8.3", - "webpack": "^5.74.0", - "webpack-cli": "^4.10.0" - }, - "pkg": { - "options": [ - "experimental-modules" - ], - "targets": [ - "node16-macos-x64", - "node16-macos-arm64", - "node16-win-x64", - "node16-linux-x64", - "node16-linux-arm64" - ], - "outputPath": "package/bin" - }, - "ava": { - "extensions": [ - "ts" - ], - "require": [ - "ts-node/register" - ] - } -} diff --git a/release.sh b/release.sh deleted file mode 100644 index dfeb17a..0000000 --- a/release.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -# remove previous generated binaries -cd ./package -rm -rf bin/ - -# create binaries -yarn package - -# create target directories -rm -rf tmp -rm -rf release -mkdir release -mkdir tmp - -# create release zips -function createZip(){ - echo "\033[0;36mcreating zip for $1 \033[0m" - mv bin/aws-profiles-"$1" tmp/aws-profiles - zip -j release/aws-profiles-"$1".zip tmp/aws-profiles - rm tmp/aws-profiles -} - -createZip "linux-arm64" -createZip "linux-x64" -createZip "macos-arm64" -createZip "macos-x64" -createZip "win-x64.exe" - -rm -rf bin -rm -rf tmp diff --git a/src/AwsProfileManager.ts b/src/AwsProfileManager.ts deleted file mode 100644 index 610ccd3..0000000 --- a/src/AwsProfileManager.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { homedir } from 'os' -import path from 'path' -import { existsSync } from 'fs' -import { createIniConfig, readConfig, writeConfig } from './utils/IniConfig' -import { Print } from './utils/Print' -import { exit } from 'process' - -type CredentialsObject = { - aws_access_key_id: string - aws_secret_access_key: string -} - -type ConfigObject = { - region: string - output: string -} - -type CredentialsMap = { - [key: string]: CredentialsObject -} - -type ConfigMap = { - [key: string]: ConfigObject -} - -class AwsProfileManager { - configPath: { - credenetials: string - config: string - } - config: ConfigMap - credentials: CredentialsMap - defaultProfileName: string - - constructor(configDir: string) { - const config = path.join(configDir, 'config') - const credenetials = path.join(configDir, 'credentials') - - this.configPath = { - config, - credenetials - } - - if (!existsSync(this.configPath.credenetials)) { - Print.error('AWS credentials file could not be found.') - exit(1) - } - if (!existsSync(this.configPath.config)) { - Print.error('AWS config file could not be found.') - exit(1) - } - - this.config = readConfig(this.configPath.config) - this.credentials = readConfig(this.configPath.credenetials) - this.defaultProfileName = '' - - const sortedConfigKeys = Object.keys(this.config).sort().toString() - const sortedCredentialsKeys = Object.keys(this.credentials) - .sort() - .toString() - - if (sortedConfigKeys.length === 0) { - Print.error( - 'Config file is empty.', - 'Please verify that all profiles exist in both files.' - ) - exit(1) - } - - if (sortedCredentialsKeys.length === 0) { - Print.error( - 'Credentials file is empty.', - 'Please verify that all profiles exist in both file.' - ) - exit(1) - } - - if (sortedConfigKeys !== sortedCredentialsKeys) { - Print.error( - 'Config and Credentials files are broken.', - 'Please verify that all profiles exist in both files.' - ) - exit(1) - } - } - - findCurrentProfile(): string { - for (const profile in this.credentials) { - if ( - profile !== 'default' && - this.credentials[profile].aws_access_key_id === - this.credentials.default.aws_access_key_id - ) { - this.defaultProfileName = profile - return profile - } - } - return '' - } - - createProfileList(appendToCurrent = ''): string[] { - const profiles = [] - for (const profile of Object.keys(this.credentials)) { - if (profile !== 'default') { - if (profile === this.defaultProfileName) { - profiles.unshift(profile + appendToCurrent) - } else { - profiles.push(profile) - } - } - } - return profiles - } - - setDefaultProfile(name: string): string { - this.config.default = this.config[name] - this.credentials.default = this.credentials[name] - return `Default profile set to '${name}'` - } - - saveProfile(): void { - const iniConfig = createIniConfig(this.config) - const iniCredentials = createIniConfig(this.credentials) - writeConfig(this.configPath.config, iniConfig) - writeConfig(this.configPath.credenetials, iniCredentials) - } - - upsertProfile( - credentials: CredentialsObject, - config: ConfigObject, - profileName: string - ): void { - this.config[profileName] = config - this.credentials[profileName] = credentials - } - - getCaseInsensitiveProfileName(profileName: string): string | undefined { - const keys = Object.keys(this.config) - return keys.find( - key => key.toLocaleLowerCase() === profileName.toLocaleLowerCase() - ) - } - - deleteProfile(profileName: string): void { - delete this.config[profileName] - delete this.credentials[profileName] - } - - static getDefaultConfigDirPath(): string { - return path.resolve(homedir(), '.aws') - } -} - -export default AwsProfileManager diff --git a/src/config.json b/src/config.json deleted file mode 100644 index edb95a5..0000000 --- a/src/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "aws-profiles", - "version": "1.1.0", - "description": "CLI to manage aws-cli profiles" -} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index eb1d2bf..0000000 --- a/src/index.ts +++ /dev/null @@ -1,406 +0,0 @@ -import chalk from 'chalk' -import { Command } from 'commander' -import inquirer from 'inquirer' -import { exit } from 'process' - -import AwsProfileManager from './AwsProfileManager' -import { createSpaces } from './utils' -import { Print } from './utils/Print' - -import config from './config.json' -import CliConfigManager from './utils/CliConfig' -import { existsSync } from 'fs' - -const defaultDirPath = AwsProfileManager.getDefaultConfigDirPath() - -const cli = new Command() -const cliConfigManager = new CliConfigManager() - -cli.name(config.name).description(config.description).version(config.version) - -cli.option( - '-p, --path ', - 'Custom path to the aws-cli config folder.', - defaultDirPath -) -cli.parse() - -const global = cli.opts() - -if (global.path !== defaultDirPath && existsSync(global.path)) { - cliConfigManager.setCustomPath(global.path) - cliConfigManager.save() -} - -cli - .command('list') - .description('List all profiles') - .action(() => { - const awsProfiler = new AwsProfileManager(global.path) - awsProfiler.findCurrentProfile() - const profiles = awsProfiler.createProfileList() - Print.info('List of aws profiles:') - let index = 0 - for (const profile of profiles) { - if (index === 0) { - Print.log(createSpaces(2), chalk.cyan(`- ${profile} [Default]`)) - } else { - Print.log(createSpaces(2), chalk.white(`- ${profile}`)) - } - index += 1 - } - }) - -cli - .command('select') - .description('Select a profile to select as the default aws profile') - .argument('', 'Profile name') - .action(profileName => { - const awsProfiler = new AwsProfileManager(global.path) - const profile = awsProfiler.findCurrentProfile() - const originalProfileName = - awsProfiler.getCaseInsensitiveProfileName(profileName) - - if (originalProfileName === 'default') { - Print.error('Cannot select', chalk.cyan('default'), 'profile') - exit(1) - } - - if (!originalProfileName) { - Print.error('Profile does not exist') - exit(1) - } - - if (profile === originalProfileName) { - Print.info( - chalk.white.bold('Default profile is already:'), - chalk.cyan(originalProfileName) - ) - } else { - switchProfile(awsProfiler, originalProfileName) - } - }) - -cli - .command('current') - .description("Display the current Default Profile's name") - .action(() => { - const awsProfiler = new AwsProfileManager(global.path) - awsProfiler.findCurrentProfile() - Print.info( - 'Current default aws profile: ', - chalk.cyan(awsProfiler.defaultProfileName) - ) - }) - -cli - .command('choose') - .description('Choose a profile from an interactive shell') - .action(() => { - const awsProfiler = new AwsProfileManager(global.path) - awsProfiler.findCurrentProfile() - const [current, ...choices] = awsProfiler.createProfileList() - Print.info('Current default aws profile: ', chalk.cyan(current)) - inquirer - .prompt([ - { - type: 'list', - name: 'profileName', - message: 'Choose a new default profile:', - choices - } - ]) - .then(({ profileName }) => { - switchProfile(awsProfiler, profileName) - }) - }) - -cli - .command('add') - .description('Add a new aws profile') - .action(() => { - const awsProfiler = new AwsProfileManager(global.path) - awsProfiler.findCurrentProfile() - inquirer - .prompt([ - { - type: 'input', - name: 'name', - message: 'Enter a profile name: ', - validate: name => { - const [isValid, validFormat] = isNameValid(name) - const originalProfileName = - awsProfiler.getCaseInsensitiveProfileName(name) - if (!isValid) { - return 'Profile name must match: ' + chalk.magenta(validFormat) - } - if (originalProfileName) { - return 'Profile already exists' - } - if (originalProfileName?.toLocaleLowerCase() === 'default') { - return 'Cannot add profile named: ' + chalk.cyan('default') - } - return true - } - }, - { - type: 'input', - name: 'aws_access_key_id', - message: 'aws_access_key_id: ' - }, - { - type: 'password', - name: 'aws_secret_access_key', - message: 'aws_secret_access_key: ' - }, - { - type: 'input', - name: 'region', - message: 'region: ' - }, - { - type: 'input', - name: 'output', - message: 'output: ' - }, - { - type: 'confirm', - name: 'setAsDefault', - message: 'Set this profile as default? ' - } - ]) - .then( - ({ - name, - aws_access_key_id, - aws_secret_access_key, - region, - output, - setAsDefault - }) => { - const credentials = { aws_access_key_id, aws_secret_access_key } - const config = { region, output } - awsProfiler.upsertProfile(credentials, config, name) - awsProfiler.saveProfile() - - if (setAsDefault) { - switchProfile(awsProfiler, name, false) - Print.info( - 'New aws profile added and set as default:', - chalk.cyan(name) - ) - } else { - Print.info('New aws profile added:', chalk.cyan(name)) - } - } - ) - }) - -cli - .command('delete') - .description('Delete a aws profile') - .argument('', 'Profile name') - .action(profileName => { - const awsProfiler = new AwsProfileManager(global.path) - const originalProfileName = - awsProfiler.getCaseInsensitiveProfileName(profileName) - if (!originalProfileName) { - Print.error('Profile does not exist') - exit(1) - } - if (originalProfileName === 'default') { - Print.error('Cannot delete', chalk.cyan('default'), 'profile') - exit(1) - } - - inquirer - .prompt([ - { - type: 'confirm', - name: 'confirm', - message: chalk.yellow( - 'This action is irreversible. Are you sure you want to delete?' - ), - - prefix: chalk.yellow('!') - } - ]) - .then(({ confirm }) => { - awsProfiler.deleteProfile(profileName) - if (confirm) { - awsProfiler.saveProfile() - Print.info('AWS Profile deleted:', chalk.cyan(profileName)) - } else { - Print.info('AWS Profile was not deleted:', chalk.cyan(profileName)) - } - }) - }) - -cli - .command('edit') - .description('Edit an existing aws profile') - .action(() => { - const awsProfiler = new AwsProfileManager(global.path) - awsProfiler.findCurrentProfile() - inquirer - .prompt([ - { - type: 'input', - name: 'name', - message: 'Enter a profile name: ', - validate: name => { - const [isValid, validFormat] = isNameValid(name) - if (!isValid) { - return 'Profile name must match: ' + chalk.magenta(validFormat) - } - const originalProfileName = - awsProfiler.getCaseInsensitiveProfileName(name) - if (!originalProfileName) { - return 'Profile does not exist' - } - if (originalProfileName.toLocaleLowerCase() === 'default') { - return 'Cannot edit default profile' - } - return true - } - }, - { - type: 'confirm', - name: 'isRename', - message: 'Do you wish to rename the profile?' - }, - { - when: ({ isRename }) => isRename, - type: 'input', - name: 'newName', - message: 'New profile name:', - validate: name => { - const originalProfileName = - awsProfiler.getCaseInsensitiveProfileName(name) - if (originalProfileName) { - return 'Profile name is already in use' - } - if (originalProfileName?.toLocaleLowerCase() === 'default') { - return 'Cannot rename to default' - } - return true - } - }, - { - type: 'input', - name: 'aws_access_key_id', - message: 'aws_access_key_id: ', - suffix: chalk.italic.grey('leave empty to skip edit'), - default: (answers: { [key: string]: string }) => { - return awsProfiler.credentials[answers.name].aws_access_key_id - } - }, - { - type: 'password', - name: 'aws_secret_access_key', - message: 'aws_secret_access_key: ', - suffix: chalk.italic.grey('leave empty to skip edit'), - default: (answers: { [key: string]: string }) => { - return awsProfiler.credentials[answers.name].aws_secret_access_key - } - }, - { - type: 'input', - name: 'region', - message: 'region: ', - suffix: chalk.italic.grey('leave empty to skip edit'), - default: (answers: { [key: string]: string }) => { - return awsProfiler.config[answers.name].region - } - }, - { - type: 'input', - name: 'output', - message: 'output: ', - suffix: chalk.italic.grey('leave empty to skip edit'), - default: (answers: { [key: string]: string }) => { - return awsProfiler.config[answers.name].output - } - }, - { - type: 'confirm', - name: 'isSave', - message: 'Save the edits for this profile?' - }, - { - when: ({ isSave }) => isSave, - type: 'confirm', - name: 'setAsDefault', - message: 'Set this profile as default? ' - } - ]) - .then( - ({ - name, - isRename, - newName, - aws_access_key_id, - aws_secret_access_key, - region, - output, - setAsDefault, - isSave - }) => { - const credentials = { aws_access_key_id, aws_secret_access_key } - const config = { region, output } - if (!isSave) { - Print.warn('Edits not saved for aws profile:', chalk.cyan(name)) - exit(0) - } - if (isRename) { - awsProfiler.deleteProfile(name) - awsProfiler.upsertProfile(credentials, config, newName) - Print.info( - 'Profile renamed:', - chalk.yellow(name), - '=>', - chalk.cyan(newName) - ) - } else { - awsProfiler.upsertProfile(credentials, config, name) - } - awsProfiler.saveProfile() - if (setAsDefault) { - switchProfile(awsProfiler, name, false) - Print.info( - 'Edits saved for aws profile and set as default:', - chalk.cyan(isRename ? newName : name) - ) - } else { - Print.info( - 'Edits saved for aws profile:', - chalk.cyan(isRename ? newName : name) - ) - } - } - ) - }) - -function switchProfile( - awsProfiler: AwsProfileManager, - profileName: string, - print = true -) { - awsProfiler.setDefaultProfile(profileName) - awsProfiler.saveProfile() - if (print) { - Print.info( - chalk.white('Default profile switched to: '), - chalk.cyan(profileName) - ) - } -} - -function isNameValid(name: string): [boolean, RegExp] { - const validNameRegex = new RegExp( - /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/ - ) - return [validNameRegex.test(name), validNameRegex] -} - -cli.parse() diff --git a/src/utils/CliConfig.ts b/src/utils/CliConfig.ts deleted file mode 100644 index 3545fc7..0000000 --- a/src/utils/CliConfig.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs' -import os from 'os' -import path from 'path' - -type CliConfig = { - name: string - version: string - description: string - reservedNames: string[] - customPath: string -} - -class CliConfigManager { - path: string - config: CliConfig - constructor() { - this.path = path.join(os.homedir(), '.aws-profiles', 'config.json') - this.config = this.load() - } - - setCustomPath(path: string) { - this.config.customPath = path - } - - save(): void { - writeFileSync(this.path, JSON.stringify(this.config, null, 2)) - } - - load(): CliConfig { - if (!existsSync(this.path)) { - const pathObj = path.parse(this.path) - mkdirSync(pathObj.dir, { recursive: true }) - writeFileSync(this.path, JSON.stringify(this.config ?? {}, null, 2), { - encoding: 'utf-8' - }) - } - return JSON.parse(readFileSync(this.path, { encoding: 'utf-8' })) - } -} - -export default CliConfigManager diff --git a/src/utils/IniConfig.ts b/src/utils/IniConfig.ts deleted file mode 100644 index 14f1c01..0000000 --- a/src/utils/IniConfig.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { encode, parse } from 'ini' -import { readFileSync, writeFileSync } from 'fs' - -type GenericMap = { [key: string]: unknown } - -export function readConfig(path: string): GenericMap { - return parse(readFileSync(path, { encoding: 'utf-8' })) -} - -export function writeConfig(path: string, iniConfig: string): void { - writeFileSync(path, iniConfig, { encoding: 'utf-8' }) -} - -export function createIniConfig(configObject: GenericMap): string { - return encode(configObject) -} diff --git a/src/utils/Print.ts b/src/utils/Print.ts deleted file mode 100644 index 71fb9e5..0000000 --- a/src/utils/Print.ts +++ /dev/null @@ -1,18 +0,0 @@ -import chalk from 'chalk' - -export class Print { - /* eslint-disable no-console */ - static log(...args: unknown[]) { - console.log(...args) - } - static error(...args: unknown[]) { - console.error(chalk.redBright('x'), chalk.white(...args)) - } - static info(...args: unknown[]) { - console.info(chalk.green('\u2713'), chalk.white(...args)) - } - static warn(...args: unknown[]) { - console.warn(chalk.yellow('!'), chalk.white(...args)) - } - /* eslint-enable no-console */ -} diff --git a/src/utils/index.ts b/src/utils/index.ts deleted file mode 100644 index 3dac83a..0000000 --- a/src/utils/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function createSpaces(spaces = 1): string { - let str = '' - let idx = 0 - while (idx < spaces) { - str += ' ' - idx += 1 - } - return str -} diff --git a/tests/config/config b/tests/config/config deleted file mode 100644 index 37f2703..0000000 --- a/tests/config/config +++ /dev/null @@ -1,15 +0,0 @@ -[default] -region=me-north-3 -output=me-json - -[foo] -region=foo-east-1 -output=foo-json - -[bar] -region=bar-east-2 -output=bar-json - -[me] -region=me-north-3 -output=me-json diff --git a/tests/config/credentials b/tests/config/credentials deleted file mode 100644 index bad73e7..0000000 --- a/tests/config/credentials +++ /dev/null @@ -1,15 +0,0 @@ -[default] -aws_access_key_id=me_id -aws_secret_access_key=me_secret - -[foo] -aws_access_key_id=foo_id -aws_secret_access_key=foo_secret - -[bar] -aws_access_key_id=bar_id -aws_secret_access_key=bar_secret - -[me] -aws_access_key_id=me_id -aws_secret_access_key=me_secret diff --git a/tests/utils/index.test.ts b/tests/utils/index.test.ts deleted file mode 100644 index ae85702..0000000 --- a/tests/utils/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import test from 'ava' -import { createSpaces } from '../../src/utils' - -test('create 2 spaces', t => { - t.is(' ', createSpaces(2)) -}) - -test('create 1 space', t => { - t.is(' ', createSpaces(1)) -}) diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index e4ae20a..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2016", - "module": "commonjs", - "rootDirs": ["src", "tests"], - "allowJs": false, - "checkJs": false, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "strict": true, - "noImplicitAny": true, - "alwaysStrict": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - } -} diff --git a/utils/filepath.go b/utils/filepath.go new file mode 100644 index 0000000..d12d5f6 --- /dev/null +++ b/utils/filepath.go @@ -0,0 +1,27 @@ +package utils + +import ( + "errors" + "os" + "os/user" + "runtime" +) + +func GetHomePath() (string, error) { + if runtime.GOOS == "windows" { + if home := os.Getenv("USERPROFILE"); home != "" { + return home, nil + } + } else { + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + } + + usr, err := user.Current() + if err == nil && usr.HomeDir != "" { + return usr.HomeDir, nil + } + + return "", errors.New("Home Directory could not be located.") +} diff --git a/webpack.config.ts b/webpack.config.ts deleted file mode 100644 index 0596e7f..0000000 --- a/webpack.config.ts +++ /dev/null @@ -1,37 +0,0 @@ -import webpack from 'webpack' -import path from 'path' -import { readFileSync, writeFileSync } from 'fs' - -import { name, version, description } from './package.json' - -console.log('Reading CLI config') -const cliConfigJson = readFileSync( - path.resolve(__dirname, 'src', 'config.json'), - { encoding: 'utf-8' } -) - -const cliConfig = JSON.parse(cliConfigJson) -console.log('Writing CLI config') -writeFileSync( - path.resolve(__dirname, 'src', 'config.json'), - JSON.stringify({ ...cliConfig, name, version, description }, null, 2), - { encoding: 'utf-8' } -) -console.log('Finished Copy CLI config') - -const config: webpack.Configuration = { - entry: './src/index.ts', - target: 'node', - output: { - filename: 'main.js', - path: path.resolve(__dirname, 'build') - }, - resolve: { - extensions: ['.webpack.js', '.ts', '.js'] - }, - module: { - rules: [{ test: /\.ts$/, loader: 'ts-loader', exclude: /node_modules/ }] - } -} - -export default config diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index cbb7e0c..0000000 --- a/yarn.lock +++ /dev/null @@ -1,2902 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.12.13": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/helper-validator-identifier@^7.18.6": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@discoveryjs/json-ext@^0.5.0": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" - integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== - -"@eslint/eslintrc@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356" - integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.15.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.10.5": - version "0.10.5" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.5.tgz#bb679745224745fff1e9a41961c1d45a49f81c04" - integrity sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/gitignore-to-minimatch@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d" - integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA== - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@jest/expect-utils@^29.0.3": - version "29.0.3" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.0.3.tgz#f5bb86f5565bf2dacfca31ccbd887684936045b2" - integrity sha512-i1xUkau7K/63MpdwiRqaxgZOjxYs4f0WMTGJnYwUKubsNRZSeQbLorS7+I4uXVF9KQ5r61BUPAUMZ7Lf66l64Q== - dependencies: - jest-get-type "^29.0.0" - -"@jest/schemas@^29.0.0": - version "29.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" - integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== - dependencies: - "@sinclair/typebox" "^0.24.1" - -"@jest/types@^29.0.3": - version "29.0.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.0.3.tgz#0be78fdddb1a35aeb2041074e55b860561c8ef63" - integrity sha512-coBJmOQvurXjN1Hh5PzF7cmsod0zLIOXpP8KD161mqNlroMhLcwpODiEzi7ZsRl5Z/AIuxpeNm8DCl43F4kz8A== - dependencies: - "@jest/schemas" "^29.0.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" - integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@sinclair/typebox@^0.24.1": - version "0.24.43" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.43.tgz#2e2bce0e5e493aaf639beed0cd6c88cfde7dd3d7" - integrity sha512-1orQTvtazZmsPeBroJjysvsOQCYV2yjWlebkSY38pl5vr2tdLjEJ+LoxITlGNZaH2RE19WlAwQMkH/7C14wLfw== - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== - -"@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.4.6" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.6.tgz#7976f054c1bccfcf514bff0564c0c41df5c08207" - integrity sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== - -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== - -"@types/ini@^1.3.31": - version "1.3.31" - resolved "https://registry.yarnpkg.com/@types/ini/-/ini-1.3.31.tgz#c78541a187bd88d5c73e990711c9d85214800d1b" - integrity sha512-8ecxxaG4AlVEM1k9+BsziMw8UsX0qy3jYI1ad/71RrDZ+rdL6aZB0wLfAuflQiDhkD5o4yJ0uPK3OSUic3fG0w== - -"@types/inquirer@^9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-9.0.1.tgz#b816a888dccbf13bd0053e74d89fbd1fa78fc6c2" - integrity sha512-I4eZdYXpFHj0pAzMndJFQMu/4hCc6Z340au9lvxHofGJnFmVgckxR/t9jRzsOVviajsOmEL+OABx+e0e28IbNw== - dependencies: - "@types/through" "*" - rxjs "^7.2.0" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^29.0.3": - version "29.0.3" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.0.3.tgz#b61a5ed100850686b8d3c5e28e3a1926b2001b59" - integrity sha512-F6ukyCTwbfsEX5F2YmVYmM5TcTHy1q9P5rWlRbrk56KyMh3v9xRGUO3aa8+SkvMi0SHXtASJv1283enXimC0Og== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - -"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/node@*", "@types/node@^18.7.20": - version "18.7.23" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.23.tgz#75c580983846181ebe5f4abc40fe9dfb2d65665f" - integrity sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg== - -"@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== - -"@types/through@*": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895" - integrity sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg== - dependencies: - "@types/node" "*" - -"@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== - -"@types/yargs@^17.0.8": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" - integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz#9f05d42fa8fb9f62304cc2f5c2805e03c01c2620" - integrity sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ== - dependencies: - "@typescript-eslint/scope-manager" "5.38.1" - "@typescript-eslint/type-utils" "5.38.1" - "@typescript-eslint/utils" "5.38.1" - debug "^4.3.4" - ignore "^5.2.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.38.1.tgz#c577f429f2c32071b92dff4af4f5fbbbd2414bd0" - integrity sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw== - dependencies: - "@typescript-eslint/scope-manager" "5.38.1" - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/typescript-estree" "5.38.1" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz#f87b289ef8819b47189351814ad183e8801d5764" - integrity sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ== - dependencies: - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/visitor-keys" "5.38.1" - -"@typescript-eslint/type-utils@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz#7f038fcfcc4ade4ea76c7c69b2aa25e6b261f4c1" - integrity sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw== - dependencies: - "@typescript-eslint/typescript-estree" "5.38.1" - "@typescript-eslint/utils" "5.38.1" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.38.1.tgz#74f9d6dcb8dc7c58c51e9fbc6653ded39e2e225c" - integrity sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg== - -"@typescript-eslint/typescript-estree@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz#657d858d5d6087f96b638ee383ee1cff52605a1e" - integrity sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g== - dependencies: - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/visitor-keys" "5.38.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.38.1.tgz#e3ac37d7b33d1362bb5adf4acdbe00372fb813ef" - integrity sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA== - dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.38.1" - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/typescript-estree" "5.38.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - -"@typescript-eslint/visitor-keys@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz#508071bfc6b96d194c0afe6a65ad47029059edbc" - integrity sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA== - dependencies: - "@typescript-eslint/types" "5.38.1" - eslint-visitor-keys "^3.3.0" - -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== - -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== - -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== - -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== - -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@xtuc/long" "4.2.2" - -"@webpack-cli/configtest@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" - integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== - -"@webpack-cli/info@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" - integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== - dependencies: - envinfo "^7.7.3" - -"@webpack-cli/serve@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" - integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1, acorn-walk@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -aggregate-error@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-4.0.1.tgz#25091fe1573b9e0be892aeda15c7c66a545f758e" - integrity sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w== - dependencies: - clean-stack "^4.0.0" - indent-string "^5.0.0" - -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6" - integrity sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA== - dependencies: - type-fest "^1.0.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -ansi-styles@^6.0.0, ansi-styles@^6.1.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.1.tgz#63cd61c72283a71cb30bd881dbb60adada74bc70" - integrity sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg== - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -arrgv@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/arrgv/-/arrgv-1.0.2.tgz#025ed55a6a433cad9b604f8112fc4292715a6ec0" - integrity sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw== - -arrify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-3.0.0.tgz#ccdefb8eaf2a1d2ab0da1ca2ce53118759fd46bc" - integrity sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw== - -ava@^4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/ava/-/ava-4.3.3.tgz#4ddcb650ed059e4e999a4b640de53ff00f4a008b" - integrity sha512-9Egq/d9R74ExrWohHeqUlexjDbgZJX5jA1Wq4KCTqc3wIfpGEK79zVy4rBtofJ9YKIxs4PzhJ8BgbW5PlAYe6w== - dependencies: - acorn "^8.7.1" - acorn-walk "^8.2.0" - ansi-styles "^6.1.0" - arrgv "^1.0.2" - arrify "^3.0.0" - callsites "^4.0.0" - cbor "^8.1.0" - chalk "^5.0.1" - chokidar "^3.5.3" - chunkd "^2.0.1" - ci-info "^3.3.1" - ci-parallel-vars "^1.0.1" - clean-yaml-object "^0.1.0" - cli-truncate "^3.1.0" - code-excerpt "^4.0.0" - common-path-prefix "^3.0.0" - concordance "^5.0.4" - currently-unhandled "^0.4.1" - debug "^4.3.4" - del "^6.1.1" - emittery "^0.11.0" - figures "^4.0.1" - globby "^13.1.1" - ignore-by-default "^2.1.0" - indent-string "^5.0.0" - is-error "^2.2.2" - is-plain-object "^5.0.0" - is-promise "^4.0.0" - matcher "^5.0.0" - mem "^9.0.2" - ms "^2.1.3" - p-event "^5.0.1" - p-map "^5.4.0" - picomatch "^2.3.1" - pkg-conf "^4.0.0" - plur "^5.1.0" - pretty-ms "^7.0.1" - resolve-cwd "^3.0.0" - slash "^3.0.0" - stack-utils "^2.0.5" - strip-ansi "^7.0.1" - supertap "^3.0.1" - temp-dir "^2.0.0" - write-file-atomic "^4.0.1" - yargs "^17.5.1" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bl@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-5.0.0.tgz#6928804a41e9da9034868e1c50ca88f21f57aea2" - integrity sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ== - dependencies: - buffer "^6.0.3" - inherits "^2.0.4" - readable-stream "^3.4.0" - -blueimp-md5@^2.10.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0" - integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.14.5: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== - dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" - -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -callsites@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-4.0.0.tgz#8014cea4fedfe681a30e2f7d2d557dd95808a92a" - integrity sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ== - -caniuse-lite@^1.0.30001400: - version "1.0.30001412" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz#30f67d55a865da43e0aeec003f073ea8764d5d7c" - integrity sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA== - -cbor@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" - integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== - dependencies: - nofilter "^3.1.0" - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^5.0.0, chalk@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" - integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -chunkd@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/chunkd/-/chunkd-2.0.1.tgz#49cd1d7b06992dc4f7fccd962fe2a101ee7da920" - integrity sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ== - -ci-info@^3.2.0, ci-info@^3.3.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.4.0.tgz#b28484fd436cbc267900364f096c9dc185efb251" - integrity sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug== - -ci-parallel-vars@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz#e87ff0625ccf9d286985b29b4ada8485ca9ffbc2" - integrity sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg== - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -clean-stack@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-4.2.0.tgz#c464e4cde4ac789f4e0735c5d75beb49d7b30b31" - integrity sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg== - dependencies: - escape-string-regexp "5.0.0" - -clean-yaml-object@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" - integrity sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw== - -cli-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" - integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== - dependencies: - restore-cursor "^4.0.0" - -cli-spinners@^2.6.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" - integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== - -cli-truncate@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" - integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== - dependencies: - slice-ansi "^5.0.0" - string-width "^5.0.0" - -cli-width@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.0.0.tgz#a5622f6a3b0a9e3e711a25f099bf2399f608caf6" - integrity sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw== - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== - -code-excerpt@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-4.0.0.tgz#2de7d46e98514385cb01f7b3b741320115f4c95e" - integrity sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA== - dependencies: - convert-to-spaces "^2.0.1" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colorette@^2.0.14: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c" - integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw== - -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -concordance@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/concordance/-/concordance-5.0.4.tgz#9896073261adced72f88d60e4d56f8efc4bbbbd2" - integrity sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw== - dependencies: - date-time "^3.1.0" - esutils "^2.0.3" - fast-diff "^1.2.0" - js-string-escape "^1.0.1" - lodash "^4.17.15" - md5-hex "^3.0.1" - semver "^7.3.2" - well-known-symbols "^2.0.0" - -convert-to-spaces@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz#61a6c98f8aa626c16b296b862a91412a33bceb6b" - integrity sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng== - dependencies: - array-find-index "^1.0.1" - -date-time@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/date-time/-/date-time-3.1.0.tgz#0d1e934d170579f481ed8df1e2b8ff70ee845e1e" - integrity sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg== - dependencies: - time-zone "^1.0.0" - -debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA== - dependencies: - clone "^1.0.2" - -del@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" - integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - -diff-sequences@^29.0.0: - version "29.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.0.0.tgz#bae49972ef3933556bcb0800b72e8579d19d9e4f" - integrity sha512-7Qe/zd1wxSDL4D/X/FPjOMB+ZMDt71W94KYaq05I2l0oQqgXgs7s4ftYYmV38gBSrPz2vcygxfs1xn0FT+rKNA== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -electron-to-chromium@^1.4.251: - version "1.4.265" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.265.tgz#45630ae190228f945ff79c060b99574b1347e5a7" - integrity sha512-38KaYBNs0oCzWCpr6j7fY/W9vF0vSp4tKFIshQTgdZMhUpkxgotkQgjJP6iGMdmlsgMs3i0/Hkko4UXLTrkYVQ== - -emittery@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.11.0.tgz#eb5f756a200d3431de2c6e850cb2d8afd97a03b9" - integrity sha512-S/7tzL6v5i+4iJd627Nhv9cLFIo5weAIlGccqJFpnBoDB8U1TF2k5tez4J/QNuxyyhWuFqHg1L84Kd3m7iXg6g== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -envinfo@^7.7.3: - version "7.8.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" - integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== - -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@5.0.0, escape-string-regexp@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" - integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^8.24.0: - version "8.24.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.24.0.tgz#489516c927a5da11b3979dbfb2679394523383c8" - integrity sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ== - dependencies: - "@eslint/eslintrc" "^1.3.2" - "@humanwhocodes/config-array" "^0.10.5" - "@humanwhocodes/gitignore-to-minimatch" "^1.0.2" - "@humanwhocodes/module-importer" "^1.0.1" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.1" - globals "^13.15.0" - globby "^11.1.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" - integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2, esutils@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -expect@^29.0.0: - version "29.0.3" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.0.3.tgz#6be65ddb945202f143c4e07c083f4f39f3bd326f" - integrity sha512-t8l5DTws3212VbmPL+tBFXhjRHLmctHB0oQbL8eUc6S7NzZtYUhycrFO9mkxA0ZUC6FAWdNi7JchJSkODtcu1Q== - dependencies: - "@jest/expect-utils" "^29.0.3" - jest-get-type "^29.0.0" - jest-matcher-utils "^29.0.3" - jest-message-util "^29.0.3" - jest-util "^29.0.3" - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.2.11, fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastest-levenshtein@^1.0.12: - version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" - integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -figures@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/figures/-/figures-4.0.1.tgz#27b26609907bc888b3e3b0ef5403643f80aa2518" - integrity sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w== - dependencies: - escape-string-regexp "^5.0.0" - is-unicode-supported "^1.2.0" - -figures@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-5.0.0.tgz#126cd055052dea699f8a54e8c9450e6ecfc44d5f" - integrity sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg== - dependencies: - escape-string-regexp "^5.0.0" - is-unicode-supported "^1.2.0" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-up@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" - integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== - dependencies: - locate-path "^7.1.0" - path-exists "^5.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^13.15.0: - version "13.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== - dependencies: - type-fest "^0.20.2" - -globby@^11.0.1, globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -globby@^13.1.1: - version "13.1.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" - integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.2.11" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^4.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore-by-default@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-2.1.0.tgz#c0e0de1a99b6065bdc93315a6f728867981464db" - integrity sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw== - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -indent-string@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5" - integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.1.tgz#c76ec81007875bc44d544ff7a11a55d12294102d" - integrity sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ== - -inquirer@^9.1.2: - version "9.1.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-9.1.2.tgz#37f5486f3de0e38820aad83a1f75c52c747e2f9a" - integrity sha512-Hj2Ml1WpxKJU2npP2Rj0OURGkHV+GtNW2CwFdHDiXlqUBAUrWTcZHxCkFywX/XHzOS7wrG/kExgJFbUkVgyHzg== - dependencies: - ansi-escapes "^5.0.0" - chalk "^5.0.1" - cli-cursor "^4.0.0" - cli-width "^4.0.0" - external-editor "^3.0.3" - figures "^5.0.0" - lodash "^4.17.21" - mute-stream "0.0.8" - ora "^6.1.2" - run-async "^2.4.0" - rxjs "^7.5.6" - string-width "^5.1.2" - strip-ansi "^7.0.1" - through "^2.3.6" - wrap-ansi "^8.0.1" - -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - -irregular-plurals@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.3.0.tgz#67d0715d4361a60d9fd9ee80af3881c631a31ee2" - integrity sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - -is-error@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" - integrity sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-fullwidth-code-point@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" - integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-interactive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" - integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-promise@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" - integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== - -is-unicode-supported@^1.1.0, is-unicode-supported@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" - integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -jest-diff@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.0.3.tgz#41cc02409ad1458ae1bf7684129a3da2856341ac" - integrity sha512-+X/AIF5G/vX9fWK+Db9bi9BQas7M9oBME7egU7psbn4jlszLFCu0dW63UgeE6cs/GANq4fLaT+8sGHQQ0eCUfg== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.0.0" - jest-get-type "^29.0.0" - pretty-format "^29.0.3" - -jest-get-type@^29.0.0: - version "29.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.0.0.tgz#843f6c50a1b778f7325df1129a0fd7aa713aef80" - integrity sha512-83X19z/HuLKYXYHskZlBAShO7UfLFXu/vWajw9ZNJASN32li8yHMaVGAQqxFW1RCFOkB7cubaL6FaJVQqqJLSw== - -jest-matcher-utils@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.0.3.tgz#b8305fd3f9e27cdbc210b21fc7dbba92d4e54560" - integrity sha512-RsR1+cZ6p1hDV4GSCQTg+9qjeotQCgkaleIKLK7dm+U4V/H2bWedU3RAtLm8+mANzZ7eDV33dMar4pejd7047w== - dependencies: - chalk "^4.0.0" - jest-diff "^29.0.3" - jest-get-type "^29.0.0" - pretty-format "^29.0.3" - -jest-message-util@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.0.3.tgz#f0254e1ffad21890c78355726202cc91d0a40ea8" - integrity sha512-7T8JiUTtDfppojosORAflABfLsLKMLkBHSWkjNQrjIltGoDzNGn7wEPOSfjqYAGTYME65esQzMJxGDjuLBKdOg== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.0.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.0.3" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-util@^29.0.0, jest-util@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.0.3.tgz#06d1d77f9a1bea380f121897d78695902959fbc0" - integrity sha512-Q0xaG3YRG8QiTC4R6fHjHQPaPpz9pJBEi0AeOE4mQh/FuWOijFjGXMMOfQEaU9i3z76cNR7FobZZUQnL6IyfdQ== - dependencies: - "@jest/types" "^29.0.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -js-sdsl@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6" - integrity sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw== - -js-string-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-parse-even-better-errors@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -load-json-file@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-7.0.1.tgz#a3c9fde6beffb6bedb5acf104fad6bb1604e1b00" - integrity sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ== - -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -locate-path@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.1.1.tgz#8e1e5a75c7343770cef02ff93c4bf1f0aa666374" - integrity sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg== - dependencies: - p-locate "^6.0.0" - -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash@^4.17.15, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -log-symbols@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" - integrity sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA== - dependencies: - chalk "^5.0.0" - is-unicode-supported "^1.1.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-error@1.x, make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -map-age-cleaner@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - -matcher@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-5.0.0.tgz#cd82f1c7ae7ee472a9eeaf8ec7cac45e0fe0da62" - integrity sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw== - dependencies: - escape-string-regexp "^5.0.0" - -md5-hex@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" - integrity sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw== - dependencies: - blueimp-md5 "^2.10.0" - -mem@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/mem/-/mem-9.0.2.tgz#bbc2d40be045afe30749681e8f5d554cee0c0354" - integrity sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A== - dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^4.0.0" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.0, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.27: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - -nofilter@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" - integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -ora@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/ora/-/ora-6.1.2.tgz#7b3c1356b42fd90fb1dad043d5dbe649388a0bf5" - integrity sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw== - dependencies: - bl "^5.0.0" - chalk "^5.0.0" - cli-cursor "^4.0.0" - cli-spinners "^2.6.1" - is-interactive "^2.0.0" - is-unicode-supported "^1.1.0" - log-symbols "^5.1.0" - strip-ansi "^7.0.1" - wcwidth "^1.0.1" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== - -p-event@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-5.0.1.tgz#614624ec02ae7f4f13d09a721c90586184af5b0c" - integrity sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ== - dependencies: - p-timeout "^5.0.2" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-map@^5.4.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-5.5.0.tgz#054ca8ca778dfa4cf3f8db6638ccb5b937266715" - integrity sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg== - dependencies: - aggregate-error "^4.0.0" - -p-timeout@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-5.1.0.tgz#b3c691cf4415138ce2d9cfe071dba11f0fee085b" - integrity sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew== - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-ms@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" - integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pkg-conf@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-4.0.0.tgz#63ace00cbacfa94c2226aee133800802d3e3b80c" - integrity sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w== - dependencies: - find-up "^6.0.0" - load-json-file "^7.0.0" - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -plur@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/plur/-/plur-5.1.0.tgz#bff58c9f557b9061d60d8ebf93959cf4b08594ae" - integrity sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg== - dependencies: - irregular-plurals "^3.3.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -pretty-format@^29.0.0, pretty-format@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.0.3.tgz#23d5f8cabc9cbf209a77d49409d093d61166a811" - integrity sha512-cHudsvQr1K5vNVLbvYF/nv3Qy/F/BcEKxGuIeMiVMRHxPOO1RxXooP8g/ZrwAp7Dx+KdMZoOc7NxLHhMrP2f9Q== - dependencies: - "@jest/schemas" "^29.0.0" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -pretty-ms@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8" - integrity sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q== - dependencies: - parse-ms "^2.1.0" - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -readable-stream@^3.4.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -rechoir@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" - integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== - dependencies: - resolve "^1.9.0" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.9.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -restore-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" - integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -rxjs@^7.2.0, rxjs@^7.5.6: - version "7.5.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" - integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== - dependencies: - tslib "^2.1.0" - -safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" - -serialize-error@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" - integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw== - dependencies: - type-fest "^0.13.1" - -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^3.0.2, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - -slice-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" - integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== - dependencies: - ansi-styles "^6.0.0" - is-fullwidth-code-point "^4.0.0" - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.3, stack-utils@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== - dependencies: - escape-string-regexp "^2.0.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supertap@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/supertap/-/supertap-3.0.1.tgz#aa89e4522104402c6e8fe470a7d2db6dc4037c6a" - integrity sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw== - dependencies: - indent-string "^5.0.0" - js-yaml "^3.14.1" - serialize-error "^7.0.1" - strip-ansi "^7.0.1" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -terser-webpack-plugin@^5.1.3: - version "5.3.6" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" - integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== - dependencies: - "@jridgewell/trace-mapping" "^0.3.14" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - terser "^5.14.1" - -terser@^5.14.1: - version "5.15.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" - integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== - dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" - commander "^2.20.0" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - -time-zone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" - integrity sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -ts-jest@^29.0.2: - version "29.0.2" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.2.tgz#0c45a1ac45d14f8b3bf89bca9048a2840c7bd5ad" - integrity sha512-P03IUItnAjG6RkJXtjjD5pu0TryQFOwcb1YKmW63rO19V0UFqL3wiXZrmR5D7qYjI98btzIOAcYafLZ0GHAcQg== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.1" - lodash.memoize "4.x" - make-error "1.x" - semver "7.x" - yargs-parser "^21.0.1" - -ts-loader@^9.4.1: - version "9.4.1" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.1.tgz#b6f3d82db0eac5a8295994f8cb5e4940ff6b1060" - integrity sha512-384TYAqGs70rn9F0VBnh6BPTfhga7yFNdC5gXbQpDrBj9/KsT4iRkGqKXhziofHOlE2j6YEaiTYVGKKvPhGWvw== - dependencies: - chalk "^4.1.0" - enhanced-resolve "^5.0.0" - micromatch "^4.0.0" - semver "^7.3.4" - -ts-node@^10.9.1: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" - integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^1.0.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" - integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== - -typescript@^4.8.3: - version "4.8.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== - -update-browserslist-db@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" - integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== - dependencies: - defaults "^1.0.3" - -webpack-cli@^4.10.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" - integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== - dependencies: - "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.2.0" - "@webpack-cli/info" "^1.5.0" - "@webpack-cli/serve" "^1.7.0" - colorette "^2.0.14" - commander "^7.0.0" - cross-spawn "^7.0.3" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" - webpack-merge "^5.7.3" - -webpack-merge@^5.7.3: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.74.0: - version "5.74.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" - integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - -well-known-symbols@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-2.0.0.tgz#e9c7c07dbd132b7b84212c8174391ec1f9871ba5" - integrity sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q== - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" - integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.0.0, yargs-parser@^21.0.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.5.1: - version "17.5.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" - integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== From 6fb51ca7d2093939a2645f26506eee899652e75b Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sat, 17 May 2025 01:51:33 +0100 Subject: [PATCH 02/31] use strconv.itoa to safely convert int to str --- lib/aws_import.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/aws_import.go b/lib/aws_import.go index 496682d..90d22c4 100644 --- a/lib/aws_import.go +++ b/lib/aws_import.go @@ -5,6 +5,7 @@ import ( "log" "os" "path" + "strconv" "strings" "github.com/rodpadev/aws-profiles/utils" @@ -66,9 +67,8 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { key := strings.TrimSpace(string(line[:assignIndex])) value := strings.TrimSpace(string(line[assignIndex+1:])) - if currentSection == "" { - currentSection = "no_category_" + string(i) + currentSection = "no_category_" + strconv.Itoa(i) if _, exists := result[currentSection]; !exists { result[currentSection] = map[string]string{} } From 89644a5545ce5560f579f0d6e8abf89b8cc99e80 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 10:27:18 +0100 Subject: [PATCH 03/31] implement BackupAWSProfileData and add utility functions for file operations --- lib/aws_import.go | 24 ++++++++++++++++++++++++ utils/{filepath.go => file.go} | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) rename utils/{filepath.go => file.go} (57%) diff --git a/lib/aws_import.go b/lib/aws_import.go index 90d22c4..bfe3cb6 100644 --- a/lib/aws_import.go +++ b/lib/aws_import.go @@ -2,6 +2,7 @@ package lib import ( "bytes" + "fmt" "log" "os" "path" @@ -11,6 +12,29 @@ import ( "github.com/rodpadev/aws-profiles/utils" ) +func BackupAWSProfileData() error { + homeDir, err := utils.GetHomePath() + if err != nil { + log.Fatal(err) + } + + dirPath := path.Join(homeDir, ".aws") + configPath := path.Join(dirPath, "config") + credentialsPath := path.Join(dirPath, "credentials") + + backupConfigPath := fmt.Sprintf("%s.backup", configPath) + backupCredentialsPathPath := fmt.Sprintf("%s.backup", credentialsPath) + + if err := utils.CopyFile(configPath, backupConfigPath); err != nil { + return err + } + if err := utils.CopyFile(credentialsPath, backupCredentialsPathPath); err != nil { + return err + } + + return nil +} + func LoadAWSProfileData() ([][]byte, error) { homeDir, err := utils.GetHomePath() diff --git a/utils/filepath.go b/utils/file.go similarity index 57% rename from utils/filepath.go rename to utils/file.go index d12d5f6..6106811 100644 --- a/utils/filepath.go +++ b/utils/file.go @@ -2,6 +2,7 @@ package utils import ( "errors" + "io" "os" "os/user" "runtime" @@ -25,3 +26,24 @@ func GetHomePath() (string, error) { return "", errors.New("Home Directory could not be located.") } + +func CopyFile(path string, destination string) error { + srcFile, err := os.Open(path) + if err != nil { + return err + } + defer srcFile.Close() + + dstFile, err := os.Create(destination) + if err != nil { + return err + } + defer dstFile.Close() + + _, err = io.Copy(dstFile, srcFile) + if err != nil { + return err + } + + return nil +} From 650ceec077ac7230dddbcade8f4d5d5377178953 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 12:56:26 +0100 Subject: [PATCH 04/31] update: rename file --- lib/{aws_import.go => aws_interop.go} | 54 ++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 5 deletions(-) rename lib/{aws_import.go => aws_interop.go} (62%) diff --git a/lib/aws_import.go b/lib/aws_interop.go similarity index 62% rename from lib/aws_import.go rename to lib/aws_interop.go index bfe3cb6..674a97d 100644 --- a/lib/aws_import.go +++ b/lib/aws_interop.go @@ -6,17 +6,16 @@ import ( "log" "os" "path" + "reflect" "strconv" "strings" "github.com/rodpadev/aws-profiles/utils" ) -func BackupAWSProfileData() error { - homeDir, err := utils.GetHomePath() - if err != nil { - log.Fatal(err) - } +const DEFAULT_SECTION = "[default]" + +func BackupAWSProfileData(homeDir string) error { dirPath := path.Join(homeDir, ".aws") configPath := path.Join(dirPath, "config") @@ -67,6 +66,7 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { var currentSection string for i, line := range lines { + line = bytes.TrimSpace(line) // remove comments and ignore empty liens if len(line) == 0 || line[0] == '#' || line[0] == ';' { @@ -111,3 +111,47 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { return result } + +func EncodeAWSProfileData(selectedProfile Profile) ([2]string, error) { + configFile := DEFAULT_SECTION + "\n" + credentialsFile := DEFAULT_SECTION + "\n" + + credVal := reflect.ValueOf(selectedProfile.Credential) + credType := reflect.TypeOf(selectedProfile.Credential) + + for i := 0; i < credVal.NumField(); i++ { + tag := credType.Field(i).Tag.Get("json") + value := credVal.Field(i).String() + credentialsFile += fmt.Sprintf("%s = %s\n", tag, value) + } + + configVal := reflect.ValueOf(selectedProfile.Config) + configType := reflect.TypeOf(selectedProfile.Config) + + for i := 0; i < configVal.NumField(); i++ { + tag := configType.Field(i).Tag.Get("json") + val := configVal.Field(i).String() + if val != "" { + configFile += fmt.Sprintf("%s = %s\n", tag, val) + } + } + + return [2]string{configFile, credentialsFile}, nil +} + +func SaveAWSProfileData(homeDir string, awsData [2]string) error { + + configFile := awsData[0] + credentialsFile := awsData[1] + + awsDir := path.Join(homeDir, ".aws") + + if err := os.WriteFile(path.Join(awsDir, "config"), []byte(configFile), 0600); err != nil { + return err + } + if err := os.WriteFile(path.Join(awsDir, "credentials"), []byte(credentialsFile), 0600); err != nil { + return err + } + + return nil +} From 6827b4158125db44a9f820855605f370da5b279a Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 12:56:44 +0100 Subject: [PATCH 05/31] tests: add integratio test for main flow --- lib/lib_integration_test.go | 204 ++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 lib/lib_integration_test.go diff --git a/lib/lib_integration_test.go b/lib/lib_integration_test.go new file mode 100644 index 0000000..3f712ce --- /dev/null +++ b/lib/lib_integration_test.go @@ -0,0 +1,204 @@ +package lib + +import ( + "os" + "path" + "testing" +) + +func TestIntegrationFlow(t *testing.T) { + // Create temp directory for test + tempDir, err := os.MkdirTemp("", "aws-profiles-test") + if err != nil { + t.Fatalf("Failed to create temp directory: %v", err) + } + defer os.RemoveAll(tempDir) + + // Create mock AWS directory + awsDir := path.Join(tempDir, ".aws") + err = os.Mkdir(awsDir, 0755) + if err != nil { + t.Fatalf("Failed to create mock .aws directory: %v", err) + } + + // Create mock config file + mockConfig := + ` + [default] + region = us-west-2 + output = json + + [dev] + region = us-east-1 + output = text + + [prod] + region = us-west-1 + output = json + ` + + err = os.WriteFile(path.Join(awsDir, "config"), []byte(mockConfig), 0644) + if err != nil { + t.Fatalf("Failed to create mock config file: %v", err) + } + + // Create mock credentials file + mockCredentials := + ` + [default] + aws_access_key_id = default-access-key + aws_secret_access_key = default-secret-key + + [dev] + aws_access_key_id = dev-access-key + aws_secret_access_key = dev-secret-key + + [prod] + aws_access_key_id = prod-access-key + aws_secret_access_key = prod-secret-key + ` + + err = os.WriteFile(path.Join(awsDir, "credentials"), []byte(mockCredentials), 0644) + if err != nil { + t.Fatalf("Failed to create mock credentials file: %v", err) + } + + // Create a store file path + storePath := path.Join(tempDir, "store.json") + + // Test BackupAWSProfileData + err = BackupAWSProfileData(tempDir) + if err != nil { + t.Fatalf("Failed to backup AWS profile data: %v", err) + } + + // Verify backup files were created + _, err = os.Stat(path.Join(awsDir, "config.backup")) + if err != nil { + t.Errorf("Config backup file was not created: %v", err) + } + _, err = os.Stat(path.Join(awsDir, "credentials.backup")) + if err != nil { + t.Errorf("Credentials backup file was not created: %v", err) + } + + // Override LoadAWSProfileData for testing + originalHomePath := os.Getenv("HOME") + os.Setenv("HOME", tempDir) + defer os.Setenv("HOME", originalHomePath) + + // Load AWS profile data + data, err := LoadAWSProfileData() + if err != nil { + t.Fatalf("Failed to load AWS profile data: %v", err) + } + + // Verify data was loaded + if len(data) != 2 { + t.Fatalf("Expected 2 data items, got %d", len(data)) + } + + // Parse AWS profile data + parsedData := ParseAWSProfileData(data) + + // Verify parsed data + if len(parsedData) != 3 { // default, profile dev, profile prod, dev, prod + t.Fatalf("Expected 3 profiles, got %d", len(parsedData)) + } + + // Check if default profile exists + defaultProfile, exists := parsedData["default"] + if !exists { + t.Fatalf("Default profile not found in parsed data") + } + + // Verify default profile values + if defaultProfile["region"] != "us-west-2" { + t.Errorf("Expected default region to be us-west-2, got %s", defaultProfile["region"]) + } + if defaultProfile["aws_access_key_id"] != "default-access-key" { + t.Errorf("Expected default access key to be default-access-key, got %s", defaultProfile["aws_access_key_id"]) + } + + // Build profile map + profileMap, err := BuildProfileMap(parsedData) + if err != nil { + t.Fatalf("Failed to build profile map: %v", err) + } + + // Verify profile map + if len(profileMap) != 3 { + t.Fatalf("Expected 3 profiles in map, got %d", len(profileMap)) + } + + // Check default profile in map + defaultMapProfile, exists := profileMap["default"] + if !exists { + t.Fatalf("Default profile not found in profile map") + } + + // Verify default profile in map + if defaultMapProfile.Config.Region != "us-west-2" { + t.Errorf("Expected default region in map to be us-west-2, got %s", defaultMapProfile.Config.Region) + } + if defaultMapProfile.Credential.AccessKey != "default-access-key" { + t.Errorf("Expected default access key in map to be default-access-key, got %s", defaultMapProfile.Credential.AccessKey) + } + + // Test saving to store + err = SaveStore(profileMap, storePath) + if err != nil { + t.Fatalf("Failed to save profile map to store: %v", err) + } + + // Verify store file was created + _, err = os.Stat(storePath) + if err != nil { + t.Errorf("Store file was not created: %v", err) + } + + // Test loading from store + loadedProfileMap, err := LoadStore(storePath) + if err != nil { + t.Fatalf("Failed to load profile map from store: %v", err) + } + + // Verify loaded profile map + if len(loadedProfileMap) != len(profileMap) { + t.Fatalf("Expected %d profiles in loaded map, got %d", len(profileMap), len(loadedProfileMap)) + } + + // Test encoding profile data + encodedData, err := EncodeAWSProfileData(defaultMapProfile) + if err != nil { + t.Fatalf("Failed to encode AWS profile data: %v", err) + } + + // Verify encoded data + if len(encodedData) != 2 { + t.Fatalf("Expected 2 encoded data items, got %d", len(encodedData)) + } + + // Test saving AWS profile data + err = SaveAWSProfileData(tempDir, encodedData) + if err != nil { + t.Fatalf("Failed to save AWS profile data: %v", err) + } + + // Verify saved files + configContent, err := os.ReadFile(path.Join(awsDir, "config")) + if err != nil { + t.Fatalf("Failed to read saved config file: %v", err) + } + if string(configContent) != encodedData[0] { + t.Errorf("Saved config content does not match encoded data") + } + + credContent, err := os.ReadFile(path.Join(awsDir, "credentials")) + if err != nil { + t.Fatalf("Failed to read saved credentials file: %v", err) + } + if string(credContent) != encodedData[1] { + t.Errorf("Saved credentials content does not match encoded data") + } +} From 13559119a74b8c4492ce187653832c6d96d099fb Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 12:56:55 +0100 Subject: [PATCH 06/31] refactor: remove unused files and clean up go.mod --- go.mod | 2 -- lib/README.md | 63 --------------------------------------------------- main.go | 29 ------------------------ 3 files changed, 94 deletions(-) delete mode 100644 lib/README.md delete mode 100644 main.go diff --git a/go.mod b/go.mod index e1337fa..fe15a3f 100644 --- a/go.mod +++ b/go.mod @@ -3,5 +3,3 @@ module github.com/rodpadev/aws-profiles go 1.23.0 toolchain go1.23.9 - -replace github.com/rodpadev/aws-profiles => ./ \ No newline at end of file diff --git a/lib/README.md b/lib/README.md deleted file mode 100644 index c2155b9..0000000 --- a/lib/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# `lib` — AWS Profiles Library - -This package provides a programmatic interface for managing custom AWS profiles stored outside of `~/.aws`. It is designed to power the `aws-profiles v2` project, enabling secure and flexible profile management with first-class support for native encryption and CLI/TUI integration. - ---- - -## 🔧 Features - -- **Add, edit, remove** AWS profiles -- Store profiles in a **separate dotfile** (not `~/.aws`) -- Support the following fields per profile: - - `name` - - `region` - - `role_arn` - - `access_key_id` - - `secret_access_key` - ---- - -## 🔐 Security - -- Profiles can be **optionally encrypted**: - - Uses **system-native credential storage** (e.g., macOS Keychain, Windows Credential Manager) when available - - Falls back to **password-based encryption** if system keyring is not supported - ---- - -## 🔁 AWS Migration Support - -- One-time import of profiles from `~/.aws/config` and `~/.aws/credentials` - - A backup will be made and will require manual deletion. -- Imported profiles are moved into the new config file -- Leaves behind an **empty default profile** in `.aws` - ---- - -## ✅ Profile Activation - -- Set a profile as "active" to: - - Recreate and write a minimal `.aws/config` and `.aws/credentials` - - Overwrite the files cleanly without concern for legacy format - ---- - -## 📦 Usage - -TODO LATER - ---- - -## 📁 Storage - -Profiles are saved in: - -``` -~/.aws-profiles/config.json -``` - -Or, if encryption is enabled: - -``` -~/.aws-profiles/config-encrypted.bin -``` \ No newline at end of file diff --git a/main.go b/main.go deleted file mode 100644 index efb856c..0000000 --- a/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "encoding/json" - "log" - - "github.com/rodpadev/aws-profiles/lib" -) - -func main() { - data, err := lib.LoadAWSProfileData() - if err != nil { - log.Printf("ERR@LoadAWSProfileData") - log.Fatal(err) - } - - parsed := lib.ParseAWSProfileData(data) - - profileMap, err := lib.BuildProfileMap(parsed) - if err != nil { - log.Printf("ERR@BuildProfileMap") - log.Fatal(err) - } - - if jsonBytes, err := json.MarshalIndent(profileMap, "", " "); err == nil { - log.Println(string(jsonBytes)) - } - -} From 82f56a2f81adc3fc4470e393486b644e744719c6 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 16:33:40 +0100 Subject: [PATCH 07/31] setup basic tui layout --- go.mod | 24 ++++++++++ go.sum | 45 ++++++++++++++++++ main.go | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 main.go diff --git a/go.mod b/go.mod index fe15a3f..2c86b4f 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,27 @@ module github.com/rodpadev/aws-profiles go 1.23.0 toolchain go1.23.9 + +require github.com/charmbracelet/bubbletea v1.3.5 + +require ( + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + golang.org/x/sync v0.13.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.3.8 // indirect +) diff --git a/go.sum b/go.sum index e69de29..f9453b6 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,45 @@ +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc= +github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= diff --git a/main.go b/main.go new file mode 100644 index 0000000..007ed55 --- /dev/null +++ b/main.go @@ -0,0 +1,139 @@ +package main + +import ( + "fmt" + "os" + + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + +const ( + leftPaneWidth int = 25 + footerHeight int = 4 +) + +type layoutModel struct { + width, height int + leftPane tea.Model + rightPane tea.Model + footer tea.Model +} + +func (m layoutModel) Init() tea.Cmd { + return tea.Batch( + m.leftPane.Init(), + m.rightPane.Init(), + m.footer.Init(), + ) +} + +func (m layoutModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.WindowSizeMsg: + m.width = msg.Width + m.height = msg.Height + case tea.KeyMsg: + switch msg.String() { + case "q", "ctrl+c": + return m, tea.Quit + } + + } + + var cmds []tea.Cmd + + m.leftPane, cmds = updateModel(m.leftPane, msg, cmds) + m.rightPane, cmds = updateModel(m.rightPane, msg, cmds) + m.footer, cmds = updateModel(m.footer, msg, cmds) + + return m, tea.Batch(cmds...) +} + +func updateModel(child tea.Model, msg tea.Msg, cmds []tea.Cmd) (tea.Model, []tea.Cmd) { + newModel, cmd := child.Update(msg) + return newModel, append(cmds, cmd) +} + +func (m layoutModel) View() string { + heightWithoutBorder := m.height - 2 + footerVisibleHeight := footerHeight - 1 + mainHeight := heightWithoutBorder - footerVisibleHeight - 2 + + right := lipgloss.NewStyle(). + Width(m.width - leftPaneWidth - 6). + Height(mainHeight - 2). + Border(lipgloss.NormalBorder()). + Render(m.rightPane.View()) + + left := lipgloss.NewStyle(). + Width(leftPaneWidth). + Height(mainHeight - 2). + Border(lipgloss.NormalBorder()). + Render(m.leftPane.View()) + + footer := lipgloss.NewStyle(). + Width(m.width - 2). + Height(footerHeight). + Border(lipgloss.NormalBorder()). + BorderBottom(false). + BorderRight(false). + BorderLeft(false). + Render(m.footer.View()) + + topRow := lipgloss.NewStyle().Height(mainHeight).Width(m.width - 2).Render( + lipgloss.JoinHorizontal(lipgloss.Top, left, right), + ) + + mainRender := lipgloss.JoinVertical(lipgloss.Top, topRow, footer) + + if m.width < 75 || m.height < 25 { + mainRender = lipgloss.Place(m.width, heightWithoutBorder, lipgloss.Center, lipgloss.Center, "Too Small! Expand your terminal") + } + + return lipgloss.NewStyle(). + Height(heightWithoutBorder). + Width(m.width - 2). + Border(lipgloss.NormalBorder()). + Render(mainRender) + +} + +func initModel() layoutModel { + return layoutModel{ + leftPane: dummyLayout{ + debugString: "left", + }, + rightPane: dummyLayout{ + debugString: "right", + }, + footer: dummyLayout{ + debugString: "footer", + }, + } +} + +type dummyLayout struct { + debugString string +} + +func (m dummyLayout) Init() tea.Cmd { + return nil +} + +func (m dummyLayout) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + return m, nil +} + +func (m dummyLayout) View() string { + return m.debugString +} + +func main() { + + p := tea.NewProgram(initModel(), tea.WithAltScreen()) + if _, err := p.Run(); err != nil { + fmt.Printf("Error: %v", err) + os.Exit(1) + } +} From 3c6a7cebc823ec47f7ff878cb867369cb2b3fad0 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 17:24:19 +0100 Subject: [PATCH 08/31] implement layout computation and pane size management --- layout/layout.go | 38 +++++++++++++++++++++++++++++++++++ layout/pane_size.go | 10 ++++++++++ main.go | 48 +++++++++++++++++++++++++++++++-------------- 3 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 layout/layout.go create mode 100644 layout/pane_size.go diff --git a/layout/layout.go b/layout/layout.go new file mode 100644 index 0000000..921ffe2 --- /dev/null +++ b/layout/layout.go @@ -0,0 +1,38 @@ +package layout + +type LayoutSizes struct { + ScreenWidth int + ScreenHeight int + + LeftPaneWidth int + RightPaneWidth int + + MainHeight int + + FooterHeight int + FooterVisible int + + HeightAvailable int +} + +func ComputeLayout(screenWidth, screenHeight int) LayoutSizes { + const border = 2 + const footer = 4 + const left = 25 + const gap = 6 // space between panes (borders, margins, etc) + + heightAvailable := screenHeight - border + footerVisible := footer - 1 + mainHeight := heightAvailable - footerVisible - 2 // for spacing/padding + + return LayoutSizes{ + ScreenWidth: screenWidth, + ScreenHeight: screenHeight, + LeftPaneWidth: left, + RightPaneWidth: screenWidth - left - gap, + MainHeight: mainHeight, + FooterHeight: footer, + FooterVisible: footerVisible, + HeightAvailable: heightAvailable, + } +} diff --git a/layout/pane_size.go b/layout/pane_size.go new file mode 100644 index 0000000..622afe3 --- /dev/null +++ b/layout/pane_size.go @@ -0,0 +1,10 @@ +package layout + +type PaneSize struct { + Width int + Height int +} + +type SizeMsg struct { + Size PaneSize +} diff --git a/main.go b/main.go index 007ed55..43906be 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/rodpadev/aws-profiles/layout" ) const ( @@ -33,6 +34,19 @@ func (m layoutModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height + + computedLayout := layout.ComputeLayout(m.width, m.height) + + m.leftPane, _ = m.leftPane.Update(layout.SizeMsg{ + Size: layout.PaneSize{Width: computedLayout.LeftPaneWidth, Height: computedLayout.MainHeight - 2}, + }) + m.rightPane, _ = m.rightPane.Update(layout.SizeMsg{ + Size: layout.PaneSize{Width: computedLayout.RightPaneWidth, Height: computedLayout.MainHeight - 2}, + }) + m.footer, _ = m.footer.Update(layout.SizeMsg{ + Size: layout.PaneSize{Width: computedLayout.ScreenWidth - 2, Height: computedLayout.FooterHeight}, + }) + case tea.KeyMsg: switch msg.String() { case "q", "ctrl+c": @@ -56,43 +70,42 @@ func updateModel(child tea.Model, msg tea.Msg, cmds []tea.Cmd) (tea.Model, []tea } func (m layoutModel) View() string { - heightWithoutBorder := m.height - 2 - footerVisibleHeight := footerHeight - 1 - mainHeight := heightWithoutBorder - footerVisibleHeight - 2 + computedLayout := layout.ComputeLayout(m.width, m.height) right := lipgloss.NewStyle(). - Width(m.width - leftPaneWidth - 6). - Height(mainHeight - 2). + Width(computedLayout.RightPaneWidth). + Height(computedLayout.MainHeight - 2). Border(lipgloss.NormalBorder()). Render(m.rightPane.View()) left := lipgloss.NewStyle(). - Width(leftPaneWidth). - Height(mainHeight - 2). + Width(computedLayout.LeftPaneWidth). + Height(computedLayout.MainHeight - 2). Border(lipgloss.NormalBorder()). Render(m.leftPane.View()) footer := lipgloss.NewStyle(). - Width(m.width - 2). - Height(footerHeight). + Width(computedLayout.ScreenWidth - 2). + Height(computedLayout.FooterHeight). Border(lipgloss.NormalBorder()). BorderBottom(false). BorderRight(false). BorderLeft(false). Render(m.footer.View()) - topRow := lipgloss.NewStyle().Height(mainHeight).Width(m.width - 2).Render( - lipgloss.JoinHorizontal(lipgloss.Top, left, right), - ) + topRow := lipgloss.NewStyle(). + Height(computedLayout.MainHeight). + Width(computedLayout.ScreenWidth - 2). + Render(lipgloss.JoinHorizontal(lipgloss.Top, left, right)) mainRender := lipgloss.JoinVertical(lipgloss.Top, topRow, footer) if m.width < 75 || m.height < 25 { - mainRender = lipgloss.Place(m.width, heightWithoutBorder, lipgloss.Center, lipgloss.Center, "Too Small! Expand your terminal") + mainRender = lipgloss.Place(m.width, computedLayout.HeightAvailable, lipgloss.Center, lipgloss.Center, "Too Small! Expand your terminal") } return lipgloss.NewStyle(). - Height(heightWithoutBorder). + Height(computedLayout.HeightAvailable). Width(m.width - 2). Border(lipgloss.NormalBorder()). Render(mainRender) @@ -115,6 +128,7 @@ func initModel() layoutModel { type dummyLayout struct { debugString string + size layout.PaneSize } func (m dummyLayout) Init() tea.Cmd { @@ -122,11 +136,15 @@ func (m dummyLayout) Init() tea.Cmd { } func (m dummyLayout) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case layout.SizeMsg: + m.size = msg.Size + } return m, nil } func (m dummyLayout) View() string { - return m.debugString + return fmt.Sprintf("%s %d", m.debugString, m.size.Height) } func main() { From 6b634aaf6ffc4e55c6e5d4273f498edc1870df20 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 17:26:04 +0100 Subject: [PATCH 09/31] display width x height --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 43906be..893ec9e 100644 --- a/main.go +++ b/main.go @@ -144,7 +144,7 @@ func (m dummyLayout) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m dummyLayout) View() string { - return fmt.Sprintf("%s %d", m.debugString, m.size.Height) + return fmt.Sprintf("%s: %dx%d", m.debugString, m.size.Width, m.size.Height) } func main() { From 310bf0cd6ce5e96b4d09ef14c1ac73f6955f4c5c Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 18:41:41 +0100 Subject: [PATCH 10/31] refactor: update layout constants and enhance sidebar model for profile selection --- layout/layout.go | 2 +- lib/aws_interop.go | 7 ++++- main.go | 41 +++++++++++++++++++++++-- state/state.go | 15 ++++++++++ tui/sidebar.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 state/state.go create mode 100644 tui/sidebar.go diff --git a/layout/layout.go b/layout/layout.go index 921ffe2..6f275e8 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -18,7 +18,7 @@ type LayoutSizes struct { func ComputeLayout(screenWidth, screenHeight int) LayoutSizes { const border = 2 const footer = 4 - const left = 25 + const left = 32 const gap = 6 // space between panes (borders, margins, etc) heightAvailable := screenHeight - border diff --git a/lib/aws_interop.go b/lib/aws_interop.go index 674a97d..e007be4 100644 --- a/lib/aws_interop.go +++ b/lib/aws_interop.go @@ -75,7 +75,12 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { // get current section if line[0] == '[' && line[len(line)-1] == ']' { - currentSection = string(line[1 : len(line)-1]) + currentSection = strings.TrimSpace(strings.Replace(string(line[1:len(line)-1]), "profile", "", 1)) + + if currentSection == "default" { + currentSection = "⚠️ RENAME [awscli default]" + } + if _, exists := result[currentSection]; !exists { result[currentSection] = make(map[string]string) } diff --git a/main.go b/main.go index 893ec9e..36db5e8 100644 --- a/main.go +++ b/main.go @@ -2,11 +2,15 @@ package main import ( "fmt" + "log" "os" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/rodpadev/aws-profiles/layout" + "github.com/rodpadev/aws-profiles/lib" + "github.com/rodpadev/aws-profiles/state" + "github.com/rodpadev/aws-profiles/tui" ) const ( @@ -14,6 +18,8 @@ const ( footerHeight int = 4 ) +var AppState state.State + type layoutModel struct { width, height int leftPane tea.Model @@ -114,8 +120,9 @@ func (m layoutModel) View() string { func initModel() layoutModel { return layoutModel{ - leftPane: dummyLayout{ - debugString: "left", + leftPane: &tui.SidebarModel{ + DebugString: "left", + State: AppState, }, rightPane: dummyLayout{ debugString: "right", @@ -149,6 +156,36 @@ func (m dummyLayout) View() string { func main() { + data, err := lib.LoadAWSProfileData() + if err != nil { + log.Fatal(err) + } + + parsed := lib.ParseAWSProfileData(data) + if err != nil { + log.Fatal(err) + } + + profileMap, err := lib.BuildProfileMap(parsed) + + if err != nil { + log.Fatal(err) + } + + var firstProfile string + for k := range profileMap { + firstProfile = k + break + } + + AppState = state.State{ + Selection: state.Selection{ + Index: 0, + Key: firstProfile, + }, + ProfileMap: profileMap, + } + p := tea.NewProgram(initModel(), tea.WithAltScreen()) if _, err := p.Run(); err != nil { fmt.Printf("Error: %v", err) diff --git a/state/state.go b/state/state.go new file mode 100644 index 0000000..0ddac92 --- /dev/null +++ b/state/state.go @@ -0,0 +1,15 @@ +package state + +import ( + "github.com/rodpadev/aws-profiles/lib" +) + +type Selection struct { + Index int + Key string +} + +type State struct { + Selection Selection + ProfileMap lib.ProfileMap +} diff --git a/tui/sidebar.go b/tui/sidebar.go new file mode 100644 index 0000000..49fe115 --- /dev/null +++ b/tui/sidebar.go @@ -0,0 +1,74 @@ +package tui + +import ( + "fmt" + "slices" + + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" + "github.com/rodpadev/aws-profiles/layout" + "github.com/rodpadev/aws-profiles/state" +) + +type SidebarModel struct { + State state.State + DebugString string + size layout.PaneSize + profileKeys []string +} + +func (m *SidebarModel) Init() tea.Cmd { + for k := range m.State.ProfileMap { + m.profileKeys = append(m.profileKeys, k) + } + + slices.Sort(m.profileKeys) + return nil +} + +func (m *SidebarModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case layout.SizeMsg: + m.size = msg.Size + case tea.KeyMsg: + switch msg.String() { + case "j", tea.KeyDown.String(): + if m.State.Selection.Index < len(m.profileKeys)-1 { + m.State.Selection.Index += 1 + } else { + m.State.Selection.Index = 0 + } + case "k", tea.KeyUp.String(): + if m.State.Selection.Index > 0 { + m.State.Selection.Index -= 1 + } else { + m.State.Selection.Index = len(m.profileKeys) - 1 + } + } + } + return m, nil +} + +func (m *SidebarModel) View() string { + + lines := make([]string, len(m.profileKeys)) + + for idx, profile := range m.profileKeys { + prefix := " " + // default color is white + color := lipgloss.Color("white") + if m.State.Selection.Index == idx { + prefix = ">" + color = lipgloss.Color("205") + } + lines[idx] = lipgloss.NewStyle(). + Foreground(color). + Render(fmt.Sprintf("%s %s", prefix, profile)) + } + + return lipgloss.NewStyle(). + Height(m.size.Height). + Width(m.size.Width). + Render(lipgloss.JoinVertical(lipgloss.Top, lines..., + )) +} From c3660ccd774383c6312f484a62a5dff0ea51cc73 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 20:21:40 +0100 Subject: [PATCH 11/31] cleanup cursor selection --- main.go | 2 +- state/state.go | 5 ++-- tui/sidebar.go | 63 +++++++++++++++++++++++++++++++++++--------------- tui/theme.go | 21 +++++++++++++++++ 4 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 tui/theme.go diff --git a/main.go b/main.go index 36db5e8..2a8eeba 100644 --- a/main.go +++ b/main.go @@ -179,7 +179,7 @@ func main() { } AppState = state.State{ - Selection: state.Selection{ + Cursor: state.ProfilePosition{ Index: 0, Key: firstProfile, }, diff --git a/state/state.go b/state/state.go index 0ddac92..0045506 100644 --- a/state/state.go +++ b/state/state.go @@ -4,12 +4,13 @@ import ( "github.com/rodpadev/aws-profiles/lib" ) -type Selection struct { +type ProfilePosition struct { Index int Key string } type State struct { - Selection Selection + Cursor ProfilePosition + Selection ProfilePosition ProfileMap lib.ProfileMap } diff --git a/tui/sidebar.go b/tui/sidebar.go index 49fe115..4c2c299 100644 --- a/tui/sidebar.go +++ b/tui/sidebar.go @@ -32,43 +32,70 @@ func (m *SidebarModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.size = msg.Size case tea.KeyMsg: switch msg.String() { + case "enter", "spacebar": + m.State.Selection = m.State.Cursor case "j", tea.KeyDown.String(): - if m.State.Selection.Index < len(m.profileKeys)-1 { - m.State.Selection.Index += 1 + if m.State.Cursor.Index < len(m.profileKeys)-1 { + m.State.Cursor.Index += 1 } else { - m.State.Selection.Index = 0 + m.State.Cursor.Index = 0 } case "k", tea.KeyUp.String(): - if m.State.Selection.Index > 0 { - m.State.Selection.Index -= 1 + if m.State.Cursor.Index > 0 { + m.State.Cursor.Index -= 1 } else { - m.State.Selection.Index = len(m.profileKeys) - 1 + m.State.Cursor.Index = len(m.profileKeys) - 1 } + case "h", tea.KeyLeft.String(): + m.State.Cursor.Index = 0 + case "l", tea.KeyRight.String(): + m.State.Cursor.Index = len(m.profileKeys) - 1 } + } return m, nil } func (m *SidebarModel) View() string { - lines := make([]string, len(m.profileKeys)) for idx, profile := range m.profileKeys { - prefix := " " - // default color is white - color := lipgloss.Color("white") - if m.State.Selection.Index == idx { - prefix = ">" - color = lipgloss.Color("205") + prefix := Icons.SidebarCursorInactive + style := lipgloss.NewStyle().Width(m.size.Width) + + isActiveIndex := m.State.Cursor.Index == idx + isCurrentSelection := m.State.Selection.Index == idx + + var fg, bg lipgloss.Color + + switch { + case isActiveIndex && isCurrentSelection: + prefix = Icons.SidebarCursorActive + fg = lipgloss.Color(Colors.OnPrimary) + bg = lipgloss.Color(Colors.Primary) + case isActiveIndex: + prefix = Icons.SidebarCursorActive + fg = lipgloss.Color(Colors.Primary) + case isCurrentSelection: + fg = lipgloss.Color(Colors.OnPrimary) + bg = lipgloss.Color(Colors.Primary) + default: + fg = lipgloss.Color(Colors.Text) } - lines[idx] = lipgloss.NewStyle(). - Foreground(color). - Render(fmt.Sprintf("%s %s", prefix, profile)) + + style = style.Foreground(fg) + + if isCurrentSelection { + style = style.Background(bg) + } else { + style = style.UnsetBackground() + } + + lines[idx] = style.Render(fmt.Sprintf(" %s %s", prefix, profile)) } return lipgloss.NewStyle(). Height(m.size.Height). Width(m.size.Width). - Render(lipgloss.JoinVertical(lipgloss.Top, lines..., - )) + Render(lipgloss.JoinVertical(lipgloss.Top, lines...)) } diff --git a/tui/theme.go b/tui/theme.go new file mode 100644 index 0000000..0e9b992 --- /dev/null +++ b/tui/theme.go @@ -0,0 +1,21 @@ +package tui + +import "github.com/charmbracelet/lipgloss" + +var Colors = struct { + Text lipgloss.Color + Primary lipgloss.Color + OnPrimary lipgloss.Color +}{ + Text: lipgloss.Color("#FFFFFF"), + Primary: lipgloss.Color("#FF9900"), + OnPrimary: lipgloss.Color("#3b2301"), +} + +var Icons = struct { + SidebarCursorActive string + SidebarCursorInactive string +}{ + SidebarCursorActive: "▶", + SidebarCursorInactive: " ", +} From f3b36733ec28cbd89cab009238a6db612927fbe4 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 20:57:08 +0100 Subject: [PATCH 12/31] receive state as pointer & update selection logic --- tui/sidebar.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tui/sidebar.go b/tui/sidebar.go index 4c2c299..8765120 100644 --- a/tui/sidebar.go +++ b/tui/sidebar.go @@ -11,7 +11,7 @@ import ( ) type SidebarModel struct { - State state.State + State *state.State DebugString string size layout.PaneSize profileKeys []string @@ -32,8 +32,17 @@ func (m *SidebarModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.size = msg.Size case tea.KeyMsg: switch msg.String() { - case "enter", "spacebar": - m.State.Selection = m.State.Cursor + case tea.KeySpace.String(), tea.KeyEnter.String(): + if m.State.Selection.Index == m.State.Cursor.Index { + m.State.Selection.Index = -1 + m.State.Selection.Key = "" + } else { + m.State.Selection.Index = m.State.Cursor.Index + m.State.Selection.Key = m.profileKeys[m.State.Cursor.Index] + } + case tea.KeyBackspace.String(): + m.State.Selection.Index = -1 + m.State.Selection.Key = "" case "j", tea.KeyDown.String(): if m.State.Cursor.Index < len(m.profileKeys)-1 { m.State.Cursor.Index += 1 From 060d01f56699dc1bdd8c4dcb7b2fa7bfe3fa79ba Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Sun, 18 May 2025 20:57:24 +0100 Subject: [PATCH 13/31] render selected profile --- main.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 2a8eeba..aced183 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "fmt" "log" "os" @@ -122,7 +123,7 @@ func initModel() layoutModel { return layoutModel{ leftPane: &tui.SidebarModel{ DebugString: "left", - State: AppState, + State: &AppState, }, rightPane: dummyLayout{ debugString: "right", @@ -151,6 +152,16 @@ func (m dummyLayout) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m dummyLayout) View() string { + if m.debugString == "right" { + if selected, ok := AppState.ProfileMap[AppState.Selection.Key]; ok { + if marshall, err := json.MarshalIndent(selected, "", " "); err != nil { + return "no" + } else { + return string(marshall) + } + + } + } return fmt.Sprintf("%s: %dx%d", m.debugString, m.size.Width, m.size.Height) } From ad227276019e6ec0db2c3fa99ce248d463a3ac8c Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 17:52:07 +0100 Subject: [PATCH 14/31] improve semantics & create content pane tui component --- main.go | 18 ++++---------- state/state.go | 5 ++++ tui/content_pane.go | 37 +++++++++++++++++++++++++++++ tui/{sidebar.go => sidebar_pane.go} | 8 +++---- 4 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 tui/content_pane.go rename tui/{sidebar.go => sidebar_pane.go} (93%) diff --git a/main.go b/main.go index aced183..24ef8f5 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "encoding/json" "fmt" "log" "os" @@ -121,12 +120,13 @@ func (m layoutModel) View() string { func initModel() layoutModel { return layoutModel{ - leftPane: &tui.SidebarModel{ + leftPane: &tui.SidebarPaneModel{ DebugString: "left", State: &AppState, }, - rightPane: dummyLayout{ - debugString: "right", + rightPane: &tui.ContentPaneModel{ + DebugString: "right", + State: &AppState, }, footer: dummyLayout{ debugString: "footer", @@ -152,16 +152,6 @@ func (m dummyLayout) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m dummyLayout) View() string { - if m.debugString == "right" { - if selected, ok := AppState.ProfileMap[AppState.Selection.Key]; ok { - if marshall, err := json.MarshalIndent(selected, "", " "); err != nil { - return "no" - } else { - return string(marshall) - } - - } - } return fmt.Sprintf("%s: %dx%d", m.debugString, m.size.Width, m.size.Height) } diff --git a/state/state.go b/state/state.go index 0045506..e114248 100644 --- a/state/state.go +++ b/state/state.go @@ -14,3 +14,8 @@ type State struct { Selection ProfilePosition ProfileMap lib.ProfileMap } + +func (s *State) GetCurrentProfile() (lib.Profile, bool) { + currentProfile, ok := s.ProfileMap[s.Selection.Key] + return currentProfile, ok +} diff --git a/tui/content_pane.go b/tui/content_pane.go new file mode 100644 index 0000000..b58b8a2 --- /dev/null +++ b/tui/content_pane.go @@ -0,0 +1,37 @@ +package tui + +import ( + "encoding/json" + + tea "github.com/charmbracelet/bubbletea" + "github.com/rodpadev/aws-profiles/layout" + "github.com/rodpadev/aws-profiles/state" +) + +type ContentPaneModel struct { + State *state.State + DebugString string + size layout.PaneSize + profile state.ProfilePosition +} + +func (m ContentPaneModel) Init() tea.Cmd { + return nil +} + +func (m ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case layout.SizeMsg: + m.size = msg.Size + } + return m, nil +} + +func (m ContentPaneModel) View() string { + if selected, ok := m.State.GetCurrentProfile(); ok { + if marshall, err := json.MarshalIndent(selected, "", " "); err == nil { + return string(marshall) + } + } + return "no profile or no unmarshall" +} diff --git a/tui/sidebar.go b/tui/sidebar_pane.go similarity index 93% rename from tui/sidebar.go rename to tui/sidebar_pane.go index 8765120..5a16e61 100644 --- a/tui/sidebar.go +++ b/tui/sidebar_pane.go @@ -10,14 +10,14 @@ import ( "github.com/rodpadev/aws-profiles/state" ) -type SidebarModel struct { +type SidebarPaneModel struct { State *state.State DebugString string size layout.PaneSize profileKeys []string } -func (m *SidebarModel) Init() tea.Cmd { +func (m *SidebarPaneModel) Init() tea.Cmd { for k := range m.State.ProfileMap { m.profileKeys = append(m.profileKeys, k) } @@ -26,7 +26,7 @@ func (m *SidebarModel) Init() tea.Cmd { return nil } -func (m *SidebarModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +func (m *SidebarPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case layout.SizeMsg: m.size = msg.Size @@ -65,7 +65,7 @@ func (m *SidebarModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil } -func (m *SidebarModel) View() string { +func (m *SidebarPaneModel) View() string { lines := make([]string, len(m.profileKeys)) for idx, profile := range m.profileKeys { From 274cfe0db7450e9f96f056941a7a44d138713d9c Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 18:16:09 +0100 Subject: [PATCH 15/31] move sidebar cursor state to sidebar --- main.go | 15 +++------------ state/state.go | 6 +++--- tui/sidebar_pane.go | 25 +++++++++++++------------ 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/main.go b/main.go index 24ef8f5..9cc1d7c 100644 --- a/main.go +++ b/main.go @@ -162,7 +162,7 @@ func main() { log.Fatal(err) } - parsed := lib.ParseAWSProfileData(data) + parsed, profileCount := lib.ParseAWSProfileData(data) if err != nil { log.Fatal(err) } @@ -173,18 +173,9 @@ func main() { log.Fatal(err) } - var firstProfile string - for k := range profileMap { - firstProfile = k - break - } - AppState = state.State{ - Cursor: state.ProfilePosition{ - Index: 0, - Key: firstProfile, - }, - ProfileMap: profileMap, + ProfileMap: profileMap, + ProfileMapSize: profileCount, } p := tea.NewProgram(initModel(), tea.WithAltScreen()) diff --git a/state/state.go b/state/state.go index e114248..2ef2a75 100644 --- a/state/state.go +++ b/state/state.go @@ -10,9 +10,9 @@ type ProfilePosition struct { } type State struct { - Cursor ProfilePosition - Selection ProfilePosition - ProfileMap lib.ProfileMap + Selection ProfilePosition + ProfileMap lib.ProfileMap + ProfileMapSize int } func (s *State) GetCurrentProfile() (lib.Profile, bool) { diff --git a/tui/sidebar_pane.go b/tui/sidebar_pane.go index 5a16e61..29620f7 100644 --- a/tui/sidebar_pane.go +++ b/tui/sidebar_pane.go @@ -11,6 +11,7 @@ import ( ) type SidebarPaneModel struct { + cursor state.ProfilePosition State *state.State DebugString string size layout.PaneSize @@ -33,32 +34,32 @@ func (m *SidebarPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.KeyMsg: switch msg.String() { case tea.KeySpace.String(), tea.KeyEnter.String(): - if m.State.Selection.Index == m.State.Cursor.Index { + if m.State.Selection.Index == m.cursor.Index { m.State.Selection.Index = -1 m.State.Selection.Key = "" } else { - m.State.Selection.Index = m.State.Cursor.Index - m.State.Selection.Key = m.profileKeys[m.State.Cursor.Index] + m.State.Selection.Index = m.cursor.Index + m.State.Selection.Key = m.profileKeys[m.cursor.Index] } case tea.KeyBackspace.String(): m.State.Selection.Index = -1 m.State.Selection.Key = "" case "j", tea.KeyDown.String(): - if m.State.Cursor.Index < len(m.profileKeys)-1 { - m.State.Cursor.Index += 1 + if m.cursor.Index < len(m.profileKeys)-1 { + m.cursor.Index += 1 } else { - m.State.Cursor.Index = 0 + m.cursor.Index = 0 } case "k", tea.KeyUp.String(): - if m.State.Cursor.Index > 0 { - m.State.Cursor.Index -= 1 + if m.cursor.Index > 0 { + m.cursor.Index -= 1 } else { - m.State.Cursor.Index = len(m.profileKeys) - 1 + m.cursor.Index = len(m.profileKeys) - 1 } case "h", tea.KeyLeft.String(): - m.State.Cursor.Index = 0 + m.cursor.Index = 0 case "l", tea.KeyRight.String(): - m.State.Cursor.Index = len(m.profileKeys) - 1 + m.cursor.Index = len(m.profileKeys) - 1 } } @@ -72,7 +73,7 @@ func (m *SidebarPaneModel) View() string { prefix := Icons.SidebarCursorInactive style := lipgloss.NewStyle().Width(m.size.Width) - isActiveIndex := m.State.Cursor.Index == idx + isActiveIndex := m.cursor.Index == idx isCurrentSelection := m.State.Selection.Index == idx var fg, bg lipgloss.Color From 399d9e393d353b124c93fce596e7b2422bcd9983 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 18:16:16 +0100 Subject: [PATCH 16/31] update ParseAWSProfileData to return profile count --- lib/aws_interop.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/aws_interop.go b/lib/aws_interop.go index e007be4..8529313 100644 --- a/lib/aws_interop.go +++ b/lib/aws_interop.go @@ -56,7 +56,7 @@ func LoadAWSProfileData() ([][]byte, error) { return [][]byte{config, credentials}, nil } -func ParseAWSProfileData(data [][]byte) map[string]map[string]string { +func ParseAWSProfileData(data [][]byte) (map[string]map[string]string, int) { result := map[string]map[string]string{} combined := append(data[0], '\n') @@ -65,6 +65,7 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { lines := bytes.Split(combined, []byte{'\n'}) var currentSection string + var profileCount int for i, line := range lines { line = bytes.TrimSpace(line) @@ -83,6 +84,7 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { if _, exists := result[currentSection]; !exists { result[currentSection] = make(map[string]string) + profileCount += 1 } continue } @@ -113,7 +115,7 @@ func ParseAWSProfileData(data [][]byte) map[string]map[string]string { } - return result + return result, profileCount } From b1365e891a798c0a7feb89a691995be4095194f0 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 19:28:45 +0100 Subject: [PATCH 17/31] modularize cursor movement --- state/cursor.go | 61 +++++++++++++++++++++++++++++++++++++++++++++ tui/sidebar_pane.go | 27 ++++++-------------- 2 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 state/cursor.go diff --git a/state/cursor.go b/state/cursor.go new file mode 100644 index 0000000..c8fd2bd --- /dev/null +++ b/state/cursor.go @@ -0,0 +1,61 @@ +package state + +import tea "github.com/charmbracelet/bubbletea" + +type Cursor struct { + Index int +} + +func (c *Cursor) MoveDown(length int) { + if length == 0 { + c.Index = 0 + return + } + if c.Index < length-1 { + c.Index += 1 + } else { + c.Index = 0 + } +} + +func (c *Cursor) MoveUp(length int) { + if length == 0 { + c.Index = 0 + return + } + if c.Index > 0 { + c.Index -= 1 + } else { + c.Index = length - 1 + } +} + +func (c *Cursor) HandleKey(msg tea.KeyMsg, listLength int) bool { + if listLength <= 0 { + c.Index = 0 + return false + } + + original := c.Index + + switch msg.String() { + case "j", tea.KeyDown.String(): + if c.Index < listLength-1 { + c.Index += 1 + } else { + c.Index = 0 + } + case "k", tea.KeyUp.String(): + if c.Index > 0 { + c.Index -= 1 + } else { + c.Index = listLength - 1 + } + case "h", tea.KeyLeft.String(): + c.Index = 0 + case "l", tea.KeyRight.String(): + c.Index = listLength - 1 + } + + return c.Index != original +} diff --git a/tui/sidebar_pane.go b/tui/sidebar_pane.go index 29620f7..ccd4e61 100644 --- a/tui/sidebar_pane.go +++ b/tui/sidebar_pane.go @@ -11,7 +11,7 @@ import ( ) type SidebarPaneModel struct { - cursor state.ProfilePosition + cursor state.Cursor State *state.State DebugString string size layout.PaneSize @@ -32,6 +32,11 @@ func (m *SidebarPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case layout.SizeMsg: m.size = msg.Size case tea.KeyMsg: + + if m.cursor.HandleKey(msg, len(m.profileKeys)) { + break + } + switch msg.String() { case tea.KeySpace.String(), tea.KeyEnter.String(): if m.State.Selection.Index == m.cursor.Index { @@ -41,25 +46,7 @@ func (m *SidebarPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.State.Selection.Index = m.cursor.Index m.State.Selection.Key = m.profileKeys[m.cursor.Index] } - case tea.KeyBackspace.String(): - m.State.Selection.Index = -1 - m.State.Selection.Key = "" - case "j", tea.KeyDown.String(): - if m.cursor.Index < len(m.profileKeys)-1 { - m.cursor.Index += 1 - } else { - m.cursor.Index = 0 - } - case "k", tea.KeyUp.String(): - if m.cursor.Index > 0 { - m.cursor.Index -= 1 - } else { - m.cursor.Index = len(m.profileKeys) - 1 - } - case "h", tea.KeyLeft.String(): - m.cursor.Index = 0 - case "l", tea.KeyRight.String(): - m.cursor.Index = len(m.profileKeys) - 1 + } } From 315b6ca6ad41ee4d745481de3d516a862c32042a Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 19:29:23 +0100 Subject: [PATCH 18/31] move deselection with backspace to root update --- main.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 9cc1d7c..f518142 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,9 @@ func (m layoutModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.KeyMsg: switch msg.String() { + case tea.KeyBackspace.String(): + AppState.Selection.Index = -1 + AppState.Selection.Key = "" case "q", "ctrl+c": return m, tea.Quit } @@ -63,8 +66,11 @@ func (m layoutModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmds []tea.Cmd - m.leftPane, cmds = updateModel(m.leftPane, msg, cmds) - m.rightPane, cmds = updateModel(m.rightPane, msg, cmds) + if AppState.Selection.Key == "" { + m.leftPane, cmds = updateModel(m.leftPane, msg, cmds) + } else { + m.rightPane, cmds = updateModel(m.rightPane, msg, cmds) + } m.footer, cmds = updateModel(m.footer, msg, cmds) return m, tea.Batch(cmds...) From b1ca6d15a40e180dcbf55dbbdce4effd6dfc6bc4 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 19:30:20 +0100 Subject: [PATCH 19/31] add basic inputs to content pane --- tui/content_pane.go | 97 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 8 deletions(-) diff --git a/tui/content_pane.go b/tui/content_pane.go index b58b8a2..e431cc5 100644 --- a/tui/content_pane.go +++ b/tui/content_pane.go @@ -1,37 +1,118 @@ package tui import ( - "encoding/json" + "fmt" + "strings" + "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" "github.com/rodpadev/aws-profiles/layout" + "github.com/rodpadev/aws-profiles/lib" "github.com/rodpadev/aws-profiles/state" ) +var ( + focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")) + contentStyle = lipgloss.NewStyle().PaddingLeft(2) +) + +type ManagedInput struct { + Name string + idx int + input textinput.Model +} + type ContentPaneModel struct { + cursor state.Cursor State *state.State DebugString string size layout.PaneSize profile state.ProfilePosition + inputs []ManagedInput } -func (m ContentPaneModel) Init() tea.Cmd { +func (m *ContentPaneModel) BuildInputs(profile lib.Profile) { + + m.inputs = make([]ManagedInput, 5) + var t ManagedInput + + for i := range m.inputs { + t.idx = i + t.input = textinput.New() + t.input.Width = m.size.Width + t.input.Prompt = "" + + switch i { + case 0: + t.Name = "Profile Name" + t.input.Focus() + t.input.PromptStyle = focusedStyle + t.input.TextStyle = focusedStyle + t.input.CharLimit = 32 + t.input.SetValue(profile.Name) + case 1: + t.Name = "Access Key" + t.input.SetValue(profile.Credential.AccessKey) + case 2: + t.Name = "Secret Key" + t.input.EchoMode = textinput.EchoPassword + t.input.EchoCharacter = 0 + t.input.SetValue(profile.Credential.SecretKey) + case 3: + t.Name = "Output" + t.input.SetValue(profile.Config.Output) + case 4: + t.Name = "Region" + t.input.SetValue(profile.Config.Region) + } + m.inputs[i] = t + } +} + +func (m *ContentPaneModel) Init() tea.Cmd { return nil } -func (m ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case layout.SizeMsg: m.size = msg.Size + case tea.KeyMsg: + if m.cursor.HandleKey(msg, len(m.inputs)) { + break + } } + return m, nil } -func (m ContentPaneModel) View() string { - if selected, ok := m.State.GetCurrentProfile(); ok { - if marshall, err := json.MarshalIndent(selected, "", " "); err == nil { - return string(marshall) +func (m *ContentPaneModel) View() string { + + selectedProfile, ok := m.State.GetCurrentProfile() + if !ok { + return "Select a profile to edit" + } + + m.BuildInputs(selectedProfile) + var b strings.Builder + + for i := range m.inputs { + if m.cursor.Index == i { + m.inputs[i].input.Focus() + m.inputs[i].input.PromptStyle = focusedStyle + m.inputs[i].input.TextStyle = focusedStyle + } else { + m.inputs[i].input.Blur() + m.inputs[i].input.PromptStyle = lipgloss.NewStyle() + m.inputs[i].input.TextStyle = lipgloss.NewStyle() + } + b.WriteString(fmt.Sprintf("%s: %s", m.inputs[i].Name, m.inputs[i].input.View())) + if i < len(m.inputs)-1 { + b.WriteRune('\n') } } - return "no profile or no unmarshall" + + mainRender := contentStyle.Width(m.size.Width).Height(m.size.Height).Render(b.String()) + return mainRender } From 54cc02c7760e672249194aecfacddf48d5ec9b53 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 19:30:45 +0100 Subject: [PATCH 20/31] add property to state to keep track of modified profiles --- state/state.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/state/state.go b/state/state.go index 2ef2a75..c7e3e28 100644 --- a/state/state.go +++ b/state/state.go @@ -10,9 +10,10 @@ type ProfilePosition struct { } type State struct { - Selection ProfilePosition - ProfileMap lib.ProfileMap - ProfileMapSize int + Selection ProfilePosition + ProfileMap lib.ProfileMap + ProfileMapSize int + ModifiedProfiledKeys []string } func (s *State) GetCurrentProfile() (lib.Profile, bool) { From 8d09c7ded235b42589d300e6752d4c5328805dbe Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 19:31:33 +0100 Subject: [PATCH 21/31] fix: handle error from ParseAWSProfileData in integration test --- lib/lib_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lib_integration_test.go b/lib/lib_integration_test.go index 3f712ce..895fe3b 100644 --- a/lib/lib_integration_test.go +++ b/lib/lib_integration_test.go @@ -99,7 +99,7 @@ func TestIntegrationFlow(t *testing.T) { } // Parse AWS profile data - parsedData := ParseAWSProfileData(data) + parsedData, _ := ParseAWSProfileData(data) // Verify parsed data if len(parsedData) != 3 { // default, profile dev, profile prod, dev, prod From 574f250801ac0ee357ee87ae5cfa76fd54432443 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 21:34:54 +0100 Subject: [PATCH 22/31] implement naive input --- main.go | 3 -- tui/content_pane.go | 126 ++++++++++++++++++++++++++++++++------------ 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/main.go b/main.go index f518142..2638c8b 100644 --- a/main.go +++ b/main.go @@ -55,9 +55,6 @@ func (m layoutModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.KeyMsg: switch msg.String() { - case tea.KeyBackspace.String(): - AppState.Selection.Index = -1 - AppState.Selection.Key = "" case "q", "ctrl+c": return m, tea.Quit } diff --git a/tui/content_pane.go b/tui/content_pane.go index e431cc5..c95f5cd 100644 --- a/tui/content_pane.go +++ b/tui/content_pane.go @@ -1,8 +1,7 @@ package tui import ( - "fmt" - "strings" + "slices" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" @@ -13,42 +12,45 @@ import ( ) var ( - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")) + focusedStyle = lipgloss.NewStyle().Foreground(Colors.Primary) contentStyle = lipgloss.NewStyle().PaddingLeft(2) + noStyle = lipgloss.NewStyle() ) type ManagedInput struct { Name string - idx int input textinput.Model } type ContentPaneModel struct { - cursor state.Cursor - State *state.State - DebugString string - size layout.PaneSize - profile state.ProfilePosition - inputs []ManagedInput + cursor state.Cursor + State *state.State + DebugString string + size layout.PaneSize + profile state.ProfilePosition + inputs []ManagedInput + modifiedInputs []int + isInputFocusCaptured bool + inputFocusCapturedIdx int + inputsInitialized bool } func (m *ContentPaneModel) BuildInputs(profile lib.Profile) { - + m.inputFocusCapturedIdx = -1 + m.isInputFocusCaptured = false m.inputs = make([]ManagedInput, 5) var t ManagedInput for i := range m.inputs { - t.idx = i t.input = textinput.New() + t.input.Blur() t.input.Width = m.size.Width t.input.Prompt = "" + t.input.TextStyle = noStyle switch i { case 0: t.Name = "Profile Name" - t.input.Focus() - t.input.PromptStyle = focusedStyle - t.input.TextStyle = focusedStyle t.input.CharLimit = 32 t.input.SetValue(profile.Name) case 1: @@ -78,41 +80,99 @@ func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case layout.SizeMsg: m.size = msg.Size + case tea.KeyMsg: - if m.cursor.HandleKey(msg, len(m.inputs)) { - break + key := msg.String() + + if m.isInputFocusCaptured { + cmd := m.updateFocusedInput(msg) + if key == tea.KeyEscape.String() { + m.modifiedInputs = append(m.modifiedInputs, m.inputFocusCapturedIdx) + m.isInputFocusCaptured = false + m.inputFocusCapturedIdx = -1 + } + return m, cmd + } + + m.cursor.HandleKey(msg, len(m.inputs)) + + switch key { + case tea.KeyEnter.String(): + m.isInputFocusCaptured = true + m.inputFocusCapturedIdx = m.cursor.Index + + cmds := make([]tea.Cmd, len(m.inputs)) + for i := range m.inputs { + if i == m.inputFocusCapturedIdx { + m.inputs[i].input.TextStyle = focusedStyle + cmds[i] = m.inputs[i].input.Focus() + } else { + m.inputs[i].input.Blur() + m.inputs[i].input.TextStyle = noStyle + } + } + return m, tea.Batch(cmds...) + + case tea.KeyEscape.String(): + m.State.Selection.Index = -1 + m.State.Selection.Key = "" } } return m, nil } -func (m *ContentPaneModel) View() string { +func (m *ContentPaneModel) updateFocusedInput(msg tea.Msg) tea.Cmd { + idx := m.inputFocusCapturedIdx + updatedInput, cmd := m.inputs[idx].input.Update(msg) + m.inputs[idx].input = updatedInput + return cmd +} +func (m *ContentPaneModel) View() string { selectedProfile, ok := m.State.GetCurrentProfile() if !ok { return "Select a profile to edit" } - m.BuildInputs(selectedProfile) - var b strings.Builder + if ok && !m.inputsInitialized { + m.BuildInputs(selectedProfile) + m.inputsInitialized = true + } + + var lines []string + for i, field := range m.inputs { + nameStyle := noStyle - for i := range m.inputs { - if m.cursor.Index == i { - m.inputs[i].input.Focus() - m.inputs[i].input.PromptStyle = focusedStyle - m.inputs[i].input.TextStyle = focusedStyle + if slices.Contains(m.modifiedInputs, i) { + nameStyle = nameStyle.Bold(true).Underline(true) + } + + var name string + if m.cursor.Index == i && m.inputFocusCapturedIdx != i { + name = nameStyle. + Background(Colors.Primary). + Foreground(Colors.OnPrimary). + Render(field.Name) } else { - m.inputs[i].input.Blur() - m.inputs[i].input.PromptStyle = lipgloss.NewStyle() - m.inputs[i].input.TextStyle = lipgloss.NewStyle() + name = nameStyle.Render(field.Name) } - b.WriteString(fmt.Sprintf("%s: %s", m.inputs[i].Name, m.inputs[i].input.View())) - if i < len(m.inputs)-1 { - b.WriteRune('\n') + + if m.inputFocusCapturedIdx == i { + field.input.TextStyle = focusedStyle + } else { + field.input.TextStyle = noStyle } + + line := lipgloss.JoinHorizontal( + lipgloss.Left, + lipgloss.NewStyle().Render(name+": "), + field.input.View(), + ) + + lines = append(lines, line) } - mainRender := contentStyle.Width(m.size.Width).Height(m.size.Height).Render(b.String()) - return mainRender + content := lipgloss.JoinVertical(lipgloss.Top, lines...) + return contentStyle.Width(m.size.Width).Height(m.size.Height).Render(content) } From 4ed735fa8b8c8eb92b677f6d0708ba1b0cb0f1e2 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Mon, 19 May 2025 21:44:35 +0100 Subject: [PATCH 23/31] chore: update dependencies in go.mod and go.sum --- go.mod | 8 ++++++-- go.sum | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 2c86b4f..841b08f 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,16 @@ go 1.23.0 toolchain go1.23.9 -require github.com/charmbracelet/bubbletea v1.3.5 +require ( + github.com/charmbracelet/bubbles v0.21.0 + github.com/charmbracelet/bubbletea v1.3.5 + github.com/charmbracelet/lipgloss v1.1.0 +) require ( + github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect - github.com/charmbracelet/lipgloss v1.1.0 // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect diff --git a/go.sum b/go.sum index f9453b6..8d8a54a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= +github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc= github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= From 4a0fdfadf8ff52dc073192284ddc767afe6ea514 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Tue, 20 May 2025 23:41:07 +0100 Subject: [PATCH 24/31] create footer panel tui --- main.go | 26 +++----------------------- tui/footer_pane.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 23 deletions(-) create mode 100644 tui/footer_pane.go diff --git a/main.go b/main.go index 2638c8b..adcc019 100644 --- a/main.go +++ b/main.go @@ -131,33 +131,13 @@ func initModel() layoutModel { DebugString: "right", State: &AppState, }, - footer: dummyLayout{ - debugString: "footer", + footer: &tui.FooterPaneModel{ + DebugString: "footer", + State: &AppState, }, } } -type dummyLayout struct { - debugString string - size layout.PaneSize -} - -func (m dummyLayout) Init() tea.Cmd { - return nil -} - -func (m dummyLayout) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case layout.SizeMsg: - m.size = msg.Size - } - return m, nil -} - -func (m dummyLayout) View() string { - return fmt.Sprintf("%s: %dx%d", m.debugString, m.size.Width, m.size.Height) -} - func main() { data, err := lib.LoadAWSProfileData() diff --git a/tui/footer_pane.go b/tui/footer_pane.go new file mode 100644 index 0000000..c50b235 --- /dev/null +++ b/tui/footer_pane.go @@ -0,0 +1,31 @@ +package tui + +import ( + "fmt" + + tea "github.com/charmbracelet/bubbletea" + "github.com/rodpadev/aws-profiles/layout" + "github.com/rodpadev/aws-profiles/state" +) + +type FooterPaneModel struct { + DebugString string + size layout.PaneSize + State *state.State +} + +func (m *FooterPaneModel) Init() tea.Cmd { + return nil +} + +func (m *FooterPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case layout.SizeMsg: + m.size = msg.Size + } + return m, nil +} + +func (m *FooterPaneModel) View() string { + return fmt.Sprintf("%s: %dx%d", m.DebugString, m.size.Width, m.size.Height) +} From a8506e45c694548bc54c7b95786b193b79ec62d9 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Tue, 20 May 2025 23:44:55 +0100 Subject: [PATCH 25/31] refactor: simplify ParseAWSProfileData return type and update usage in main --- lib/aws_interop.go | 4 ++-- main.go | 5 ++--- state/state.go | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/aws_interop.go b/lib/aws_interop.go index 8529313..c9f0666 100644 --- a/lib/aws_interop.go +++ b/lib/aws_interop.go @@ -56,7 +56,7 @@ func LoadAWSProfileData() ([][]byte, error) { return [][]byte{config, credentials}, nil } -func ParseAWSProfileData(data [][]byte) (map[string]map[string]string, int) { +func ParseAWSProfileData(data [][]byte) map[string]map[string]string { result := map[string]map[string]string{} combined := append(data[0], '\n') @@ -115,7 +115,7 @@ func ParseAWSProfileData(data [][]byte) (map[string]map[string]string, int) { } - return result, profileCount + return result } diff --git a/main.go b/main.go index adcc019..d9e3e08 100644 --- a/main.go +++ b/main.go @@ -145,7 +145,7 @@ func main() { log.Fatal(err) } - parsed, profileCount := lib.ParseAWSProfileData(data) + parsed := lib.ParseAWSProfileData(data) if err != nil { log.Fatal(err) } @@ -157,8 +157,7 @@ func main() { } AppState = state.State{ - ProfileMap: profileMap, - ProfileMapSize: profileCount, + ProfileMap: profileMap, } p := tea.NewProgram(initModel(), tea.WithAltScreen()) diff --git a/state/state.go b/state/state.go index c7e3e28..a5c965f 100644 --- a/state/state.go +++ b/state/state.go @@ -10,10 +10,10 @@ type ProfilePosition struct { } type State struct { - Selection ProfilePosition - ProfileMap lib.ProfileMap - ProfileMapSize int - ModifiedProfiledKeys []string + Selection ProfilePosition + ProfileMap lib.ProfileMap + EditedProfileMap lib.ProfileMap + IsCommandModeActive bool } func (s *State) GetCurrentProfile() (lib.Profile, bool) { From c308a200a00dc9545216bd31100a7026f5bd5681 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Wed, 21 May 2025 00:09:38 +0100 Subject: [PATCH 26/31] feat: implement command mode toggle and update footer pane display --- lib/lib_integration_test.go | 2 +- main.go | 28 ++++++++++++++++++++++------ tui/footer_pane.go | 16 ++++++++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/lib/lib_integration_test.go b/lib/lib_integration_test.go index 895fe3b..3f712ce 100644 --- a/lib/lib_integration_test.go +++ b/lib/lib_integration_test.go @@ -99,7 +99,7 @@ func TestIntegrationFlow(t *testing.T) { } // Parse AWS profile data - parsedData, _ := ParseAWSProfileData(data) + parsedData := ParseAWSProfileData(data) // Verify parsed data if len(parsedData) != 3 { // default, profile dev, profile prod, dev, prod diff --git a/main.go b/main.go index d9e3e08..cd3854a 100644 --- a/main.go +++ b/main.go @@ -57,18 +57,28 @@ func (m layoutModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg.String() { case "q", "ctrl+c": return m, tea.Quit + case ":": + AppState.IsCommandModeActive = true + return m, nil + case tea.KeyEscape.String(): + if AppState.IsCommandModeActive { + AppState.IsCommandModeActive = false + return m, nil + } } } var cmds []tea.Cmd - - if AppState.Selection.Key == "" { - m.leftPane, cmds = updateModel(m.leftPane, msg, cmds) + if !AppState.IsCommandModeActive { + if AppState.Selection.Key == "" { + m.leftPane, cmds = updateModel(m.leftPane, msg, cmds) + } else { + m.rightPane, cmds = updateModel(m.rightPane, msg, cmds) + } } else { - m.rightPane, cmds = updateModel(m.rightPane, msg, cmds) + m.footer, cmds = updateModel(m.footer, msg, cmds) } - m.footer, cmds = updateModel(m.footer, msg, cmds) return m, tea.Batch(cmds...) } @@ -110,7 +120,13 @@ func (m layoutModel) View() string { mainRender := lipgloss.JoinVertical(lipgloss.Top, topRow, footer) if m.width < 75 || m.height < 25 { - mainRender = lipgloss.Place(m.width, computedLayout.HeightAvailable, lipgloss.Center, lipgloss.Center, "Too Small! Expand your terminal") + mainRender = lipgloss.Place( + m.width, + computedLayout.HeightAvailable, + lipgloss.Center, + lipgloss.Center, + "Too Small! Expand your terminal", + ) } return lipgloss.NewStyle(). diff --git a/tui/footer_pane.go b/tui/footer_pane.go index c50b235..9449516 100644 --- a/tui/footer_pane.go +++ b/tui/footer_pane.go @@ -9,8 +9,8 @@ import ( ) type FooterPaneModel struct { - DebugString string size layout.PaneSize + DebugString string State *state.State } @@ -22,10 +22,22 @@ func (m *FooterPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case layout.SizeMsg: m.size = msg.Size + case tea.KeyMsg: + switch msg.String() { + case tea.KeyEscape.String(): + m.State.IsCommandModeActive = false + return m, nil + } } + return m, nil } func (m *FooterPaneModel) View() string { - return fmt.Sprintf("%s: %dx%d", m.DebugString, m.size.Width, m.size.Height) + if m.State.IsCommandModeActive { + return fmt.Sprintf(":") + } + + return fmt.Sprintf("Enter command mode with ':'") + } From 3be562a9dac4b5ad4676f9e7495b00ef0e441cc8 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Wed, 21 May 2025 00:10:22 +0100 Subject: [PATCH 27/31] remove DebugString from SidebarPaneModel and ContentPaneModel --- main.go | 9 +++------ tui/content_pane.go | 1 - tui/footer_pane.go | 5 ++--- tui/sidebar_pane.go | 1 - 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index cd3854a..cf6ac45 100644 --- a/main.go +++ b/main.go @@ -140,16 +140,13 @@ func (m layoutModel) View() string { func initModel() layoutModel { return layoutModel{ leftPane: &tui.SidebarPaneModel{ - DebugString: "left", - State: &AppState, + State: &AppState, }, rightPane: &tui.ContentPaneModel{ - DebugString: "right", - State: &AppState, + State: &AppState, }, footer: &tui.FooterPaneModel{ - DebugString: "footer", - State: &AppState, + State: &AppState, }, } } diff --git a/tui/content_pane.go b/tui/content_pane.go index c95f5cd..20639be 100644 --- a/tui/content_pane.go +++ b/tui/content_pane.go @@ -25,7 +25,6 @@ type ManagedInput struct { type ContentPaneModel struct { cursor state.Cursor State *state.State - DebugString string size layout.PaneSize profile state.ProfilePosition inputs []ManagedInput diff --git a/tui/footer_pane.go b/tui/footer_pane.go index 9449516..7a16800 100644 --- a/tui/footer_pane.go +++ b/tui/footer_pane.go @@ -9,9 +9,8 @@ import ( ) type FooterPaneModel struct { - size layout.PaneSize - DebugString string - State *state.State + size layout.PaneSize + State *state.State } func (m *FooterPaneModel) Init() tea.Cmd { diff --git a/tui/sidebar_pane.go b/tui/sidebar_pane.go index ccd4e61..d41125c 100644 --- a/tui/sidebar_pane.go +++ b/tui/sidebar_pane.go @@ -13,7 +13,6 @@ import ( type SidebarPaneModel struct { cursor state.Cursor State *state.State - DebugString string size layout.PaneSize profileKeys []string } From 4c095571a54cc117c9ba730474fcc148267522c7 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Wed, 21 May 2025 00:16:07 +0100 Subject: [PATCH 28/31] rename properites --- tui/content_pane.go | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tui/content_pane.go b/tui/content_pane.go index 20639be..c322b8d 100644 --- a/tui/content_pane.go +++ b/tui/content_pane.go @@ -23,20 +23,20 @@ type ManagedInput struct { } type ContentPaneModel struct { - cursor state.Cursor - State *state.State - size layout.PaneSize - profile state.ProfilePosition - inputs []ManagedInput - modifiedInputs []int - isInputFocusCaptured bool - inputFocusCapturedIdx int - inputsInitialized bool + cursor state.Cursor + State *state.State + size layout.PaneSize + profile state.ProfilePosition + inputs []ManagedInput + modifiedInputs []int + isInputFocusLocked bool + focusedInputIndex int + inputsInitialized bool } func (m *ContentPaneModel) BuildInputs(profile lib.Profile) { - m.inputFocusCapturedIdx = -1 - m.isInputFocusCaptured = false + m.focusedInputIndex = -1 + m.isInputFocusLocked = false m.inputs = make([]ManagedInput, 5) var t ManagedInput @@ -83,12 +83,12 @@ func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.KeyMsg: key := msg.String() - if m.isInputFocusCaptured { + if m.isInputFocusLocked { cmd := m.updateFocusedInput(msg) if key == tea.KeyEscape.String() { - m.modifiedInputs = append(m.modifiedInputs, m.inputFocusCapturedIdx) - m.isInputFocusCaptured = false - m.inputFocusCapturedIdx = -1 + m.modifiedInputs = append(m.modifiedInputs, m.focusedInputIndex) + m.isInputFocusLocked = false + m.focusedInputIndex = -1 } return m, cmd } @@ -97,12 +97,12 @@ func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch key { case tea.KeyEnter.String(): - m.isInputFocusCaptured = true - m.inputFocusCapturedIdx = m.cursor.Index + m.isInputFocusLocked = true + m.focusedInputIndex = m.cursor.Index cmds := make([]tea.Cmd, len(m.inputs)) for i := range m.inputs { - if i == m.inputFocusCapturedIdx { + if i == m.focusedInputIndex { m.inputs[i].input.TextStyle = focusedStyle cmds[i] = m.inputs[i].input.Focus() } else { @@ -122,7 +122,7 @@ func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m *ContentPaneModel) updateFocusedInput(msg tea.Msg) tea.Cmd { - idx := m.inputFocusCapturedIdx + idx := m.focusedInputIndex updatedInput, cmd := m.inputs[idx].input.Update(msg) m.inputs[idx].input = updatedInput return cmd @@ -148,7 +148,7 @@ func (m *ContentPaneModel) View() string { } var name string - if m.cursor.Index == i && m.inputFocusCapturedIdx != i { + if m.cursor.Index == i && m.focusedInputIndex != i { name = nameStyle. Background(Colors.Primary). Foreground(Colors.OnPrimary). @@ -157,7 +157,7 @@ func (m *ContentPaneModel) View() string { name = nameStyle.Render(field.Name) } - if m.inputFocusCapturedIdx == i { + if m.focusedInputIndex == i { field.input.TextStyle = focusedStyle } else { field.input.TextStyle = noStyle From 7b49483054dd39e8b987526b232559bbb5e8f181 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Wed, 21 May 2025 00:39:53 +0100 Subject: [PATCH 29/31] keep track of edited profiles and fields globally --- lib/profile.go | 32 ++++++++++++++++++++++++++++++++ main.go | 3 ++- state/state.go | 19 +++++++++++++++++++ tui/content_pane.go | 44 +++++++++++++++++++++++++++++++------------- 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/lib/profile.go b/lib/profile.go index d6b44be..f5f37f2 100644 --- a/lib/profile.go +++ b/lib/profile.go @@ -38,3 +38,35 @@ func BuildProfileMap(data map[string]map[string]string) (ProfileMap, error) { return profiles, nil } + +func (p *Profile) SetField(field, value string) { + switch field { + case "name": + p.Name = value + case "aws_access_key_id": + p.Credential.AccessKey = value + case "aws_secret_access_key": + p.Credential.SecretKey = value + case "region": + p.Config.Region = value + case "output": + p.Config.Output = value + } +} + +func (p Profile) GetField(field string) string { + switch field { + case "name": + return p.Name + case "aws_access_key_id": + return p.Credential.AccessKey + case "aws_secret_access_key": + return p.Credential.SecretKey + case "region": + return p.Config.Region + case "output": + return p.Config.Output + default: + return "" + } +} diff --git a/main.go b/main.go index cf6ac45..d698163 100644 --- a/main.go +++ b/main.go @@ -170,7 +170,8 @@ func main() { } AppState = state.State{ - ProfileMap: profileMap, + ProfileMap: profileMap, + EditedProfileMap: lib.ProfileMap{}, } p := tea.NewProgram(initModel(), tea.WithAltScreen()) diff --git a/state/state.go b/state/state.go index a5c965f..25de739 100644 --- a/state/state.go +++ b/state/state.go @@ -20,3 +20,22 @@ func (s *State) GetCurrentProfile() (lib.Profile, bool) { currentProfile, ok := s.ProfileMap[s.Selection.Key] return currentProfile, ok } + +func (s *State) IsFieldEdited(profileKey string, field string) bool { + if s.EditedProfileMap == nil { + return false + } + editedProfile, ok := s.EditedProfileMap[profileKey] + if !ok { + return false + } + originalProfile, ok := s.ProfileMap[profileKey] + if !ok { + return false + } + originalField := originalProfile.GetField(field) + editedField := editedProfile.GetField(field) + + return originalField != editedField + +} diff --git a/tui/content_pane.go b/tui/content_pane.go index c322b8d..1f7d07f 100644 --- a/tui/content_pane.go +++ b/tui/content_pane.go @@ -1,8 +1,6 @@ package tui import ( - "slices" - "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" @@ -20,6 +18,7 @@ var ( type ManagedInput struct { Name string input textinput.Model + field string } type ContentPaneModel struct { @@ -28,7 +27,6 @@ type ContentPaneModel struct { size layout.PaneSize profile state.ProfilePosition inputs []ManagedInput - modifiedInputs []int isInputFocusLocked bool focusedInputIndex int inputsInitialized bool @@ -49,21 +47,26 @@ func (m *ContentPaneModel) BuildInputs(profile lib.Profile) { switch i { case 0: + t.field = "name" t.Name = "Profile Name" t.input.CharLimit = 32 t.input.SetValue(profile.Name) case 1: + t.field = "aws_access_key_id" t.Name = "Access Key" t.input.SetValue(profile.Credential.AccessKey) case 2: + t.field = "aws_secret_access_key" t.Name = "Secret Key" t.input.EchoMode = textinput.EchoPassword t.input.EchoCharacter = 0 t.input.SetValue(profile.Credential.SecretKey) case 3: + t.field = "output" t.Name = "Output" t.input.SetValue(profile.Config.Output) case 4: + t.field = "region" t.Name = "Region" t.input.SetValue(profile.Config.Region) } @@ -86,7 +89,20 @@ func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.isInputFocusLocked { cmd := m.updateFocusedInput(msg) if key == tea.KeyEscape.String() { - m.modifiedInputs = append(m.modifiedInputs, m.focusedInputIndex) + modifiedValue := m.inputs[m.focusedInputIndex].input.Value() + profile, ok := m.State.GetCurrentProfile() + if ok && modifiedValue != profile.GetField(m.inputs[m.focusedInputIndex].field) { + + key := m.State.Selection.Key + edited, exists := m.State.EditedProfileMap[key] + if !exists { + edited = profile + } + + edited.SetField(m.inputs[m.focusedInputIndex].field, modifiedValue) + + m.State.EditedProfileMap[key] = edited + } m.isInputFocusLocked = false m.focusedInputIndex = -1 } @@ -113,6 +129,8 @@ func (m *ContentPaneModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Batch(cmds...) case tea.KeyEscape.String(): + // exit content pane + // todo: this should be handled in the main loop m.State.Selection.Index = -1 m.State.Selection.Key = "" } @@ -140,33 +158,33 @@ func (m *ContentPaneModel) View() string { } var lines []string - for i, field := range m.inputs { + for idx, input := range m.inputs { nameStyle := noStyle - if slices.Contains(m.modifiedInputs, i) { + if m.State.IsFieldEdited(m.State.Selection.Key, input.field) { nameStyle = nameStyle.Bold(true).Underline(true) } var name string - if m.cursor.Index == i && m.focusedInputIndex != i { + if m.cursor.Index == idx && m.focusedInputIndex != idx { name = nameStyle. Background(Colors.Primary). Foreground(Colors.OnPrimary). - Render(field.Name) + Render(input.Name) } else { - name = nameStyle.Render(field.Name) + name = nameStyle.Render(input.Name) } - if m.focusedInputIndex == i { - field.input.TextStyle = focusedStyle + if m.focusedInputIndex == idx { + input.input.TextStyle = focusedStyle } else { - field.input.TextStyle = noStyle + input.input.TextStyle = noStyle } line := lipgloss.JoinHorizontal( lipgloss.Left, lipgloss.NewStyle().Render(name+": "), - field.input.View(), + input.input.View(), ) lines = append(lines, line) From e2d4673fed6332e0a4099879bfbee6c6d6a045e3 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Wed, 21 May 2025 00:57:31 +0100 Subject: [PATCH 30/31] feat: add profile editing state tracking and update UI indicators --- state/state.go | 8 ++++++++ tui/content_pane.go | 10 ++++++++-- tui/sidebar_pane.go | 7 ++++++- tui/theme.go | 2 ++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/state/state.go b/state/state.go index 25de739..115e4bc 100644 --- a/state/state.go +++ b/state/state.go @@ -39,3 +39,11 @@ func (s *State) IsFieldEdited(profileKey string, field string) bool { return originalField != editedField } + +func (s *State) IsProfileEdited(profileKey string) bool { + if s.EditedProfileMap == nil { + return false + } + _, ok := s.EditedProfileMap[profileKey] + return ok +} diff --git a/tui/content_pane.go b/tui/content_pane.go index 1f7d07f..efd8203 100644 --- a/tui/content_pane.go +++ b/tui/content_pane.go @@ -1,6 +1,8 @@ package tui import ( + "fmt" + "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" @@ -11,7 +13,7 @@ import ( var ( focusedStyle = lipgloss.NewStyle().Foreground(Colors.Primary) - contentStyle = lipgloss.NewStyle().PaddingLeft(2) + contentStyle = lipgloss.NewStyle().PaddingLeft(1) noStyle = lipgloss.NewStyle() ) @@ -160,9 +162,11 @@ func (m *ContentPaneModel) View() string { var lines []string for idx, input := range m.inputs { nameStyle := noStyle + prefix := " " if m.State.IsFieldEdited(m.State.Selection.Key, input.field) { nameStyle = nameStyle.Bold(true).Underline(true) + prefix = Icons.ModifiedMarker } var name string @@ -183,7 +187,9 @@ func (m *ContentPaneModel) View() string { line := lipgloss.JoinHorizontal( lipgloss.Left, - lipgloss.NewStyle().Render(name+": "), + lipgloss.NewStyle().Render( + fmt.Sprintf("%s %s: ", prefix, name), + ), input.input.View(), ) diff --git a/tui/sidebar_pane.go b/tui/sidebar_pane.go index d41125c..f9414ff 100644 --- a/tui/sidebar_pane.go +++ b/tui/sidebar_pane.go @@ -58,6 +58,8 @@ func (m *SidebarPaneModel) View() string { for idx, profile := range m.profileKeys { prefix := Icons.SidebarCursorInactive style := lipgloss.NewStyle().Width(m.size.Width) + profileStyle := lipgloss.NewStyle() + suffix := "" isActiveIndex := m.cursor.Index == idx isCurrentSelection := m.State.Selection.Index == idx @@ -75,6 +77,9 @@ func (m *SidebarPaneModel) View() string { case isCurrentSelection: fg = lipgloss.Color(Colors.OnPrimary) bg = lipgloss.Color(Colors.Primary) + case m.State.IsProfileEdited(profile): + profileStyle = style.Bold(true).Underline(true) + suffix = Icons.ModifiedMarker default: fg = lipgloss.Color(Colors.Text) } @@ -87,7 +92,7 @@ func (m *SidebarPaneModel) View() string { style = style.UnsetBackground() } - lines[idx] = style.Render(fmt.Sprintf(" %s %s", prefix, profile)) + lines[idx] = style.Render(fmt.Sprintf(" %s %s", prefix, profileStyle.Render(profile+suffix))) } return lipgloss.NewStyle(). diff --git a/tui/theme.go b/tui/theme.go index 0e9b992..cf28eb9 100644 --- a/tui/theme.go +++ b/tui/theme.go @@ -15,7 +15,9 @@ var Colors = struct { var Icons = struct { SidebarCursorActive string SidebarCursorInactive string + ModifiedMarker string }{ SidebarCursorActive: "▶", SidebarCursorInactive: " ", + ModifiedMarker: "●", } From c422b50c653564c6e3df37720fd21b21e351f6e1 Mon Sep 17 00:00:00 2001 From: "Patrick Rodrigues (rodapdev)" <47316946+RodPaDev@users.noreply.github.com> Date: Wed, 21 May 2025 01:08:24 +0100 Subject: [PATCH 31/31] fix: correct profile style rendering and improve modified marker display --- tui/sidebar_pane.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tui/sidebar_pane.go b/tui/sidebar_pane.go index f9414ff..299cc38 100644 --- a/tui/sidebar_pane.go +++ b/tui/sidebar_pane.go @@ -58,7 +58,7 @@ func (m *SidebarPaneModel) View() string { for idx, profile := range m.profileKeys { prefix := Icons.SidebarCursorInactive style := lipgloss.NewStyle().Width(m.size.Width) - profileStyle := lipgloss.NewStyle() + suffix := "" isActiveIndex := m.cursor.Index == idx @@ -77,13 +77,20 @@ func (m *SidebarPaneModel) View() string { case isCurrentSelection: fg = lipgloss.Color(Colors.OnPrimary) bg = lipgloss.Color(Colors.Primary) - case m.State.IsProfileEdited(profile): - profileStyle = style.Bold(true).Underline(true) - suffix = Icons.ModifiedMarker + default: fg = lipgloss.Color(Colors.Text) } + profileStyle := style + if m.State.IsProfileEdited(profile) { + profileStyle = style.Bold(true). + Underline(true). + Background(bg). + Foreground(fg) + suffix = Icons.ModifiedMarker + } + style = style.Foreground(fg) if isCurrentSelection { @@ -92,7 +99,7 @@ func (m *SidebarPaneModel) View() string { style = style.UnsetBackground() } - lines[idx] = style.Render(fmt.Sprintf(" %s %s", prefix, profileStyle.Render(profile+suffix))) + lines[idx] = style.Render(fmt.Sprintf(" %s %s", prefix, profileStyle.Render(profile+" "+suffix))) } return lipgloss.NewStyle().