From f05f0cc38d500c8599e18eb57d540c68f36dd16c Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Sat, 6 Sep 2025 00:33:24 +0900 Subject: [PATCH 1/3] ci: migrate to semantic-release Adopt semantic-release for automated versioning. All future commits must follow Conventional Commits format. - Add semantic-release configuration and workflows - Add commitizen for guided commit messages - Add commitlint for PR validation - Update documentation for new workflow - Update repository URLs to CrackingShells organization This enables fully automated versioning and releases for the validation library. --- .commitlintrc.json | 27 + .github/workflows/commitlint.yml | 25 + .github/workflows/semantic-release.yml | 64 + .gitignore | 9 + .releaserc.json | 62 + CONTRIBUTING.md | 223 + README.md | 36 +- package-lock.json | 8790 ++++++++++++++++++++++++ package.json | 23 + 9 files changed, 9257 insertions(+), 2 deletions(-) create mode 100644 .commitlintrc.json create mode 100644 .github/workflows/commitlint.yml create mode 100644 .github/workflows/semantic-release.yml create mode 100644 .releaserc.json create mode 100644 CONTRIBUTING.md create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.commitlintrc.json b/.commitlintrc.json new file mode 100644 index 0000000..eca3a08 --- /dev/null +++ b/.commitlintrc.json @@ -0,0 +1,27 @@ +{ + "extends": ["@commitlint/config-conventional"], + "rules": { + "type-enum": [ + 2, + "always", + [ + "build", + "chore", + "ci", + "docs", + "feat", + "fix", + "perf", + "refactor", + "revert", + "style", + "test" + ] + ], + "subject-case": [2, "never", ["start-case", "pascal-case", "upper-case"]], + "subject-empty": [2, "never"], + "subject-full-stop": [2, "never", "."], + "header-max-length": [2, "always", 72], + "body-max-line-length": [2, "always", 500] + } +} diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..300aaa6 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,25 @@ +name: Commit Lint + +on: + pull_request: + branches: [main, dev] + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "lts/*" + + - name: Install dependencies + run: npm ci + + - name: Validate PR commits with commitlint + run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose diff --git a/.github/workflows/semantic-release.yml b/.github/workflows/semantic-release.yml new file mode 100644 index 0000000..ca762ad --- /dev/null +++ b/.github/workflows/semantic-release.yml @@ -0,0 +1,64 @@ +name: Semantic Release + +on: + push: + branches: + - main + - dev + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install -e . + + - name: Run tests + run: | + python -c "import hatch_validator; print('Package imports successfully')" + + release: + needs: test + runs-on: ubuntu-latest + if: github.event_name == 'push' + steps: + - name: Generate GitHub App Token + id: generate_token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.SEMANTIC_RELEASE_APP_ID }} + private_key: ${{ secrets.SEMANTIC_RELEASE_PRIVATE_KEY }} + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ steps.generate_token.outputs.token }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "lts/*" + + - name: Install Node dependencies + run: npm ci + + - name: Verify npm audit + run: npm audit signatures + + - name: Release + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + run: npx semantic-release diff --git a/.gitignore b/.gitignore index 0a19790..2f33375 100644 --- a/.gitignore +++ b/.gitignore @@ -172,3 +172,12 @@ cython_debug/ # PyPI configuration file .pypirc + +# Node.js dependencies for semantic-release +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Semantic-release +.semantic-release/ diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 0000000..efad62f --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,62 @@ +{ + "repositoryUrl": "https://github.com/CrackingShells/Hatch-Validator", + "tagFormat": "v${version}", + "branches": [ + "main", + { + "name": "dev", + "prerelease": "dev" + } + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + {"type": "docs", "scope": "README", "release": "patch"}, + {"type": "refactor", "release": "patch"}, + {"type": "style", "release": "patch"}, + {"type": "test", "release": false}, + {"type": "chore", "release": false} + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + {"type": "feat", "section": "Features"}, + {"type": "fix", "section": "Bug Fixes"}, + {"type": "docs", "section": "Documentation"}, + {"type": "refactor", "section": "Code Refactoring"}, + {"type": "perf", "section": "Performance Improvements"} + ] + } + } + ], + [ + "@semantic-release/changelog", + { + "changelogFile": "CHANGELOG.md" + } + ], + [ + "@semantic-release/git", + { + "assets": ["CHANGELOG.md", "pyproject.toml"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ], + [ + "@semantic-release/github", + { + "successComment": false, + "failComment": false, + "releasedLabels": false + } + ] + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..bffa0b1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,223 @@ +# Contributing to Hatch-Validator + +Thank you for your interest in contributing to Hatch-Validator! This guide will help you get started with our development workflow and contribution standards. + +## Commit Message Format + +We use [Conventional Commits](https://www.conventionalcommits.org/) for automated versioning and changelog generation. + +### Format + +``` +[optional scope]: + +[optional body] + +[optional footer(s)] +``` + +### Types + +- **feat**: New features (triggers minor version bump) +- **fix**: Bug fixes (triggers patch version bump) +- **docs**: Documentation changes +- **refactor**: Code refactoring without functional changes +- **test**: Adding or updating tests +- **chore**: Maintenance tasks, dependency updates +- **ci**: Changes to CI/CD configuration +- **perf**: Performance improvements +- **style**: Code style changes (formatting, etc.) + +### Examples + +```bash +# Good commit messages +feat: add support for schema version 1.3.0 +fix: resolve validation error for empty dependencies +docs: update API documentation for package validator +refactor: simplify dependency resolution logic +test: add integration tests for schema validation +chore: update dependencies to latest versions + +# Breaking changes (use sparingly until v1.0.0) +feat!: change validation API interface +fix!: remove deprecated validation methods + +# With scope +feat(validator): add new validation rules +fix(schema): resolve schema loading timeout +docs(api): update validation method documentation +``` + +### Using Commitizen + +For guided commit messages, use commitizen: + +```bash +# Install dependencies first +npm install + +# Use commitizen for guided commits +npm run commit +# or +npx cz +``` + +This will prompt you through creating a properly formatted commit message. + +## Development Workflow + +### 1. Fork and Clone + +```bash +git clone https://github.com/YOUR_USERNAME/Hatch-Validator.git +cd Hatch-Validator +``` + +### 2. Set Up Development Environment + +```bash +# Install Python dependencies +pip install -e . + +# Install Node.js dependencies for semantic-release +npm install +``` + +### 3. Create Feature Branch + +```bash +git checkout -b feat/your-feature-name +# or +git checkout -b fix/your-bug-fix +``` + +### 4. Make Changes + +- Write code following existing patterns +- Add tests for new functionality +- Update documentation as needed +- Follow PEP 8 style guidelines + +### 5. Test Your Changes + +```bash +# Run basic import test +python -c "import hatch_validator; print('Package imports successfully')" + +# Add more comprehensive tests when available +``` + +### 6. Commit Changes + +```bash +# Use commitizen for guided commits +npm run commit + +# Or commit manually with conventional format +git commit -m "feat: add your feature description" +``` + +### 7. Push and Create Pull Request + +```bash +git push origin feat/your-feature-name +``` + +Then create a pull request on GitHub. + +## Pull Request Guidelines + +### Title Format + +Use conventional commit format for PR titles: +- `feat: add new validation functionality` +- `fix: resolve schema parsing issue` +- `docs: update installation guide` + +### Description + +Include in your PR description: +- **What**: Brief description of changes +- **Why**: Reason for the changes +- **How**: Implementation approach (if complex) +- **Testing**: How you tested the changes +- **Breaking Changes**: Any breaking changes (if applicable) + +### Checklist + +- [ ] Code follows existing style and patterns +- [ ] Tests added for new functionality +- [ ] Documentation updated (if needed) +- [ ] Commit messages follow conventional format +- [ ] All tests pass +- [ ] No breaking changes (unless intentional and documented) + +## Code Style + +### Python + +- Follow PEP 8 style guidelines +- Use type hints where appropriate +- Write docstrings for public functions and classes +- Keep functions focused and small +- Use meaningful variable and function names + +### Documentation + +- Update relevant documentation for changes +- Use clear, concise language +- Include code examples where helpful +- Keep README.md up to date + +## Testing + +### Running Tests + +```bash +# Basic import test +python -c "import hatch_validator; print('Package imports successfully')" + +# Add comprehensive test commands when test suite is available +``` + +### Writing Tests + +- Add tests for new features +- Test edge cases and error conditions +- Use descriptive test names +- Follow existing test patterns + +## Release Process + +Releases are fully automated using semantic-release: + +1. **Commits are analyzed** for conventional commit format +2. **Version is calculated** based on commit types +3. **Changelog is generated** from commit messages +4. **Version files are updated** (pyproject.toml, CHANGELOG.md) +5. **Changes are committed** back to repository using GitHub App +6. **GitHub release is created** with release notes and tags + +### Version Impact + +- `feat:` commits → Minor version (0.7.1 → 0.8.0) +- `fix:` commits → Patch version (0.7.1 → 0.7.2) +- `feat!:` or `BREAKING CHANGE:` → Major version (0.7.1 → 1.0.0) +- Other types → No release + +## Getting Help + +- **Issues**: Report bugs or request features via GitHub Issues +- **Discussions**: Ask questions in GitHub Discussions +- **Documentation**: Check existing documentation for guidance +- **Code**: Look at existing code for patterns and examples + +## Code of Conduct + +- Be respectful and inclusive +- Focus on constructive feedback +- Help others learn and grow +- Follow GitHub's community guidelines + +Thank you for contributing to Hatch-Validator! 🚀 diff --git a/README.md b/README.md index 10dac13..cdfbd2c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ A validation package for Hatch packages and dependencies. ```bash # Install directly from the repository -pip install git+https://github.com/yourusername/Hatch-Validator.git +pip install git+https://github.com/CrackingShells/Hatch-Validator.git # Or install local copy pip install /path/to/Hatch-Validator @@ -25,11 +25,13 @@ pip install /path/to/Hatch-Validator If using as a git submodule: 1. Add as a submodule to your project: + ```bash - git submodule add https://github.com/yourusername/Hatch-Validator.git validator + git submodule add https://github.com/CrackingShells/Hatch-Validator.git validator ``` 2. Install the submodule as a package: + ```bash pip install ./validator ``` @@ -56,6 +58,36 @@ resolver = DependencyResolver() missing_deps = resolver.get_missing_hatch_dependencies(dependencies) ``` +## Contributing + +We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details. + +### Quick Start + +1. **Fork and clone** the repository +2. **Install dependencies**: `pip install -e .` and `npm install` +3. **Create a feature branch**: `git checkout -b feat/your-feature` +4. **Make changes** and add tests +5. **Use conventional commits**: `npm run commit` for guided commits +6. **Run tests**: `python -c "import hatch_validator; print('Package imports successfully')"` +7. **Create a pull request** + +### Commit Messages + +We use [Conventional Commits](https://www.conventionalcommits.org/) for automated versioning: + +```bash +feat: add new feature +fix: resolve bug +docs: update documentation +test: add tests +chore: maintenance tasks +``` + +Use `npm run commit` for guided commit messages. + +For detailed guidelines, see [CONTRIBUTING.md](./CONTRIBUTING.md). + ## License AGPL v3: see [file](./LICENSE) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..cc13985 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8790 @@ +{ + "name": "hatch-validator", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hatch-validator", + "devDependencies": { + "@commitlint/cli": "^18.6.1", + "@commitlint/config-conventional": "^18.6.2", + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^9.2.6", + "commitizen": "^4.3.0", + "cz-conventional-changelog": "^3.3.0", + "semantic-release": "^22.0.12" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@commitlint/cli": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-18.6.1.tgz", + "integrity": "sha512-5IDE0a+lWGdkOvKH892HHAZgbAjcj1mT5QrfA/SVbLJV/BbBMGyKN0W5mhgjekPJJwEQdVNvhl9PwUacY58Usw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^18.6.1", + "@commitlint/lint": "^18.6.1", + "@commitlint/load": "^18.6.1", + "@commitlint/read": "^18.6.1", + "@commitlint/types": "^18.6.1", + "execa": "^5.0.0", + "lodash.isfunction": "^3.0.9", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "18.6.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-18.6.3.tgz", + "integrity": "sha512-8ZrRHqF6je+TRaFoJVwszwnOXb/VeYrPmTwPhf0WxpzpGTcYy1p0SPyZ2eRn/sRi/obnWAcobtDAq6+gJQQNhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^18.6.1", + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-18.6.1.tgz", + "integrity": "sha512-05uiToBVfPhepcQWE1ZQBR/Io3+tb3gEotZjnI4tTzzPk16NffN6YABgwFQCLmzZefbDcmwWqJWc2XT47q7Znw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^18.6.1", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-18.6.1.tgz", + "integrity": "sha512-BPm6+SspyxQ7ZTsZwXc7TRQL5kh5YWt3euKmEIBZnocMFkJevqs3fbLRb8+8I/cfbVcAo4mxRlpTPfz8zX7SnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^18.6.1", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-18.6.1.tgz", + "integrity": "sha512-7s37a+iWyJiGUeMFF6qBlyZciUkF8odSAnHijbD36YDctLhGKoYltdvuJ/AFfRm6cBLRtRk9cCVPdsEFtt/2rg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-18.6.1.tgz", + "integrity": "sha512-K8mNcfU/JEFCharj2xVjxGSF+My+FbUHoqR+4GqPGrHNqXOGNio47ziiR4HQUPKtiNs05o8/WyLBoIpMVOP7wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^18.6.1", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-18.6.1.tgz", + "integrity": "sha512-MOfJjkEJj/wOaPBw5jFjTtfnx72RGwqYIROABudOtJKW7isVjFe9j0t8xhceA02QebtYf4P/zea4HIwnXg8rvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^18.6.1", + "semver": "7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-18.6.1.tgz", + "integrity": "sha512-8WwIFo3jAuU+h1PkYe5SfnIOzp+TtBHpFr4S8oJWhu44IWKuVx6GOPux3+9H1iHOan/rGBaiacicZkMZuluhfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^18.6.1", + "@commitlint/parse": "^18.6.1", + "@commitlint/rules": "^18.6.1", + "@commitlint/types": "^18.6.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-18.6.1.tgz", + "integrity": "sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^18.6.1", + "@commitlint/execute-rule": "^18.6.1", + "@commitlint/resolve-extends": "^18.6.1", + "@commitlint/types": "^18.6.1", + "chalk": "^4.1.0", + "cosmiconfig": "^8.3.6", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/message": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-18.6.1.tgz", + "integrity": "sha512-VKC10UTMLcpVjMIaHHsY1KwhuTQtdIKPkIdVEwWV+YuzKkzhlI3aNy6oo1eAN6b/D2LTtZkJe2enHmX0corYRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-18.6.1.tgz", + "integrity": "sha512-eS/3GREtvVJqGZrwAGRwR9Gdno3YcZ6Xvuaa+vUF8j++wsmxrA2En3n0ccfVO2qVOLJC41ni7jSZhQiJpMPGOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^18.6.1", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-18.6.1.tgz", + "integrity": "sha512-ia6ODaQFzXrVul07ffSgbZGFajpe8xhnDeLIprLeyfz3ivQU1dIoHp7yz0QIorZ6yuf4nlzg4ZUkluDrGN/J/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^18.6.1", + "@commitlint/types": "^18.6.1", + "git-raw-commits": "^2.0.11", + "minimist": "^1.2.6" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-18.6.1.tgz", + "integrity": "sha512-ifRAQtHwK+Gj3Bxj/5chhc4L2LIc3s30lpsyW67yyjsETR6ctHAHRu1FSpt0KqahK5xESqoJ92v6XxoDRtjwEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^18.6.1", + "@commitlint/types": "^18.6.1", + "import-fresh": "^3.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-18.6.1.tgz", + "integrity": "sha512-kguM6HxZDtz60v/zQYOe0voAtTdGybWXefA1iidjWYmyUUspO1zBPQEmJZ05/plIAqCVyNUTAiRPWIBKLCrGew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^18.6.1", + "@commitlint/message": "^18.6.1", + "@commitlint/to-lines": "^18.6.1", + "@commitlint/types": "^18.6.1", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-18.6.1.tgz", + "integrity": "sha512-Gl+orGBxYSNphx1+83GYeNy5N0dQsHBQ9PJMriaLQDB51UQHCVLBT/HBdOx5VaYksivSf5Os55TLePbRLlW50Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-18.6.1.tgz", + "integrity": "sha512-HyiHQZUTf0+r0goTCDs/bbVv/LiiQ7AVtz6KIar+8ZrseB9+YJAIo8HQ2IC2QT1y3N1lbW6OqVEsTHjbT6hGSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-18.6.1.tgz", + "integrity": "sha512-gwRLBLra/Dozj2OywopeuHj2ac26gjGkz2cZ+86cTJOdtWfiRRr4+e77ZDAGc6MDWxaWheI+mAV5TLWWRwqrFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", + "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz", + "integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.2.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^5.0.0" + } + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@semantic-release/changelog": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.3.tgz", + "integrity": "sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "fs-extra": "^11.0.0", + "lodash": "^4.17.4" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/commit-analyzer": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-11.1.0.tgz", + "integrity": "sha512-cXNTbv3nXR2hlzHjAMgbuiQVtvWHTlwwISt60B+4NZv01y/QRY7p2HcJm8Eh2StzcTJoNnflvKjHH/cjFS7d5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "debug": "^4.0.0", + "import-from-esm": "^1.0.3", + "lodash-es": "^4.17.21", + "micromatch": "^4.0.2" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", + "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@semantic-release/git": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", + "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/github": { + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-9.2.6.tgz", + "integrity": "sha512-shi+Lrf6exeNZF+sBhK+P011LSbhmIAoUEgEY6SsxF8irJ+J2stwI5jkyDQ+4gzYyDImzV6LCKdYB9FXnQRWKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-retry": "^6.0.0", + "@octokit/plugin-throttling": "^8.0.0", + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^5.0.0", + "debug": "^4.3.4", + "dir-glob": "^3.0.1", + "globby": "^14.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "issue-parser": "^6.0.0", + "lodash-es": "^4.17.21", + "mime": "^4.0.0", + "p-filter": "^4.0.0", + "url-join": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@semantic-release/github/node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-11.0.3.tgz", + "integrity": "sha512-KUsozQGhRBAnoVg4UMZj9ep436VEGwT536/jwSqB7vcEfA6oncCUU7UIYTRdLx7GvTtqn0kBjnkfLVkcnBa2YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^5.0.0", + "execa": "^8.0.0", + "fs-extra": "^11.0.0", + "lodash-es": "^4.17.21", + "nerf-dart": "^1.0.0", + "normalize-url": "^8.0.0", + "npm": "^10.5.0", + "rc": "^1.2.8", + "read-pkg": "^9.0.0", + "registry-auth-token": "^5.0.0", + "semver": "^7.1.2", + "tempy": "^3.0.0" + }, + "engines": { + "node": "^18.17 || >=20" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@semantic-release/npm/node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@semantic-release/npm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@semantic-release/npm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-12.1.0.tgz", + "integrity": "sha512-g6M9AjUKAZUZnxaJZnouNBeDNTCUrJ5Ltj+VJ60gJeDaRRahcHsry9HW8yKrnKkKNkx5lbWiEP1FPMqVNQz8Kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-writer": "^7.0.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "debug": "^4.0.0", + "get-stream": "^7.0.0", + "import-from-esm": "^1.0.3", + "into-stream": "^7.0.0", + "lodash-es": "^4.17.21", + "read-pkg-up": "^11.0.0" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/get-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", + "integrity": "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/argv-formatter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", + "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commitizen": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.1.tgz", + "integrity": "sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cachedir": "2.3.0", + "cz-conventional-changelog": "3.3.0", + "dedent": "0.7.0", + "detect-indent": "6.1.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "9.1.0", + "glob": "7.2.3", + "inquirer": "8.2.5", + "is-utf8": "^0.2.1", + "lodash": "4.17.21", + "minimist": "1.2.7", + "strip-bom": "4.0.0", + "strip-json-comments": "3.1.1" + }, + "bin": { + "commitizen": "bin/commitizen", + "cz": "bin/git-cz", + "git-cz": "bin/git-cz" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/commitizen/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/commitizen/node_modules/minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", + "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-filter": "^4.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^12.0.1", + "semver": "^7.5.2", + "split2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true, + "license": "ISC" + }, + "node_modules/conventional-commits-filter": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", + "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.1.0.tgz", + "integrity": "sha512-7PtBB+6FdsOvZyJtlF3hEPpACq7RQX6BVGsgC7/lfVXnKMvNCu/XY3ykreqG5w/rBNdu2z8LCIKoF3kpHHdHlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "^1.21.6" + }, + "engines": { + "node": ">=v16" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=8.2", + "typescript": ">=4" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cz-conventional-changelog": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", + "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" + } + }, + "node_modules/cz-conventional-changelog/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/cz-conventional-changelog/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cz-conventional-changelog/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/env-ci": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-10.0.0.tgz", + "integrity": "sha512-U4xcd/utDYFgMh0yWj07R1H6L5fwhVbmxBCpnL0DbVSDZVnsC82HONw0wxtxNkIAcua3KtbomQvIk5xFZGAQJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^8.0.0", + "java-properties": "^1.0.2" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, + "node_modules/env-ci/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/env-ci/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/env-ci/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/env-ci/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "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.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-node-modules": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", + "integrity": "sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.1" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-versions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-regex": "^4.0.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-log-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.1.tgz", + "integrity": "sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "0.6.8" + } + }, + "node_modules/git-log-parser/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/git-log-parser/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/git-log-parser/node_modules/split2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "~2.0.0" + } + }, + "node_modules/git-log-parser/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/git-log-parser/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-raw-commits/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/git-raw-commits/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-raw-commits/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/git-raw-commits/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-raw-commits/node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits/node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-raw-commits/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/git-raw-commits/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/git-raw-commits/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/git-raw-commits/node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/git-raw-commits/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/git-raw-commits/node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/git-raw-commits/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/git-raw-commits/node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/git-raw-commits/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hook-std": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from-esm": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.4.tgz", + "integrity": "sha512-7EyUlPFC0HOlBDpUFGfYstsU7XHxZJKAAMzCT8wZ0hMW7b+hG51LIKTDcsgtz8Pu6YC0HqRVbX+rVUtsGMUKvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": ">=16.20" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/index-to-position": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", + "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/into-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-7.0.0.tgz", + "integrity": "sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/issue-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", + "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": ">=10.13" + } + }, + "node_modules/java-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", + "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", + "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/marked-terminal": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz", + "integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.3.0", + "cli-table3": "^0.6.3", + "node-emoji": "^2.1.3", + "supports-hyperlinks": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "marked": ">=1 <12" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.7.tgz", + "integrity": "sha512-2OfDPL+e03E0LrXaGYOtTFIYhiuzep94NSsuhrNULq+stylcJedcHdzHtz0atMUuGwJfFYs0YL5xeC/Ca2x0eQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.2.tgz", + "integrity": "sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm": { + "version": "10.9.3", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.3.tgz", + "integrity": "sha512-6Eh1u5Q+kIVXeA8e7l2c/HpnFFcwrkt37xDMujD5be1gloWa9p6j3Fsv3mByXXmqJHy+2cElRMML8opNT7xIJQ==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dev": true, + "license": "Artistic-2.0", + "workspaces": [ + "docs", + "smoke-tests", + "mock-globals", + "mock-registry", + "workspaces/*" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^8.0.1", + "@npmcli/config": "^9.0.0", + "@npmcli/fs": "^4.0.0", + "@npmcli/map-workspaces": "^4.0.2", + "@npmcli/package-json": "^6.2.0", + "@npmcli/promise-spawn": "^8.0.2", + "@npmcli/redact": "^3.2.2", + "@npmcli/run-script": "^9.1.0", + "@sigstore/tuf": "^3.1.1", + "abbrev": "^3.0.1", + "archy": "~1.0.0", + "cacache": "^19.0.1", + "chalk": "^5.4.1", + "ci-info": "^4.2.0", + "cli-columns": "^4.0.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.4.5", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^8.1.0", + "ini": "^5.0.0", + "init-package-json": "^7.0.2", + "is-cidr": "^5.1.1", + "json-parse-even-better-errors": "^4.0.0", + "libnpmaccess": "^9.0.0", + "libnpmdiff": "^7.0.1", + "libnpmexec": "^9.0.1", + "libnpmfund": "^6.0.1", + "libnpmhook": "^11.0.0", + "libnpmorg": "^7.0.0", + "libnpmpack": "^8.0.1", + "libnpmpublish": "^10.0.1", + "libnpmsearch": "^8.0.0", + "libnpmteam": "^7.0.0", + "libnpmversion": "^7.0.0", + "make-fetch-happen": "^14.0.3", + "minimatch": "^9.0.5", + "minipass": "^7.1.1", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^11.2.0", + "nopt": "^8.1.0", + "normalize-package-data": "^7.0.0", + "npm-audit-report": "^6.0.0", + "npm-install-checks": "^7.1.1", + "npm-package-arg": "^12.0.2", + "npm-pick-manifest": "^10.0.0", + "npm-profile": "^11.0.1", + "npm-registry-fetch": "^18.0.2", + "npm-user-validate": "^3.0.0", + "p-map": "^7.0.3", + "pacote": "^19.0.1", + "parse-conflict-json": "^4.0.0", + "proc-log": "^5.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^4.1.0", + "semver": "^7.7.2", + "spdx-expression-parse": "^4.0.0", + "ssri": "^12.0.0", + "supports-color": "^9.4.0", + "tar": "^6.2.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^6.0.1", + "which": "^5.0.0", + "write-file-atomic": "^6.0.0" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "8.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^4.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/map-workspaces": "^4.0.1", + "@npmcli/metavuln-calculator": "^8.0.0", + "@npmcli/name-from-folder": "^3.0.0", + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.1", + "@npmcli/query": "^4.0.0", + "@npmcli/redact": "^3.0.0", + "@npmcli/run-script": "^9.0.1", + "bin-links": "^5.0.0", + "cacache": "^19.0.1", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^10.2.2", + "minimatch": "^9.0.4", + "nopt": "^8.0.0", + "npm-install-checks": "^7.1.0", + "npm-package-arg": "^12.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.1", + "pacote": "^19.0.0", + "parse-conflict-json": "^4.0.0", + "proc-log": "^5.0.0", + "proggy": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^4.0.0", + "semver": "^7.3.7", + "ssri": "^12.0.0", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^4.0.1", + "@npmcli/package-json": "^6.0.1", + "ci-info": "^4.0.0", + "ini": "^5.0.0", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "6.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^8.0.0", + "ini": "^5.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^10.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "8.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^19.0.0", + "json-parse-even-better-errors": "^4.0.0", + "pacote": "^20.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { + "version": "20.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "6.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "proc-log": "^5.0.0", + "semver": "^7.5.3", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "3.2.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "9.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "node-gyp": "^11.0.0", + "proc-log": "^5.0.0", + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.4.3", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.4.1", + "tuf-js": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^7.0.0", + "npm-normalize-package-bin": "^4.0.0", + "proc-log": "^5.0.0", + "read-cmd-shim": "^5.0.0", + "write-file-atomic": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "19.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/chownr": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/mkdirp": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/tar": { + "version": "7.4.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/cacache/node_modules/yallist": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.4.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.1.3", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.6", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.4.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.2", + "dev": true, + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.3.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.4.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.2.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.6", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/package-json": "^6.0.0", + "npm-package-arg": "^12.0.0", + "promzard": "^2.0.0", + "read": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^4.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "3.4.3", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^12.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.1", + "@npmcli/installed-package-contents": "^3.0.0", + "binary-extensions": "^2.3.0", + "diff": "^5.1.0", + "minimatch": "^9.0.4", + "npm-package-arg": "^12.0.0", + "pacote": "^19.0.0", + "tar": "^6.2.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "9.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.1", + "@npmcli/run-script": "^9.0.1", + "ci-info": "^4.0.0", + "npm-package-arg": "^12.0.0", + "pacote": "^19.0.0", + "proc-log": "^5.0.0", + "read": "^4.0.0", + "read-package-json-fast": "^4.0.0", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "11.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "8.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^8.0.1", + "@npmcli/run-script": "^9.0.1", + "npm-package-arg": "^12.0.0", + "pacote": "^19.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "10.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^7.0.0", + "npm-package-arg": "^12.0.0", + "npm-registry-fetch": "^18.0.1", + "proc-log": "^5.0.0", + "semver": "^7.3.7", + "sigstore": "^3.0.0", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^18.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.1", + "@npmcli/run-script": "^9.0.1", + "json-parse-even-better-errors": "^4.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.4.3", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "14.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "11.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^8.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "7.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "12.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^7.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "10.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^7.1.0", + "npm-normalize-package-bin": "^4.0.0", + "npm-package-arg": "^12.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "11.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "18.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^3.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^14.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^12.0.0", + "proc-log": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "7.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/package-json-from-dist": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/npm/node_modules/pacote": { + "version": "19.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.11.1", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/proggy": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.7.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.1.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.4.0", + "@sigstore/sign": "^3.1.0", + "@sigstore/tuf": "^3.1.0", + "@sigstore/verify": "^2.1.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.4.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.1.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.4.0", + "make-fetch-happen": "^14.0.2", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { + "version": "2.1.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^3.1.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.4.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "dev": true, + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.21", + "dev": true, + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/sprintf-js": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ssri": { + "version": "12.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minizlib": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tinyglobby": { + "version": "0.2.14", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/npm/node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "dev": true, + "inBundle": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/which": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-each-series": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-4.1.0.tgz", + "integrity": "sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-map": "^7.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", + "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-11.0.0.tgz", + "integrity": "sha512-LOVbvF1Q0SZdjClSefZ0Nz5z8u+tIE7mV5NibzmE9VYmDe9CaBbAVtz1veOSZbofrdsilxuDAYnFenukZVp8/Q==", + "deprecated": "Renamed to read-package-up", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/registry-auth-token": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", + "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/semantic-release": { + "version": "22.0.12", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-22.0.12.tgz", + "integrity": "sha512-0mhiCR/4sZb00RVFJIUlMuiBkW3NMpVIW2Gse7noqEMoFGkvfPPAImEQbkBV8xga4KOPP4FdTRYuLLy32R1fPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/commit-analyzer": "^11.0.0", + "@semantic-release/error": "^4.0.0", + "@semantic-release/github": "^9.0.0", + "@semantic-release/npm": "^11.0.0", + "@semantic-release/release-notes-generator": "^12.0.0", + "aggregate-error": "^5.0.0", + "cosmiconfig": "^8.0.0", + "debug": "^4.0.0", + "env-ci": "^10.0.0", + "execa": "^8.0.0", + "figures": "^6.0.0", + "find-versions": "^5.1.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^7.0.0", + "import-from-esm": "^1.3.1", + "lodash-es": "^4.17.21", + "marked": "^9.0.0", + "marked-terminal": "^6.0.0", + "micromatch": "^4.0.2", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-pkg-up": "^11.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^4.0.0", + "signale": "^1.2.1", + "yargs": "^17.5.1" + }, + "bin": { + "semantic-release": "bin/semantic-release.js" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, + "node_modules/semantic-release/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/semantic-release/node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/semantic-release/node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/semantic-release/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/semantic-release/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/signale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/signale/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/signale/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-error-forwarder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", + "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-combiner2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-combiner2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/stream-combiner2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/traverse": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", + "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c81d31f --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "hatch-validator", + "private": true, + "scripts": { + "commit": "cz", + "semantic-release": "semantic-release" + }, + "devDependencies": { + "@commitlint/cli": "^18.6.1", + "@commitlint/config-conventional": "^18.6.2", + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^9.2.6", + "commitizen": "^4.3.0", + "cz-conventional-changelog": "^3.3.0", + "semantic-release": "^22.0.12" + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } + } +} From 02b37f357826cd476a947c117f16a1c42499f6e9 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Mon, 8 Sep 2025 01:17:43 +0900 Subject: [PATCH 2/3] docs: first pass on whole package docs --- README.md | 21 +- docs/articles/appendices/glossary.md | 231 +++++++++ .../ChainOfResponsibilityPattern.md | 453 +++++++++++++++++ .../devs/architecture/ComponentTypes.md | 323 ++++++++++++ .../devs/architecture/SchemaIntegration.md | 479 ++++++++++++++++++ .../ExtendingChainOfResponsibility.md | 378 ++++++++++++++ docs/articles/users/GettingStarted.md | 169 ++++++ .../users/data_access/PackageService.md | 208 ++++++++ .../users/data_access/RegistryService.md | 299 +++++++++++ .../data_access/VersionAgnosticAccess.md | 226 +++++++++ .../users/integration/ProgrammaticUsage.md | 454 +++++++++++++++++ .../users/validation/PackageValidation.md | 249 +++++++++ .../users/validation/SchemaManagement.md | 302 +++++++++++ .../chain_of_responsibility_overview.puml | 238 +++++++++ .../three_component_architecture.puml | 217 ++++++++ .../diagrams/version_agnostic_access.puml | 210 ++++++++ 16 files changed, 4439 insertions(+), 18 deletions(-) create mode 100644 docs/articles/appendices/glossary.md create mode 100644 docs/articles/devs/architecture/ChainOfResponsibilityPattern.md create mode 100644 docs/articles/devs/architecture/ComponentTypes.md create mode 100644 docs/articles/devs/architecture/SchemaIntegration.md create mode 100644 docs/articles/devs/contribution_guidelines/ExtendingChainOfResponsibility.md create mode 100644 docs/articles/users/GettingStarted.md create mode 100644 docs/articles/users/data_access/PackageService.md create mode 100644 docs/articles/users/data_access/RegistryService.md create mode 100644 docs/articles/users/data_access/VersionAgnosticAccess.md create mode 100644 docs/articles/users/integration/ProgrammaticUsage.md create mode 100644 docs/articles/users/validation/PackageValidation.md create mode 100644 docs/articles/users/validation/SchemaManagement.md create mode 100644 docs/resources/diagrams/chain_of_responsibility_overview.puml create mode 100644 docs/resources/diagrams/three_component_architecture.puml create mode 100644 docs/resources/diagrams/version_agnostic_access.puml diff --git a/README.md b/README.md index cdfbd2c..ddf32c8 100644 --- a/README.md +++ b/README.md @@ -17,25 +17,11 @@ A validation package for Hatch packages and dependencies. pip install git+https://github.com/CrackingShells/Hatch-Validator.git # Or install local copy +git clone https://github.com/CrackingShells/Hatch-Validator.git +cd Hatch-Validator pip install /path/to/Hatch-Validator ``` -### As a Submodule - -If using as a git submodule: - -1. Add as a submodule to your project: - - ```bash - git submodule add https://github.com/CrackingShells/Hatch-Validator.git validator - ``` - -2. Install the submodule as a package: - - ```bash - pip install ./validator - ``` - ## Usage ```python @@ -69,8 +55,7 @@ We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) 3. **Create a feature branch**: `git checkout -b feat/your-feature` 4. **Make changes** and add tests 5. **Use conventional commits**: `npm run commit` for guided commits -6. **Run tests**: `python -c "import hatch_validator; print('Package imports successfully')"` -7. **Create a pull request** +6. **Create a pull request** ### Commit Messages diff --git a/docs/articles/appendices/glossary.md b/docs/articles/appendices/glossary.md new file mode 100644 index 0000000..5ade349 --- /dev/null +++ b/docs/articles/appendices/glossary.md @@ -0,0 +1,231 @@ +# Glossary + +## A + +**Auto-Approval** +A configuration option for dependency installation that automatically approves installation operations without user confirmation. + +## B + +**Background Updates** +The ability to update schemas in background threads without blocking main application operations. + +**Backward Compatibility** +The guarantee that newer components can handle packages and data from older schema versions through delegation. + +**Backward Compatibility Testing** +Testing that newer components can properly handle data from older schema versions. + +## C + +**Cache Corruption Recovery** +The ability of the schema cache system to detect and recover from corrupted cache files by redownloading schemas. + +**Cache Directory** +The local directory where schemas are cached, defaulting to `~/.hatch/schemas/` but configurable through constructor parameters. + +**Cache TTL (Time To Live)** +The duration for which cached schemas are considered fresh before triggering update checks. Default is 24 hours (86400 seconds). + +**Chain Construction** +The process by which factory classes create and link components in the correct order (newest to oldest) to form functional chains. + +**Chain of Responsibility Pattern** +A behavioral design pattern that allows passing requests along a chain of handlers. In Hatch-Validator, this pattern enables extensible functionality by allowing new components to inherit and modify only changed logic from previous versions. + +**Chain Behavior Testing** +Testing the delegation behavior between components to ensure proper flow of requests through the chain. + +**Chain Validation** +The process of verifying that component chains are properly constructed and cover all required functionality. + +**CLI Integration** +The integration of Hatch-Validator functionality into command-line interfaces for package validation and management operations. + +**Component Registration** +The process of registering component classes with factory classes to enable automatic discovery and chain construction. + +**Component Reuse** +The practice of reusing component instances across multiple operations to reduce object creation overhead. + +**CrackingShells Package Registry** +A package registry format supported by Hatch-Validator, featuring repository-based organization with packages containing multiple versions. + +## D + +**Delegation** +The process by which a component in the Chain of Responsibility passes unchanged concerns to the next component in the chain. This enables code reuse and maintains separation of concerns across schema versions. + +**Dependency Types** +Categories of dependencies supported by Hatch packages: hatch (Hatch packages), python (PyPI packages), system (system packages), and docker (Docker images). + +## E + +**Environment Management** +The process of managing isolated package environments, which integrates with Hatch-Validator for package validation and dependency resolution. + +**Extension Mechanisms** +The methods and patterns used to add support for new schema versions without modifying existing component implementations. + +## F + +**Factory Pattern** +A creational design pattern used to create chains of components. HatchPkgAccessorFactory, ValidatorFactory, and RegistryAccessorFactory automatically discover and link components from newest to oldest versions. + +**First-Party Consumer** +Applications and tools that use Hatch-Validator as a library, such as the Dependency Installation Orchestrator, Environment Manager, and CLI tools. + +**Force Update** +A configuration option that bypasses cache freshness checks and forces schema updates from the remote repository. + +## G + +**GitHub API Integration** +The use of GitHub's REST API to discover latest schema versions and download schema files from the Hatch-Schemas repository. + +**Graceful Degradation** +The ability of the validation system to continue operating when certain components fail, typically by falling back to cached data or alternative validation methods. + +## H + +**Hatch Package Manager** +The broader package management system that Hatch-Validator supports, providing package creation, validation, and distribution capabilities. + +**Hatch-Schemas Repository** +An external GitHub repository (CrackingShells/Hatch-Schemas) that provides versioned schema definitions for package metadata and registry data. + +**HatchPkgAccessorFactory** +A factory class that creates package accessor chains by automatically discovering and linking package accessors from newest to oldest versions. + +## I + +**Integration Testing** +Testing complete component chains to verify proper delegation flow and end-to-end functionality. + +## J + +**JSON Schema Validation** +The use of JSON Schema specifications to validate package metadata structure and content against schema definitions. + +## L + +**Lazy Loading** +The practice of loading schemas and creating component chains only when needed, improving application startup time and memory usage. + +## M + +**MCP (Model Context Protocol)** +A protocol supported by Hatch packages for AI model integration, with entry point configurations handled by the validation system. + +**Metadata Structure** +The organization of data within package metadata files, which varies across schema versions (e.g., separate vs. unified dependencies). + +## N + +**Network Resilience** +The ability of the schema management system to handle network failures gracefully by falling back to cached schemas. + +## P + +**Package Accessors** +Components that provide unified access to package metadata across schema versions, abstracting differences in metadata structure and field organization. + +**PackageService** +A high-level service class that provides version-agnostic access to package metadata using package accessor chains. + +**Programmatic Usage** +The use of Hatch-Validator through its API rather than command-line interfaces, enabling integration into larger applications and workflows. + +## R + +**Real-World Usage Patterns** +Common integration patterns derived from actual production implementations, demonstrating practical benefits of version-agnostic data access. + +**Registry Accessors** +Components that enable consistent registry data access regardless of registry schema version, providing unified interfaces for package discovery and version resolution. + +**Registry Schema** +The schema defining the structure of registry data, currently at version v1.1.0 with support for the CrackingShells Package Registry format. + +**RegistryAccessorFactory** +A factory class that creates registry accessor chains by automatically discovering and linking registry accessors based on registry data format. + +**RegistryService** +A high-level service class that provides version-agnostic access to registry data using registry accessor chains. + +## S + +**Schema Evolution** +The process of updating schema definitions to support new features while maintaining backward compatibility. Handled through the Chain of Responsibility pattern. + +**SchemaCache** +A class that manages local schema storage and retrieval, providing offline operation capabilities and cache freshness validation. + +**SchemaFetcher** +A class that handles network operations to retrieve schema definitions from the Hatch-Schemas GitHub repository. + +**SchemaRetriever** +The main interface for schema operations, coordinating between SchemaFetcher and SchemaCache to provide automatic schema management. + +**Schema Version** +A version identifier that specifies the structure and format of package metadata or registry data. Examples include v1.1.0, v1.2.0, and v1.2.1. + +**Service Layer** +High-level interfaces (PackageService, RegistryService, HatchPackageValidator) that abstract the complexity of the Chain of Responsibility pattern from consumers. + +**Simulation Mode** +A configuration mode that prevents network operations and relies entirely on cached or local data for testing purposes. + +**Strategy Pattern** +A behavioral design pattern used within validators to encapsulate validation algorithms. Examples include EntryPointValidation, DependencyValidation, and ToolsValidation strategies. + +## T + +**Terminal Component** +The oldest version component in a chain that implements complete functionality without delegation. In Hatch-Validator, v1.1.0 components serve as terminal components. + +## U + +**Unit Testing** +Testing individual components in isolation to verify their specific functionality and delegation behavior. + +## V + +**v1.1.0 Schema** +The initial package schema version featuring separate dependency structures (hatch_dependencies and python_dependencies) and basic entry point configuration. + +**v1.2.0 Schema** +An updated package schema version introducing unified dependency structure with support for multiple dependency types (hatch, python, system, docker). + +**v1.2.1 Schema** +The latest package schema version adding dual entry point support (mcp_server and hatch_mcp_server) while maintaining the unified dependency structure from v1.2.0. + +**Validation Chain** +A sequence of validators linked together using the Chain of Responsibility pattern, ordered from newest to oldest schema version. + +**Validation Error Aggregation** +The process of collecting and organizing validation errors from multiple validation strategies into comprehensive error reports. + +**Validation Strategy** +A specific validation algorithm encapsulated within a strategy class. Examples include schema validation, entry point validation, and dependency validation. + +**ValidationContext** +A data structure that carries state and configuration information across validator chains, including registry data and validation settings. + +**Validators** +Components that handle validation logic for different schema versions. They implement comprehensive package validation while delegating unchanged validation concerns to previous validators in the chain. + +**ValidatorFactory** +A factory class that creates validator chains by automatically discovering and linking validators from newest to oldest versions. + +**Version Ordering** +The practice of organizing schema versions from newest to oldest in factory classes to ensure proper chain construction. + +**Version-Agnostic Access** +The ability to access package or registry data without needing to know the specific schema version. Achieved through the Chain of Responsibility pattern and service layer abstraction. + +**Environment Management** +The process of managing isolated package environments, which integrates with Hatch-Validator for package validation and dependency resolution. + +**CLI Integration** +The integration of Hatch-Validator functionality into command-line interfaces for package validation and management operations. diff --git a/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md b/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md new file mode 100644 index 0000000..493317b --- /dev/null +++ b/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md @@ -0,0 +1,453 @@ +# Chain of Responsibility Pattern + +This article is about: + +- Chain of Responsibility pattern overview and principles in Hatch-Validator +- Strategy Pattern integration within validators for validation algorithm encapsulation +- Universal implementation pattern across validators, package accessors, and registry accessors +- Delegation mechanisms and chain construction across all component types +- Dual pattern architecture: when to use delegation vs. strategy composition +- Benefits for extensibility and maintainability in schema evolution + +## Pattern Overview + +The Chain of Responsibility pattern is the central architectural feature of Hatch-Validator, implemented consistently across three major component types. This pattern enables extensible functionality by allowing new components to inherit and modify only the changed logic from previous versions, creating a maintainable and scalable system. + +### Core Principles + +**Delegation Over Inheritance**: Components delegate unchanged concerns to previous versions rather than using traditional class inheritance. + +**Version-Specific Specialization**: Each component version implements only the logic that has changed from previous versions. + +**Automatic Chain Construction**: Factory classes automatically discover and link components from newest to oldest versions. + +**Unified Interface**: All components in a chain provide the same interface to consumers, abstracting version differences. + +## Dual Pattern Architecture + +Validators implement a sophisticated dual-pattern architecture that combines Chain of Responsibility with Strategy Pattern to handle both version delegation and validation algorithm encapsulation. + +### Pattern Integration + +**Chain of Responsibility**: Handles version-specific delegation between validators for unchanged validation concerns. + +**Strategy Pattern**: Encapsulates validation algorithms within each validator for changed validation concerns. + +**Decision Matrix**: Each validation concern (schema, dependencies, entry points, tools) uses either strategy composition or chain delegation based on whether the validation logic has changed in the current version. + +### When Validators Use Strategy Pattern + +Validators compose strategies for validation concerns that have changed in their version: + +- **New validation requirements**: Schema version introduces new validation logic +- **Algorithm changes**: Validation algorithm changes significantly from previous version +- **Version-specific logic**: New validation requirements specific to the current version + +### When Validators Use Chain of Responsibility + +Validators delegate to the chain for validation concerns that remain unchanged: + +- **Unchanged logic**: Validation logic identical to previous version +- **No new requirements**: No new validation requirements introduced +- **Previous implementation sufficient**: Previous version's strategy meets current needs + +## Universal Implementation Pattern + +### Three Component Types + +The Chain of Responsibility pattern is implemented identically across three component types: + +**1. Validators** (`hatch_validator/core/validator_base.py`) + +- Handle validation logic for different schema versions +- Delegate unchanged validation concerns to previous validators + +**2. Package Accessors** (`hatch_validator/core/pkg_accessor_base.py`) + +- Provide unified access to package metadata across schema versions +- Delegate unchanged metadata access to previous accessors + +**3. Registry Accessors** (`hatch_validator/registry/registry_accessor_base.py`) + +- Enable consistent registry data access regardless of registry schema version +- Delegate unchanged registry operations to previous accessors + +### Abstract Base Classes + +All component types follow the same abstract base class pattern: + +```python +# Universal pattern implemented by all three component types +class ComponentBase(ABC): + def __init__(self, next_component: Optional['ComponentBase'] = None): + self.next_component = next_component + + @abstractmethod + def can_handle(self, version_or_data) -> bool: + """Determine if this component can handle the given version/data.""" + pass + + def set_next(self, component: 'ComponentBase') -> 'ComponentBase': + """Set the next component in the chain.""" + self.next_component = component + return component + + # Delegation methods follow the same pattern: + def operation(self, data): + """Perform operation or delegate to next component.""" + if self.next_component: + return self.next_component.operation(data) + raise NotImplementedError("Operation not implemented for this version") +``` + +### Factory Pattern Integration + +All component types use identical factory patterns for chain construction: + +```python +# Universal factory pattern used by all three component types +class ComponentFactory: + _component_registry: Dict[str, Type[ComponentBase]] = {} + _version_order: List[str] = [] # Newest to oldest + + @classmethod + def create_component_chain(cls, target_version: Optional[str] = None) -> ComponentBase: + """Create component chain from target version to oldest.""" + + # Determine target version (latest if not specified) + if target_version is None: + target_version = cls._version_order[0] + + # Create chain starting from target version down to oldest + target_index = cls._version_order.index(target_version) + chain_versions = cls._version_order[target_index:] + + # Create components in order (newest to oldest) + components = [] + for version in chain_versions: + component_class = cls._component_registry[version] + component = component_class() + components.append(component) + + # Link components (each points to the next older one) + for i in range(len(components) - 1): + components[i].set_next(components[i + 1]) + + return components[0] # Return head of chain +``` + +## Delegation Mechanisms + +### Version-Specific Delegation + +Each component type implements delegation for unchanged concerns: + +**Package Accessors Example:** + +```python +class V121PackageAccessor(HatchPkgAccessorBase): + """v1.2.1 accessor - handles dual entry points, delegates dependencies.""" + + def get_entry_points(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Handle dual entry point access for v1.2.1.""" + # v1.2.1-specific logic for dual entry points + return { + 'mcp_server': metadata.get('mcp_server', {}), + 'hatch_mcp_server': metadata.get('hatch_mcp_server', {}) + } + + def get_dependencies(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Delegate dependency access to v1.2.0.""" + if self.next_accessor: + return self.next_accessor.get_dependencies(metadata) + raise NotImplementedError("Dependencies accessor not implemented") + +class V120PackageAccessor(HatchPkgAccessorBase): + """v1.2.0 accessor - handles unified dependencies, delegates basic fields.""" + + def get_dependencies(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Handle unified dependency structure for v1.2.0.""" + # v1.2.0-specific logic for unified dependencies + return metadata.get('dependencies', {}) + + def get_name(self, metadata: Dict[str, Any]) -> str: + """Delegate basic field access to v1.1.0.""" + if self.next_accessor: + return self.next_accessor.get_name(metadata) + raise NotImplementedError("Name accessor not implemented") +``` + +### Delegation Flow + +For a v1.2.1 package requesting dependencies: + +1. **v1.2.1 Accessor**: Recognizes it doesn't handle dependencies → delegates to v1.2.0 +2. **v1.2.0 Accessor**: Handles unified dependency structure → returns result +3. **Consumer**: Receives unified dependency data + +For a v1.2.1 package requesting entry points: + +1. **v1.2.1 Accessor**: Handles dual entry point logic → returns result directly +2. **Consumer**: Receives dual entry point data + +### Terminal Components + +The oldest version in each chain serves as the terminal component: + +**v1.1.0 Components**: Implement all basic functionality without delegation + +- **Package Accessor**: Handles all basic metadata fields and separate dependencies +- **Validator**: Implements all basic validation strategies +- **Registry Accessor**: Handles basic registry operations + +## Chain Construction Process + +### Automatic Discovery + +Factory classes automatically discover available components: + +```python +class ValidatorFactory: + @classmethod + def _ensure_validators_loaded(cls) -> None: + """Automatically discover and register validators.""" + if not cls._validator_registry: + # Import and register v1.2.1 validator (newest first) + from hatch_validator.package.v1_2_1.validator import Validator as V121Validator + cls.register_validator('1.2.1', V121Validator) + + # Import and register v1.2.0 validator + from hatch_validator.package.v1_2_0.validator import Validator as V120Validator + cls.register_validator('1.2.0', V120Validator) + + # Import and register v1.1.0 validator + from hatch_validator.package.v1_1_0.validator import Validator as V110Validator + cls.register_validator('1.1.0', V110Validator) +``` + +### Version Ordering + +Components are ordered from newest to oldest: + +```python +# Version order maintained across all component types +_version_order = ['1.2.1', '1.2.0', '1.1.0'] # Newest to oldest +``` + +### Chain Linking + +Components are linked in a specific order: + +1. **Create Components**: Instantiate all components in the chain +2. **Link Forward**: Each component points to the next older version +3. **Return Head**: Return the newest component as the chain head + +```python +# Example chain for v1.2.1 target: +# v1.2.1 → v1.2.0 → v1.1.0 +components[0].set_next(components[1]) # v1.2.1 → v1.2.0 +components[1].set_next(components[2]) # v1.2.0 → v1.1.0 +# v1.1.0 has no next (terminal) +``` + +## Strategy Pattern Integration + +Validators implement the Strategy Pattern alongside Chain of Responsibility to encapsulate validation algorithms. This dual-pattern architecture provides fine-grained control over which validation concerns use strategy composition versus chain delegation. + +### Strategy Interface Hierarchy + +Located in `hatch_validator/core/validation_strategy.py`: + +```python +class ValidationStrategy(ABC): + """Base interface for all validation strategies.""" + pass + +class DependencyValidationStrategy(ValidationStrategy): + @abstractmethod + def validate_dependencies(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + pass + +class ToolsValidationStrategy(ValidationStrategy): + @abstractmethod + def validate_tools(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + pass + +class EntryPointValidationStrategy(ValidationStrategy): + @abstractmethod + def validate_entry_point(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + pass + +class SchemaValidationStrategy(ValidationStrategy): + @abstractmethod + def validate_schema(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + pass +``` + +### Validator Strategy Composition + +Each validator composes only the strategies for validation concerns that have changed in their version: + +```python +class Validator(ValidatorBase): + def __init__(self, next_validator=None): + super().__init__(next_validator) + # Compose strategies for changed concerns only + self.schema_strategy = SchemaValidation() + self.entry_point_strategy = EntryPointValidation() + self.tools_strategy = ToolsValidation() + # No dependency_strategy - delegates to v1.2.0 +``` + +### Strategy vs. Chain Decision Matrix + +**Strategy Composition Used When**: + +- Schema version introduces new validation logic +- Validation algorithm changes significantly +- New validation requirements specific to version + +**Chain Delegation Used When**: + +- Validation logic unchanged from previous version +- No new validation requirements +- Previous version's strategy sufficient + +### Version-Specific Strategy Implementation + +**v1.2.1 Validator**: + +- **Strategies**: `SchemaValidation`, `EntryPointValidation`, `ToolsValidation` +- **Delegation**: Dependencies → v1.2.0 +- **Specialization**: Dual entry point validation, FastMCP server enforcement + +**v1.2.0 Validator**: + +- **Strategies**: `SchemaValidation`, `DependencyValidation` +- **Delegation**: Entry points, tools → v1.1.0 +- **Specialization**: Unified dependency structure validation + +**v1.1.0 Validator**: + +- **Strategies**: All strategies (`SchemaValidation`, `DependencyValidation`, `EntryPointValidation`, `ToolsValidation`) +- **Delegation**: None (terminal validator) +- **Specialization**: Complete validation implementation + +## Benefits for Extensibility + +### Adding New Schema Versions + +To add support for a new schema version (e.g., v1.3.0): + +1. **Create Version Directory**: `hatch_validator/package/v1_3_0/` +2. **Implement Components**: Create accessor.py and validator.py +3. **Override Changed Logic**: Implement only methods that handle new features +4. **Delegate Unchanged Logic**: Use delegation for unchanged concerns +5. **Auto-Registration**: Factory automatically discovers new components + +**Example v1.3.0 Accessor:** + +```python +class V130PackageAccessor(HatchPkgAccessorBase): + """v1.3.0 accessor - handles new features, delegates unchanged concerns.""" + + def can_handle(self, schema_version: str) -> bool: + return schema_version == "1.3.0" + + def get_new_feature(self, metadata: Dict[str, Any]) -> Any: + """Handle v1.3.0-specific new feature.""" + return metadata.get('new_feature', {}) + + # All others are automatically delegated from HatchPkgAccessorBase implementation +``` + +### Incremental Development + +New versions require minimal code changes: + +- **Focused Implementation**: Only implement changed functionality +- **Reuse Existing Logic**: Delegate unchanged concerns to previous versions +- **Isolated Testing**: Test only new functionality, existing logic is preserved +- **Gradual Migration**: Packages can migrate to new versions incrementally + +## Benefits for Maintainability + +### Code Reuse + +The pattern maximizes code reuse across versions: + +- **Delegation**: Unchanged logic is reused through delegation +- **No Duplication**: Avoid copying code between versions +- **Single Source of Truth**: Each piece of logic exists in one place + +### Isolated Changes + +Changes are isolated to specific versions: + +- **Version Boundaries**: Changes are contained within version-specific modules +- **Minimal Impact**: New versions don't affect existing version logic +- **Safe Evolution**: Schema evolution doesn't break existing functionality + +### Testability + +The pattern improves testability: + +- **Component Isolation**: Each component can be tested independently +- **Chain Testing**: Entire chains can be tested for delegation behavior +- **Version-Specific Testing**: Test only the logic specific to each version + +## Error Handling in Chains + +### Graceful Degradation + +Chains handle errors gracefully: + +```python +def operation(self, data): + """Operation with graceful error handling.""" + try: + # Try to handle with this component + if self.can_handle(data): + return self._handle_operation(data) + except Exception as e: + logger.warning(f"Component {self.__class__.__name__} failed: {e}") + + # Delegate to next component + if self.next_component: + return self.next_component.operation(data) + + # No component could handle the operation + raise NotImplementedError(f"No component can handle operation for {data}") +``` + +### Chain Validation + +Factories validate chain integrity: + +- **Complete Coverage**: Ensure all supported versions have components +- **Proper Linking**: Verify components are linked correctly +- **Terminal Validation**: Confirm terminal components implement all operations + +## Performance Considerations + +### Lazy Loading + +Components are created only when needed: + +- **Factory Caching**: Factories cache created chains +- **On-Demand Creation**: Chains created only when requested +- **Component Reuse**: Same component instances used across operations + +### Delegation Efficiency + +Delegation is optimized for common cases: + +- **Early Termination**: Delegation stops at first capable component +- **Version Ordering**: Most common versions are checked first +- **Minimal Overhead**: Delegation adds minimal performance cost + +## Related Documentation + +- [Component Types](ComponentTypes.md) - How different component types work together +- [Schema Integration](SchemaIntegration.md) - Integration with schema management +- [Extending Chain of Responsibility](../contribution_guidelines/ExtendingChainOfResponsibility.md) - Adding new components diff --git a/docs/articles/devs/architecture/ComponentTypes.md b/docs/articles/devs/architecture/ComponentTypes.md new file mode 100644 index 0000000..894b4d7 --- /dev/null +++ b/docs/articles/devs/architecture/ComponentTypes.md @@ -0,0 +1,323 @@ +# Component Types + +This article is about: + +- Validators: Extensible validation with version-specific delegation +- Package Accessors: Version-agnostic metadata access capabilities +- Registry Accessors: Version-agnostic registry data access functionality +- How all three component types work together in the unified architecture + +## Overview + +Hatch-Validator implements the Chain of Responsibility pattern across three distinct component types, each serving a specific purpose in the validation and data access ecosystem. These components work together to provide comprehensive, version-agnostic functionality for package management and validation. + +## Validators + +### Purpose and Scope + +Validators handle validation logic for different schema versions, implementing comprehensive package validation while delegating unchanged validation concerns to previous validators in the chain. + +**Location**: `hatch_validator/core/validator_base.py` and version-specific implementations + +**Key Responsibilities:** + +- Schema-specific validation logic +- Entry point validation +- Tools configuration validation +- Dependency structure validation +- Metadata schema validation + +### Purpose and Scope +Validators implement a dual-pattern architecture combining Chain of Responsibility for version delegation with Strategy Pattern for validation algorithm encapsulation. + +### Dual Pattern Implementation + +**Strategy Composition**: Each validator composes strategies for validation concerns that have changed in their version + +**Chain Delegation**: Validators delegate unchanged validation concerns to previous validators + +### Version-Specific Strategy Implementation + +**v1.2.1 Validator**: + +- **Strategies**: SchemaValidation, EntryPointValidation, ToolsValidation +- **Delegation**: Dependencies → v1.2.0 +- **Specialization**: Dual entry point validation (mcp_server + hatch_mcp_server) + +**v1.2.0 Validator**: + +- **Strategies**: SchemaValidation, DependencyValidation +- **Delegation**: Entry points, tools → v1.1.0 +- **Specialization**: Unified dependency structure validation + +**v1.1.0 Validator**: + +- **Strategies**: All strategies (SchemaValidation, DependencyValidation, EntryPointValidation, ToolsValidation) +- **Delegation**: None (terminal validator) +- **Specialization**: Complete validation implementation + +For detailed information on the dual pattern architecture, see [Chain of Responsibility Pattern](../architecture/ChainOfResponsibilityPattern.md#dual-pattern-architecture). + +## Package Accessors + +### Purpose and Scope + +Package Accessors provide unified access to package metadata across schema versions, abstracting differences in metadata structure and field organization. + +**Location**: `hatch_validator/core/pkg_accessor_base.py` and version-specific implementations + +**Key Responsibilities:** + +- Version-agnostic metadata field access +- Dependency structure normalization +- Entry point configuration access +- Tools configuration access +- Local dependency detection + +### Package Accessor Architecture + +**Base Class**: `HatchPkgAccessor` (abstract base class) + +```python +class HatchPkgAccessor(ABC): + def __init__(self, next_accessor: Optional['HatchPkgAccessor'] = None): + self.next_accessor = next_accessor + + @abstractmethod + def can_handle(self, schema_version: str) -> bool: + """Determine if this accessor can handle the schema version.""" + pass + + def get_dependencies(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Get dependencies or delegate to next accessor.""" + if self.next_accessor: + return self.next_accessor.get_dependencies(metadata) + raise NotImplementedError("Dependencies accessor not implemented") + + # And so on for all other metadata access methods +``` + +### Version-Specific Implementations + +**v1.2.1 Accessor** (`hatch_validator/package/v1_2_1/accessor.py`): + +- **Specialization**: Dual entry point metadata access +- **Delegation**: Delegates dependency access to v1.2.0 +- **Entry Points**: Handles both mcp_server and hatch_mcp_server configurations + +**v1.2.0 Accessor** (`hatch_validator/package/v1_2_0/accessor.py`): + +- **Specialization**: Unified dependency structure access +- **Delegation**: Delegates basic field access to v1.1.0 +- **Dependencies**: Handles unified dependencies with hatch, python, system, docker types + +**v1.1.0 Accessor** (`hatch_validator/package/v1_1_0/accessor.py`): + +- **Specialization**: Terminal accessor implementing all basic metadata access +- **Dependencies**: Handles separate hatch_dependencies and python_dependencies +- **Coverage**: All basic metadata fields (name, version, description, etc.) + +For delegation mechanisms, see [Chain of Responsibility Pattern](../architecture/ChainOfResponsibilityPattern.md#delegation-mechanisms). + +## Registry Accessors + +### Purpose and Scope + +Registry Accessors enable consistent registry data access regardless of registry schema version, providing unified interfaces for package discovery and version resolution. + +**Location**: `hatch_validator/registry/registry_accessor_base.py` and version-specific implementations + +**Key Responsibilities:** + +- Version-agnostic registry data access +- Package existence validation +- Version compatibility checking +- Package URI resolution +- Repository management operations + +### Registry Accessor Architecture + +**Base Class**: `RegistryAccessorBase` (abstract base class) + +```python +class RegistryAccessorBase(ABC): + def __init__(self, successor: Optional['RegistryAccessorBase'] = None): + self._successor = successor + + @abstractmethod + def can_handle(self, registry_data: Dict[str, Any]) -> bool: + """Check if this accessor can handle the registry data.""" + pass + + def handle_request(self, registry_data: Dict[str, Any]) -> Optional['RegistryAccessorBase']: + """Handle request using chain of responsibility pattern.""" + if self.can_handle(registry_data): + return self + elif self._successor: + return self._successor.handle_request(registry_data) + return None +``` + +### Version-Specific Implementations + +**v1.1.0 Registry Accessor** (`hatch_validator/registry/v1_1_0/registry_accessor.py`): + +- **Specialization**: CrackingShells Package Registry format +- **Coverage**: Repository-based structure with packages containing versions +- **Operations**: Package existence, version resolution, URI generation +- **Terminal**: Currently serves as terminal accessor for registry operations + +Registry accessors use the same delegation pattern described in [delegation mechanisms](../architecture/ChainOfResponsibilityPattern.md#delegation-mechanisms). + +## Component Integration + +### Service Layer Integration + +The three component types integrate through high-level service classes: + +**PackageService Integration:** + +```python +class PackageService: + def __init__(self, metadata: Optional[Dict[str, Any]] = None): + self._accessor: Optional[HatchPkgAccessor] = None + if metadata: + # Create package accessor chain + schema_version = metadata.get("package_schema_version") + self._accessor = HatchPkgAccessorFactory.create_accessor_chain(schema_version) + + def get_dependencies(self) -> Dict[str, Any]: + """Use accessor chain for version-agnostic dependency access.""" + return self._accessor.get_dependencies(self._metadata) +``` + +**RegistryService Integration:** + +```python +class RegistryService: + def __init__(self, registry_data: Optional[Dict[str, Any]] = None): + self._accessor: Optional[RegistryAccessorBase] = None + if registry_data: + # Create registry accessor chain + self._accessor = RegistryAccessorFactory.create_accessor_for_data(registry_data) + + def package_exists(self, package_name: str) -> bool: + """Use accessor chain for version-agnostic registry operations.""" + return self._accessor.package_exists(self._registry_data, package_name) +``` + +**HatchPackageValidator Integration:** + +```python +class HatchPackageValidator: + def validate_package(self, package_path: Path) -> Tuple[bool, Dict[str, Any]]: + """Use validator chain for version-agnostic validation.""" + + # Load metadata and detect schema version + with open(package_path / "hatch_metadata.json", 'r') as f: + metadata = json.load(f) + + schema_version = metadata.get("package_schema_version") + + # Create validator chain + validator = ValidatorFactory.create_validator_chain(schema_version) + + # Execute validation through chain + context = ValidationContext(registry_data=self.registry_data) + is_valid, errors = validator.validate(metadata, context) + + return is_valid, self._format_results(is_valid, errors, metadata) +``` + +### Cross-Component Coordination + +Components coordinate to provide comprehensive functionality: + +**Validation with Data Access:** + +```python +# Validator uses package accessor for dependency validation +class DependencyValidation: + def validate(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + # Use package accessor for version-agnostic dependency access + package_service = PackageService(metadata) + dependencies = package_service.get_dependencies() + + # Use registry accessor for dependency existence validation + registry_service = RegistryService(context.registry_data) + + errors = [] + for dep_type, deps in dependencies.items(): + for dep in deps: + if not registry_service.package_exists(dep['name']): + errors.append(f"Dependency {dep['name']} not found in registry") + + return len(errors) == 0, errors +``` + +### Factory Coordination + +Factory classes coordinate component creation: + +```python +# Coordinated factory usage +def create_validation_system(metadata: Dict[str, Any], registry_data: Dict[str, Any]): + """Create coordinated validation system with all component types.""" + + schema_version = metadata.get("package_schema_version") + + # Create coordinated chains + validator = ValidatorFactory.create_validator_chain(schema_version) + package_accessor = HatchPkgAccessorFactory.create_accessor_chain(schema_version) + registry_accessor = RegistryAccessorFactory.create_accessor_for_data(registry_data) + + # Create coordinated services + package_service = PackageService(metadata) + registry_service = RegistryService(registry_data) + + return { + 'validator': validator, + 'package_service': package_service, + 'registry_service': registry_service + } +``` + +## Benefits of Component Type Separation + +### Clear Separation of Concerns + +Each component type has a distinct responsibility: + +- **Validators**: Validation logic and error detection +- **Package Accessors**: Metadata structure abstraction +- **Registry Accessors**: Registry format abstraction + +### Independent Evolution + +Component types can evolve independently: + +- **Validation Changes**: New validation rules don't affect data access +- **Metadata Changes**: Schema evolution doesn't affect validation logic +- **Registry Changes**: Registry format changes don't affect package validation + +### Testability + +Component types can be tested independently: + +- **Unit Testing**: Each component type tested in isolation +- **Integration Testing**: Component coordination tested separately +- **Chain Testing**: Delegation behavior tested per component type + +### Extensibility + +New functionality can be added to specific component types: + +- **New Validators**: Add validation for new schema features +- **New Accessors**: Add support for new metadata structures +- **New Registry Support**: Add support for new registry formats + +## Related Documentation + +- [Chain of Responsibility Pattern](ChainOfResponsibilityPattern.md) - Universal pattern implementation +- [Schema Integration](SchemaIntegration.md) - Integration with schema management +- [Extending Chain of Responsibility](../contribution_guidelines/ExtendingChainOfResponsibility.md) - Adding new components diff --git a/docs/articles/devs/architecture/SchemaIntegration.md b/docs/articles/devs/architecture/SchemaIntegration.md new file mode 100644 index 0000000..bb7d8b7 --- /dev/null +++ b/docs/articles/devs/architecture/SchemaIntegration.md @@ -0,0 +1,479 @@ +# Schema Integration + +This article is about: +- Integration with Hatch-Schemas repository for schema management +- Schema fetching, caching, and version resolution mechanisms +- How schema evolution is handled across all component types +- Version detection and automatic chain selection processes + +## Overview + +Hatch-Validator integrates with the external Hatch-Schemas repository to provide automatic schema management, version detection, and chain selection. This integration ensures that validators always have access to the latest schema definitions while maintaining backward compatibility and offline operation capabilities. + +## Hatch-Schemas Repository Integration + +### Repository Structure + +The Hatch-Schemas repository provides versioned schema definitions: + +**GitHub Repository**: `CrackingShells/Hatch-Schemas` + +**Schema Types:** +- **Package Schemas**: `hatch_pkg_metadata_schema.json` - Define package metadata structure +- **Registry Schemas**: `hatch_all_pkg_metadata_schema.json` - Define registry data structure + +**Release Tagging:** +- **Package Schema Releases**: Tagged with `schemas-package-` prefix (e.g., `schemas-package-v1.2.1`) +- **Registry Schema Releases**: Tagged with `schemas-registry-` prefix (e.g., `schemas-registry-v1.1.0`) + +### API Integration + +The schema management system integrates with GitHub APIs: + +**GitHub Releases API:** +``` +https://api.github.com/repos/CrackingShells/Hatch-Schemas/releases +``` + +**Schema Download URLs:** +``` +https://github.com/CrackingShells/Hatch-Schemas/releases/download/{tag}/{filename} +``` + +**Example Integration:** +```python +from hatch_validator.schemas.schema_fetcher import SchemaFetcher + +fetcher = SchemaFetcher() + +# Discover latest schema versions +schema_info = fetcher.get_latest_schema_info() +# Returns: +# { +# "latest_package_version": "v1.2.1", +# "latest_registry_version": "v1.1.0", +# "package": { +# "version": "v1.2.1", +# "url": "https://github.com/.../schemas-package-v1.2.1/hatch_pkg_metadata_schema.json" +# } +# } + +# Download specific schema +schema_data = fetcher.download_schema(schema_info['package']['url']) +``` + +## Schema Fetching and Caching + +### SchemaFetcher Integration + +The SchemaFetcher class handles network operations with the Hatch-Schemas repository: + +**Key Methods:** +- `get_latest_schema_info()`: Discovers latest schema versions via GitHub API +- `download_schema(url)`: Downloads schema JSON files from GitHub releases + +**Network Resilience:** +```python +def download_schema(self, url: str) -> Optional[Dict[str, Any]]: + """Download schema with error handling.""" + try: + response = requests.get(url, timeout=30) + response.raise_for_status() + return response.json() + except (requests.RequestException, json.JSONDecodeError) as e: + logger.error(f"Error downloading schema: {e}") + return None # Graceful degradation to cached schemas +``` + +### SchemaCache Integration + +The SchemaCache class manages local schema storage: + +**Cache Structure:** +``` +~/.hatch/schemas/ +├── schema_info.json # Cache metadata +├── hatch_pkg_metadata_schema.json # Latest package schema +├── hatch_all_pkg_metadata_schema.json # Latest registry schema +└── v1.2.1/ # Version-specific storage + ├── hatch_pkg_metadata_schema.json + └── hatch_all_pkg_metadata_schema.json +``` + +**Cache Management:** +```python +from hatch_validator.schemas.schema_cache import SchemaCache + +cache = SchemaCache() + +# Check cache freshness (default: 24 hours) +if not cache.is_fresh(): + # Cache is stale, trigger update + schema_retriever.update_schemas() + +# Load cached schema +schema = cache.load_schema("package", "v1.2.1") +``` + +### SchemaRetriever Coordination + +The SchemaRetriever class coordinates fetching and caching: + +```python +from hatch_validator.schemas.schemas_retriever import SchemaRetriever + +retriever = SchemaRetriever() + +# Get schema with automatic cache management +schema = retriever.get_schema("package", "latest", force_update=False) + +# Process: +# 1. Check cache freshness +# 2. If stale, fetch latest schema info from GitHub +# 3. Download new schemas if available +# 4. Update cache with new schemas +# 5. Return requested schema +``` + +## Schema Evolution Handling + +### Version Detection + +The system automatically detects schema versions from metadata: + +```python +def detect_schema_version(metadata: Dict[str, Any]) -> str: + """Detect schema version from package metadata.""" + schema_version = metadata.get("package_schema_version") + + if not schema_version: + # Fallback to default version for legacy packages + return "1.1.0" + + # Normalize version format (remove 'v' prefix if present) + return schema_version.lstrip('v') +``` + +### Automatic Chain Selection + +Schema version detection drives automatic chain selection: + +```python +class ValidatorFactory: + @classmethod + def create_validator_chain(cls, target_version: Optional[str] = None) -> Validator: + """Create validator chain based on detected schema version.""" + + if target_version is None: + # Use latest available version + target_version = cls._version_order[0] + + # Normalize version format + target_version = target_version.lstrip('v') + + # Create chain from target version to oldest + target_index = cls._version_order.index(target_version) + chain_versions = cls._version_order[target_index:] + + # Build and link chain + validators = [cls._validator_registry[v]() for v in chain_versions] + for i in range(len(validators) - 1): + validators[i].set_next(validators[i + 1]) + + return validators[0] +``` + +### Schema Compatibility + +The system handles schema compatibility across versions: + +**Forward Compatibility:** +- Newer validators can handle older schema versions through delegation +- Chain construction ensures appropriate validator is selected + +**Backward Compatibility:** +- Older schema versions continue to work with newer validator implementations +- Terminal validators (v1.1.0) provide complete baseline functionality + +**Example Compatibility Matrix:** +``` +Schema Version | Validator Chain +v1.1.0 | v1.1.0 (terminal) +v1.2.0 | v1.2.0 → v1.1.0 +v1.2.1 | v1.2.1 → v1.2.0 → v1.1.0 +``` + +## Integration with Component Types + +### Validator Integration + +Validators use schema information for validation: + +```python +class SchemaValidation: + def validate(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + """Validate metadata against appropriate schema.""" + + schema_version = metadata.get("package_schema_version", "1.1.0") + + # Get appropriate schema from cache/repository + schema = get_package_schema(schema_version) + if not schema: + return False, [f"Schema not available for version {schema_version}"] + + # Validate metadata against schema + try: + jsonschema.validate(metadata, schema) + return True, [] + except jsonschema.ValidationError as e: + return False, [f"Schema validation error: {e.message}"] +``` + +### Package Accessor Integration + +Package accessors adapt to schema structure changes: + +```python +class V120PackageAccessor(HatchPkgAccessorBase): + def get_dependencies(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Access dependencies based on v1.2.0 schema structure.""" + + # v1.2.0 introduced unified dependencies structure + dependencies = metadata.get('dependencies', {}) + + # Validate structure matches expected schema + expected_types = ['hatch', 'python', 'system', 'docker'] + for dep_type in dependencies: + if dep_type not in expected_types: + logger.warning(f"Unexpected dependency type: {dep_type}") + + return dependencies +``` + +### Registry Accessor Integration + +Registry accessors handle registry schema evolution: + +```python +class V110RegistryAccessor(RegistryAccessorBase): + def can_handle(self, registry_data: Dict[str, Any]) -> bool: + """Check if this accessor can handle the registry schema.""" + + # Check for v1.1.0 registry schema indicators + schema_version = registry_data.get('registry_schema_version', '') + if schema_version.startswith('1.1.'): + return True + + # Check for CrackingShells registry structure + if 'repositories' in registry_data: + return True + + return False +``` + +## Automatic Schema Updates + +### Update Triggers + +Schema updates are triggered by several events: + +**Time-Based Updates:** +- Cache TTL expiration (default: 24 hours) +- Forced update requests (`force_update=True`) + +**Event-Based Updates:** +- Application startup with stale cache +- Schema loading failures +- Validation errors due to missing schemas + +### Update Process + +The schema update process is coordinated across components: + +```python +def update_schemas() -> bool: + """Coordinate schema updates across the system.""" + + # 1. Fetch latest schema information from GitHub + fetcher = SchemaFetcher() + latest_info = fetcher.get_latest_schema_info() + + if not latest_info: + logger.warning("Failed to fetch latest schema info") + return False + + # 2. Check for new schema versions + cache = SchemaCache() + current_info = cache.get_info() + + updated = False + for schema_type in ['package', 'registry']: + current_version = current_info.get(f"latest_{schema_type}_version") + latest_version = latest_info.get(f"latest_{schema_type}_version") + + if current_version != latest_version: + # 3. Download new schema + schema_url = latest_info[schema_type]['url'] + schema_data = fetcher.download_schema(schema_url) + + if schema_data: + # 4. Update cache + cache.save_schema(schema_type, schema_data, latest_version) + cache.save_schema(schema_type, schema_data) # Also save as latest + updated = True + logger.info(f"Updated {schema_type} schema to {latest_version}") + + # 5. Update cache metadata + if updated: + cache.update_info(latest_info) + + return updated +``` + +### Component Coordination + +Schema updates coordinate with component factories: + +```python +class ValidatorFactory: + @classmethod + def _ensure_validators_loaded(cls) -> None: + """Ensure validators are loaded and schemas are current.""" + + # Check for schema updates before loading validators + schema_retriever.get_schema("package", "latest") # Triggers update check + + # Load validators based on available schemas + if not cls._validator_registry: + # Auto-discover and register validators + cls._discover_validators() +``` + +## Error Handling and Resilience + +### Network Failure Handling + +The system gracefully handles network failures: + +```python +def get_schema_with_fallback(schema_type: str, version: str) -> Optional[Dict[str, Any]]: + """Get schema with network failure fallback.""" + + try: + # Try to get latest schema (may trigger network request) + return schema_retriever.get_schema(schema_type, version, force_update=True) + except requests.RequestException: + # Network failure - fall back to cached schema + logger.warning("Network failure, using cached schema") + return schema_retriever.get_schema(schema_type, version, force_update=False) + except Exception as e: + # Other errors - log and continue with cached schema + logger.error(f"Schema retrieval error: {e}") + return schema_retriever.get_schema(schema_type, version, force_update=False) +``` + +### Schema Validation Errors + +The system handles schema validation errors gracefully: + +```python +def validate_with_fallback(metadata: Dict, schema_version: str) -> Tuple[bool, List[str]]: + """Validate with schema fallback.""" + + # Try validation with specific schema version + schema = get_package_schema(schema_version) + if schema: + try: + jsonschema.validate(metadata, schema) + return True, [] + except jsonschema.ValidationError as e: + return False, [f"Schema validation error: {e.message}"] + + # Fallback to latest schema if specific version unavailable + latest_schema = get_package_schema("latest") + if latest_schema: + try: + jsonschema.validate(metadata, latest_schema) + logger.warning(f"Validated with latest schema instead of {schema_version}") + return True, [] + except jsonschema.ValidationError as e: + return False, [f"Schema validation error (latest): {e.message}"] + + # No schema available - skip schema validation + logger.error("No schema available for validation") + return True, ["Schema validation skipped - no schema available"] +``` + +### Cache Corruption Recovery + +The system recovers from cache corruption: + +```python +def load_schema_with_recovery(schema_type: str, version: str) -> Optional[Dict[str, Any]]: + """Load schema with corruption recovery.""" + + try: + return cache.load_schema(schema_type, version) + except (json.JSONDecodeError, IOError) as e: + logger.warning(f"Cache corruption detected: {e}") + + # Remove corrupted cache file + cache_path = cache.get_schema_path(schema_type, version) + if cache_path.exists(): + cache_path.unlink() + + # Trigger fresh download + return schema_retriever.get_schema(schema_type, version, force_update=True) +``` + +## Performance Optimization + +### Lazy Schema Loading + +Schemas are loaded only when needed: + +```python +class LazySchemaLoader: + def __init__(self): + self._schema_cache = {} + + def get_schema(self, schema_type: str, version: str) -> Optional[Dict[str, Any]]: + """Get schema with lazy loading.""" + + cache_key = f"{schema_type}:{version}" + + if cache_key not in self._schema_cache: + # Load schema on first access + self._schema_cache[cache_key] = schema_retriever.get_schema(schema_type, version) + + return self._schema_cache[cache_key] +``` + +### Background Updates + +Schema updates can happen in the background: + +```python +import threading + +def background_schema_update(): + """Update schemas in background thread.""" + + def update_worker(): + try: + schema_retriever.get_schema("package", "latest", force_update=True) + schema_retriever.get_schema("registry", "latest", force_update=True) + logger.info("Background schema update completed") + except Exception as e: + logger.error(f"Background schema update failed: {e}") + + # Start background update + update_thread = threading.Thread(target=update_worker, daemon=True) + update_thread.start() +``` + +## Related Documentation + +- [Chain of Responsibility Pattern](ChainOfResponsibilityPattern.md) - Core architectural pattern +- [Component Types](ComponentTypes.md) - How components use schema information +- [Schema Management](../../users/validation/SchemaManagement.md) - User-facing schema management diff --git a/docs/articles/devs/contribution_guidelines/ExtendingChainOfResponsibility.md b/docs/articles/devs/contribution_guidelines/ExtendingChainOfResponsibility.md new file mode 100644 index 0000000..ee0b3b8 --- /dev/null +++ b/docs/articles/devs/contribution_guidelines/ExtendingChainOfResponsibility.md @@ -0,0 +1,378 @@ +# Extending Chain of Responsibility + +This article is about: + +- Adding new schema version support across all three component types +- Extension mechanisms for validators, package accessors, and registry accessors +- Best practices for implementing delegation and maintaining chain integrity +- Testing strategies for new components and chain behavior + +## Overview + +Extending Hatch-Validator to support new schema versions requires implementing components across all three types: validators, package accessors, and registry accessors. This guide provides comprehensive instructions for adding new schema version support while maintaining the Chain of Responsibility pattern integrity. + +## Adding New Schema Version Support + +### Step 1: Create Version Directory Structure + +For a new schema version (e.g., v1.3.0), create the following directory structure: + +```plaintext +hatch_validator/ +├── package/ +│ └── v1_3_0/ +│ ├── __init__.py +│ ├── accessor.py # Package accessor implementation +│ ├── new_feature_validation.py # Strategy for new feature validation +│ └── validator.py # Validator implementation +└── registry/ + └── v1_3_0/ + ├── __init__.py + └── registry_accessor.py # Registry accessor implementation +``` + +### Step 2: Implement Package Accessor + +Create the package accessor for the new schema version: + +```python +# hatch_validator/package/v1_3_0/accessor.py +from typing import Dict, Any, Optional +from hatch_validator.core.pkg_accessor_base import HatchPkgAccessorBase + +class V130PackageAccessor(HatchPkgAccessorBase): + """Package accessor for schema version 1.3.0.""" + + def can_handle(self, schema_version: str) -> bool: + """Check if this accessor can handle the schema version.""" + return schema_version in ["1.3.0", "v1.3.0"] + + def get_new_feature(self, metadata: Dict[str, Any]) -> Any: + """Handle v1.3.0-specific new feature.""" + # Implement new functionality specific to v1.3.0 + return metadata.get('new_feature_field', {}) + + def get_dependencies(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Delegate dependency access to v1.2.1.""" + # v1.3.0 doesn't change dependency structure, delegate to v1.2.1 + if self.next_accessor: + return self.next_accessor.get_dependencies(metadata) + raise NotImplementedError("Dependencies accessor not implemented") + + def get_entry_points(self, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Handle entry points - may delegate or implement new logic.""" + # If v1.3.0 changes entry point structure, implement here + # Otherwise, delegate to previous version + if self.next_accessor: + return self.next_accessor.get_entry_points(metadata) + raise NotImplementedError("Entry points accessor not implemented") +``` + +### Step 3: Implement Validator + +Create the validator for the new schema version: + +```python +# hatch_validator/package/v1_3_0/validator.py +from typing import Dict, List, Tuple, Optional +from hatch_validator.core.validator_base import Validator +from hatch_validator.core.validation_context import ValidationContext + +class V130Validator(Validator): + """Validator for schema version 1.3.0.""" + + def can_handle(self, schema_version: str) -> bool: + """Check if this validator can handle the schema version.""" + return schema_version in ["1.3.0", "v1.3.0"] + + def validate(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + """Validate v1.3.0 package or delegate to next validator.""" + + schema_version = metadata.get("package_schema_version", "") + + if not self.can_handle(schema_version): + # Delegate to next validator in chain + if self.next_validator: + return self.next_validator.validate(metadata, context) + return False, [f"Unsupported schema version: {schema_version}"] + + # Perform v1.3.0-specific validation + errors = [] + + # Validate new features specific to v1.3.0 + new_feature_valid, new_feature_errors = self._validate_new_feature(metadata, context) + errors.extend(new_feature_errors) + + # Delegate unchanged validation concerns to previous validators + if self.next_validator: + # Delegate dependency validation to v1.2.1 + dep_valid, dep_errors = self.next_validator.validate_dependencies(metadata, context) + errors.extend(dep_errors) + + # Delegate entry point validation to v1.2.1 + entry_valid, entry_errors = self.next_validator.validate_entry_points(metadata, context) + errors.extend(entry_errors) + + return len(errors) == 0, errors + + def _validate_new_feature(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + """Validate v1.3.0-specific new feature.""" + errors = [] + + new_feature = metadata.get('new_feature_field') + if new_feature is not None: + # Implement validation logic for new feature + if not isinstance(new_feature, dict): + errors.append("new_feature_field must be a dictionary") + + # Add more specific validation rules + required_fields = ['field1', 'field2'] + for field in required_fields: + if field not in new_feature: + errors.append(f"new_feature_field missing required field: {field}") + + return len(errors) == 0, errors +``` + +### Step 4: Implement Registry Accessor (if needed) + +If the new schema version affects registry operations, implement a registry accessor: + +```python +# hatch_validator/registry/v1_3_0/registry_accessor.py +from typing import Dict, Any, Optional +from hatch_validator.registry.registry_accessor_base import RegistryAccessorBase + +class V130RegistryAccessor(RegistryAccessorBase): + """Registry accessor for schema version 1.3.0.""" + + def can_handle(self, registry_data: Dict[str, Any]) -> bool: + """Check if this accessor can handle the registry data.""" + schema_version = registry_data.get('registry_schema_version', '') + return schema_version.startswith('1.3.') + + def package_exists(self, registry_data: Dict[str, Any], package_name: str, + repo_name: Optional[str] = None) -> bool: + """Check package existence with v1.3.0 registry format.""" + + # If v1.3.0 doesn't change registry structure, delegate + if self._successor: + return self._successor.package_exists(registry_data, package_name, repo_name) + + # Otherwise, implement v1.3.0-specific logic here + return False +``` + +### Step 5: Register Components with Factories + +Update factory classes to register new components: + +```python +# hatch_validator/core/pkg_accessor_factory.py +class HatchPkgAccessorFactory: + @classmethod + def _ensure_accessors_loaded(cls) -> None: + """Load all available accessors including v1.3.0.""" + if not cls._accessor_registry: + # Register v1.3.0 accessor (newest first) + from hatch_validator.package.v1_3_0.accessor import V130PackageAccessor + cls.register_accessor('1.3.0', V130PackageAccessor) + + # Register existing accessors + from hatch_validator.package.v1_2_1.accessor import V121PackageAccessor + cls.register_accessor('1.2.1', V121PackageAccessor) + + # ... register other versions + + # Update version order (newest to oldest) + cls._version_order = ['1.3.0', '1.2.1', '1.2.0', '1.1.0'] + +# hatch_validator/core/validator_factory.py +class ValidatorFactory: + @classmethod + def _ensure_validators_loaded(cls) -> None: + """Load all available validators including v1.3.0.""" + if not cls._validator_registry: + # Register v1.3.0 validator (newest first) + from hatch_validator.package.v1_3_0.validator import V130Validator + cls.register_validator('1.3.0', V130Validator) + + # Register existing validators + # ... register other versions + + # Update version order (newest to oldest) + cls._version_order = ['1.3.0', '1.2.1', '1.2.0', '1.1.0'] +``` + +## Strategy Implementation Guidelines + +### When to Implement New Strategies + +**Create New Strategy When**: + +1. Schema version introduces new validation requirements +2. Validation algorithm changes significantly +3. New validation logic cannot reuse previous implementation + +**Use Chain Delegation When**: + +1. Validation logic unchanged from previous version +2. Previous version's strategy is sufficient +3. No new validation requirements + +### Strategy Implementation Process + +1. **Create Strategy Class**: + +```python +class NewFeatureValidation(ValidationStrategy): + def validate_new_feature(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + # Implement v1.3.0-specific validation logic + pass +``` + +2. **Compose Strategy in Validator**: + +```python +class V130Validator(ValidatorBase): + def __init__(self, next_validator=None): + super().__init__(next_validator) + self.new_feature_strategy = NewFeatureValidation() + + def validate_new_feature(self, metadata: Dict, context: ValidationContext) -> Tuple[bool, List[str]]: + return self.new_feature_strategy.validate_new_feature(metadata, context) +``` + +For comprehensive information on strategy interfaces and patterns, see [Chain of Responsibility Pattern](../architecture/ChainOfResponsibilityPattern.md#strategy-interface-hierarchy). + +## Extension Best Practices + +For delegation principles and patterns, see [Chain of Responsibility Pattern](../architecture/ChainOfResponsibilityPattern.md#delegation-mechanisms). This section focuses on extension-specific implementation details. + +### Error Handling + +**Graceful Delegation**: Handle errors gracefully when delegating: + +```python +def get_field_with_fallback(self, metadata: Dict[str, Any], field_name: str) -> Any: + """Get field with graceful delegation.""" + try: + # Try to handle with this accessor + if field_name in self.HANDLED_FIELDS: + return self._get_field(metadata, field_name) + except Exception as e: + logger.warning(f"Error handling {field_name}: {e}") + + # Delegate to next accessor + if self.next_accessor: + return self.next_accessor.get_field_with_fallback(metadata, field_name) + + raise NotImplementedError(f"Field {field_name} not handled by any accessor") +``` + +**Chain Validation**: Validate chain integrity during construction: + +```python +def validate_chain_integrity(chain_head: ComponentBase) -> bool: + """Validate that chain covers all required functionality.""" + + current = chain_head + covered_versions = set() + + while current: + # Check that component implements required methods + required_methods = ['can_handle', 'get_dependencies', 'get_entry_points'] + for method in required_methods: + if not hasattr(current, method): + logger.error(f"Component {current.__class__.__name__} missing method: {method}") + return False + + # Track covered versions + if hasattr(current, 'SUPPORTED_VERSION'): + covered_versions.add(current.SUPPORTED_VERSION) + + current = getattr(current, 'next_accessor', None) or getattr(current, 'next_validator', None) + + # Ensure all required versions are covered + required_versions = {'1.1.0', '1.2.0', '1.2.1'} + if not required_versions.issubset(covered_versions): + missing = required_versions - covered_versions + logger.error(f"Chain missing support for versions: {missing}") + return False + + return True +``` + +## Maintaining Chain Integrity + +### Version Ordering + +Maintain correct version ordering in factories: + +```python +# Always order from newest to oldest +_version_order = ['1.3.0', '1.2.1', '1.2.0', '1.1.0'] + +# Verify ordering is correct +def validate_version_ordering(versions: List[str]) -> bool: + """Validate that versions are ordered newest to oldest.""" + for i in range(len(versions) - 1): + current = parse_version(versions[i]) + next_version = parse_version(versions[i + 1]) + if current <= next_version: + return False + return True +``` + +### Component Registration + +Ensure all components are registered correctly: + +```python +def register_all_components(): + """Register all components with their factories.""" + + # Package accessors + HatchPkgAccessorFactory.register_accessor('1.3.0', V130PackageAccessor) + HatchPkgAccessorFactory.register_accessor('1.2.1', V121PackageAccessor) + # ... register all versions + + # Validators + ValidatorFactory.register_validator('1.3.0', V130Validator) + ValidatorFactory.register_validator('1.2.1', V121Validator) + # ... register all versions + + # Registry accessors (if applicable) + RegistryAccessorFactory.register_accessor('1.3.0', V130RegistryAccessor) + # ... register all versions +``` + +### Backward Compatibility + +Ensure new components maintain backward compatibility: + +```python +def test_backward_compatibility(): + """Test that new components work with older packages.""" + + # v1.3.0 chain should handle v1.2.1 packages + chain = HatchPkgAccessorFactory.create_accessor_chain("1.3.0") + + v121_metadata = { + "package_schema_version": "1.2.1", + "name": "old-package", + "mcp_server": {"command": "server"}, + "hatch_mcp_server": {"command": "hatch-server"} + } + + # Should delegate to v1.2.1 accessor + entry_points = chain.get_entry_points(v121_metadata) + assert "mcp_server" in entry_points + assert "hatch_mcp_server" in entry_points +``` + +## Related Documentation + +- [Chain of Responsibility Pattern](../architecture/ChainOfResponsibilityPattern.md) - Core pattern implementation +- [Component Types](../architecture/ComponentTypes.md) - Understanding different component types +- [Schema Integration](../architecture/SchemaIntegration.md) - Schema management integration diff --git a/docs/articles/users/GettingStarted.md b/docs/articles/users/GettingStarted.md new file mode 100644 index 0000000..d288bf1 --- /dev/null +++ b/docs/articles/users/GettingStarted.md @@ -0,0 +1,169 @@ +# Getting Started with Hatch-Validator + +This article is about: +- Installing and setting up Hatch-Validator +- Understanding version-agnostic data access concepts +- Basic validation workflows using HatchPackageValidator +- Introduction to PackageService and RegistryService capabilities + +## Installation + +Install Hatch-Validator using pip: + +```bash +pip install hatch-validator +``` + +## Core Concepts + +### Version-Agnostic Data Access + +Hatch-Validator provides a unified interface for working with package metadata and registry data across different schema versions. This means your code remains stable even as package schemas evolve from v1.1.0 to v1.2.0 to v1.2.1 and beyond. + +**Key Benefits:** +- **Schema Transparency**: Your code doesn't need to know about schema versions +- **Automatic Evolution**: New schema versions work without code changes +- **Consistent APIs**: Same method signatures across all schema versions + +### Chain of Responsibility Architecture + +The validator uses the Chain of Responsibility design pattern to handle different schema versions. When you request data or validation, the system automatically: + +1. Detects the schema version from metadata +2. Creates the appropriate chain of components +3. Delegates requests through the chain +4. Returns results using a consistent interface + +## Basic Package Validation + +### Simple Validation Example + +```python +from pathlib import Path +from hatch_validator import HatchPackageValidator + +# Create validator with default settings +validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True +) + +# Validate a package +package_path = Path("./my-package") +is_valid, results = validator.validate_package(package_path) + +if is_valid: + print("Package validation successful!") +else: + print("Package validation failed:") + for category, result in results.items(): + if not result.get('valid', True) and result.get('errors'): + print(f"{category}: {result['errors']}") +``` + +### Validation with Registry Data + +```python +from hatch_validator import HatchPackageValidator + +# Create validator with registry data for dependency validation +validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True, + registry_data=registry_data # From environment manager +) + +# Validation automatically handles schema versions +is_valid, results = validator.validate_package(package_path) +``` + +## Working with Package Metadata + +### PackageService Overview + +The PackageService class provides version-agnostic access to package metadata: + +```python +from hatch_validator.package.package_service import PackageService + +# Load package metadata +service = PackageService(metadata) + +# Access dependencies without knowing schema version +dependencies = service.get_dependencies() + +# Access any metadata field +name = service.get_field('name') +version = service.get_field('version') +``` + +**Key Features:** +- Automatic schema version detection +- Unified dependency access across schema versions +- Consistent field access methods + +## Working with Registry Data + +### RegistryService Overview + +The RegistryService class provides version-agnostic access to registry data: + +```python +from hatch_validator.registry.registry_service import RegistryService + +# Initialize with registry data +service = RegistryService(registry_data) + +# Check package existence +exists = service.package_exists("my-package") + +# Find compatible versions +compatible_version = service.find_compatible_version( + "my-package", ">=1.0.0" +) + +# Get package URI +uri = service.get_package_uri("my-package", "1.2.0") +``` + +**Key Features:** +- Automatic registry schema detection +- Version-agnostic package discovery +- Consistent registry operations + +## Schema Version Support + +Hatch-Validator currently supports these package schema versions: + +- **v1.1.0**: Base schema with separate hatch and python dependencies +- **v1.2.0**: Unified dependencies structure with hatch, python, system, and docker support +- **v1.2.1**: Dual entry point support with enhanced validation + +The system automatically detects and handles the appropriate schema version based on the `package_schema_version` field in your metadata. + +## Integration Patterns + +### Environment Integration + +For comprehensive examples of how to integrate Hatch-Validator with environment managers, dependency orchestrators, and CLI tools, see [Programmatic Usage](../integration/ProgrammaticUsage.md). + +### Data Access Patterns + +For detailed information about version-agnostic data access: +- [PackageService Guide](../data_access/PackageService.md) +- [RegistryService Guide](../data_access/RegistryService.md) +- [Version-Agnostic Access Concepts](../data_access/VersionAgnosticAccess.md) + +### Validation Workflows + +For advanced validation scenarios: +- [Package Validation Guide](../validation/PackageValidation.md) +- [Schema Management](../validation/SchemaManagement.md) + +## Next Steps + +1. **Explore Real-World Examples**: See [Programmatic Usage](../integration/ProgrammaticUsage.md) for actual integration patterns from first-party consumers +2. **Understand the Architecture**: Read about the [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) that enables version-agnostic access +3. **Learn Extension Patterns**: See [Extending Chain of Responsibility](../../devs/contribution_guidelines/ExtendingChainOfResponsibility.md) for adding new schema versions + +The version-agnostic design ensures your integration code remains stable as the Hatch ecosystem evolves, providing a reliable foundation for package management and validation workflows. diff --git a/docs/articles/users/data_access/PackageService.md b/docs/articles/users/data_access/PackageService.md new file mode 100644 index 0000000..e908b4f --- /dev/null +++ b/docs/articles/users/data_access/PackageService.md @@ -0,0 +1,208 @@ +# PackageService Guide + +This article is about: +- Version-agnostic package metadata access through PackageService +- How PackageService abstracts schema versioning using accessor chains +- API overview and key methods for metadata operations +- Integration patterns with the Chain of Responsibility architecture + +## Overview + +The PackageService class provides a unified interface for accessing package metadata regardless of schema version. It automatically detects the schema version from metadata and creates the appropriate accessor chain to handle version-specific data structures. + +## Core Concepts + +### Automatic Schema Detection + +PackageService automatically detects the package schema version and creates the appropriate accessor chain: + +```python +from hatch_validator.package.package_service import PackageService + +# Service automatically detects schema version from metadata +service = PackageService(metadata) + +# No need to specify schema version - it's handled automatically +dependencies = service.get_dependencies() +``` + +### Accessor Chain Integration + +The service uses the HatchPkgAccessorFactory to create accessor chains that implement the Chain of Responsibility pattern: + +1. **Schema Version Detection**: Extracts `package_schema_version` from metadata +2. **Chain Creation**: Creates accessor chain starting from detected version +3. **Delegation**: Each accessor handles its version or delegates to older versions +4. **Unified Interface**: Returns data through consistent method signatures + +## API Reference + +### Constructor + +```python +PackageService(metadata: Optional[Dict[str, Any]] = None) +``` + +**Parameters:** +- `metadata`: Optional package metadata dictionary. If provided, automatically initializes the accessor chain. + +### Core Methods + +#### load_metadata() + +```python +def load_metadata(self, metadata: Dict[str, Any]) -> None +``` + +Loads package metadata and initializes the appropriate accessor chain based on the detected schema version. + +**Parameters:** +- `metadata`: Package metadata dictionary containing `package_schema_version` + +**Raises:** +- `ValueError`: If `package_schema_version` is missing or no accessor can handle the version + +#### get_dependencies() + +```python +def get_dependencies(self) -> Dict[str, Any] +``` + +Returns all dependencies from the package metadata using version-appropriate access patterns. + +**Returns:** +- Dictionary of dependencies organized by type (e.g., 'hatch', 'python', 'system', 'docker') + +**Schema Version Handling:** +- **v1.1.0**: Returns `{'hatch': [...], 'python': [...]}` +- **v1.2.0+**: Returns unified dependency structure with all supported types + +#### get_field() + +```python +def get_field(self, field: str) -> Any +``` + +Retrieves a top-level field from package metadata using the appropriate accessor. + +**Parameters:** +- `field`: Field name to retrieve (e.g., 'name', 'version', 'description') + +**Returns:** +- Field value or None if not found + +#### is_local_dependency() + +```python +def is_local_dependency(self, dep: Dict[str, Any], root_dir: Optional[Path] = None) -> bool +``` + +Determines if a dependency is local using version-appropriate logic. + +**Parameters:** +- `dep`: Dependency dictionary +- `root_dir`: Optional root directory for relative path resolution + +**Returns:** +- True if dependency is local, False otherwise + +### Utility Methods + +#### is_loaded() + +```python +def is_loaded(self) -> bool +``` + +Checks if package metadata is loaded and accessible. + +**Returns:** +- True if metadata and accessor are available + +## Schema Version Abstraction + +### Version-Specific Behavior + +The PackageService abstracts differences between schema versions: + +**v1.1.0 Schema:** +- Separate `hatch_dependencies` and `python_dependencies` fields +- Basic dependency structure + +**v1.2.0 Schema:** +- Unified `dependencies` structure +- Support for hatch, python, system, and docker dependency types +- Enhanced dependency metadata + +**v1.2.1 Schema:** +- Dual entry point configuration +- Enhanced tools validation +- Backward compatibility with v1.2.0 dependency structure + +### Consistent Interface + +Regardless of schema version, the same method calls work: + +```python +# This code works with any supported schema version +service = PackageService(metadata) +deps = service.get_dependencies() +name = service.get_field('name') +``` + +## Integration with Chain of Responsibility + +### Accessor Chain Creation + +When PackageService loads metadata, it: + +1. **Extracts Schema Version**: Gets `package_schema_version` from metadata +2. **Creates Chain**: Uses HatchPkgAccessorFactory to create accessor chain +3. **Links Components**: Accessors are linked newest to oldest (e.g., v1.2.1 → v1.2.0 → v1.1.0) +4. **Delegates Requests**: Each accessor handles its concerns or delegates to the next + +### Delegation Flow + +For a v1.2.1 package requesting dependencies: + +1. **v1.2.1 Accessor**: Handles dual entry point metadata, delegates dependency access to v1.2.0 +2. **v1.2.0 Accessor**: Handles unified dependency structure, returns result +3. **Service**: Returns unified dependency data to caller + +## Error Handling + +### Common Exceptions + +**ValueError**: Raised when: +- `package_schema_version` is missing from metadata +- No accessor can handle the detected schema version +- Metadata is not loaded when accessing data + +**AttributeError**: Raised when: +- Requested field is not supported by the accessor chain + +### Best Practices + +```python +try: + service = PackageService() + service.load_metadata(metadata) + dependencies = service.get_dependencies() +except ValueError as e: + # Handle schema version or loading errors + print(f"Metadata loading failed: {e}") +except AttributeError as e: + # Handle unsupported field access + print(f"Field access failed: {e}") +``` + +## Real-World Usage Examples + +For comprehensive examples of PackageService usage in production environments, including integration with dependency orchestrators and environment managers, see [Programmatic Usage](../integration/ProgrammaticUsage.md). + +## Related Documentation + +- [RegistryService Guide](RegistryService.md) - Version-agnostic registry data access +- [Version-Agnostic Access Concepts](VersionAgnosticAccess.md) - Core principles and benefits +- [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) - Architectural foundation +- [Programmatic Usage](../integration/ProgrammaticUsage.md) - Real-world integration examples diff --git a/docs/articles/users/data_access/RegistryService.md b/docs/articles/users/data_access/RegistryService.md new file mode 100644 index 0000000..a37686f --- /dev/null +++ b/docs/articles/users/data_access/RegistryService.md @@ -0,0 +1,299 @@ +# RegistryService Guide + +This article is about: +- Version-agnostic registry data access through RegistryService +- Package discovery and version resolution capabilities +- API overview and key methods for registry operations +- Integration patterns with registry accessor chains + +## Overview + +The RegistryService class provides a unified interface for working with package registries regardless of registry schema version. It automatically detects the registry data format and creates the appropriate accessor chain to handle version-specific registry structures. + +## Core Concepts + +### Automatic Registry Schema Detection + +RegistryService automatically detects the registry schema version and creates the appropriate accessor chain: + +```python +from hatch_validator.registry.registry_service import RegistryService + +# Service automatically detects registry schema from data +service = RegistryService(registry_data) + +# No need to specify schema version - it's handled automatically +exists = service.package_exists("my-package") +``` + +### Registry Accessor Chain Integration + +The service uses the RegistryAccessorFactory to create accessor chains that implement the Chain of Responsibility pattern: + +1. **Schema Detection**: Analyzes registry data structure and format +2. **Chain Creation**: Creates accessor chain for detected registry version +3. **Delegation**: Each accessor handles its format or delegates to compatible versions +4. **Unified Interface**: Returns data through consistent method signatures + +## API Reference + +### Constructor + +```python +RegistryService(registry_data: Optional[Dict[str, Any]] = None) +``` + +**Parameters:** +- `registry_data`: Optional registry data dictionary. If provided, automatically initializes the accessor chain. + +### Core Methods + +#### load_registry_data() + +```python +def load_registry_data(self, registry_data: Dict[str, Any]) -> None +``` + +Loads registry data and initializes the appropriate accessor chain based on the detected registry format. + +**Parameters:** +- `registry_data`: Registry data dictionary + +**Raises:** +- `RegistryError`: If no accessor can handle the registry data format + +#### Package Discovery Methods + +##### package_exists() + +```python +def package_exists(self, package_name: str, repo_name: Optional[str] = None) -> bool +``` + +Checks if a package exists in the registry. + +**Parameters:** +- `package_name`: Name of the package to check +- `repo_name`: Optional repository name. If None, infers from package_name if present + +**Returns:** +- True if package exists in the registry + +##### get_all_package_names() + +```python +def get_all_package_names(self, repo_name: Optional[str] = None) -> List[str] +``` + +Retrieves all package names from the registry. + +**Parameters:** +- `repo_name`: Optional repository name. If None, returns packages from all repositories + +**Returns:** +- List of all package names + +#### Version Resolution Methods + +##### find_compatible_version() + +```python +def find_compatible_version(self, package_name: str, version_constraint: str) -> str +``` + +Finds a package version that satisfies the given version constraint. + +**Parameters:** +- `package_name`: Name of the package +- `version_constraint`: Version constraint string (e.g., ">=1.0.0", "~=2.1.0") + +**Returns:** +- Compatible version string + +**Raises:** +- `VersionConstraintError`: If no compatible version is found + +##### get_package_uri() + +```python +def get_package_uri(self, package_name: str, version: str) -> str +``` + +Retrieves the download URI for a specific package version. + +**Parameters:** +- `package_name`: Name of the package +- `version`: Specific version string + +**Returns:** +- Package download URI + +#### Repository Management Methods + +##### list_repositories() + +```python +def list_repositories(self) -> List[str] +``` + +Lists all repository names in the loaded registry. + +**Returns:** +- List of repository names + +##### repository_exists() + +```python +def repository_exists(self, repo_name: str) -> bool +``` + +Checks if a repository exists in the loaded registry. + +**Parameters:** +- `repo_name`: Repository name to check + +**Returns:** +- True if repository exists + +##### list_packages() + +```python +def list_packages(self, repo_name: str) -> List[str] +``` + +Lists all package names in a specific repository. + +**Parameters:** +- `repo_name`: Repository name + +**Returns:** +- List of package names in the repository + +### Utility Methods + +#### is_loaded() + +```python +def is_loaded(self) -> bool +``` + +Checks if registry data is loaded and accessible. + +**Returns:** +- True if registry data and accessor are available + +#### has_repository_name() + +```python +def has_repository_name(self, package_name: str) -> bool +``` + +Checks if a package name includes a repository prefix (e.g., "repo:package"). + +**Parameters:** +- `package_name`: Package name to check + +**Returns:** +- True if package name includes repository prefix + +## Registry Schema Abstraction + +### Version-Specific Behavior + +The RegistryService abstracts differences between registry schema versions: + +**v1.1.0 Registry Schema (CrackingShells Format):** +- Repository-based structure with packages containing versions +- Standard package metadata fields +- Version constraint validation + +**Future Registry Schemas:** +- Will be handled automatically through the accessor chain +- Backward compatibility maintained through delegation + +### Consistent Interface + +Regardless of registry schema version, the same method calls work: + +```python +# This code works with any supported registry schema version +service = RegistryService(registry_data) +exists = service.package_exists("my-package") +version = service.find_compatible_version("my-package", ">=1.0.0") +uri = service.get_package_uri("my-package", version) +``` + +## Integration with Chain of Responsibility + +### Accessor Chain Creation + +When RegistryService loads registry data, it: + +1. **Analyzes Data Format**: Examines registry data structure and schema indicators +2. **Creates Chain**: Uses RegistryAccessorFactory to create accessor chain +3. **Links Components**: Accessors are linked to handle format variations +4. **Delegates Requests**: Each accessor handles its format or delegates to compatible accessors + +### Delegation Flow + +For registry operations: + +1. **Primary Accessor**: Attempts to handle the registry data format +2. **Fallback Accessors**: Handle alternative formats or provide compatibility +3. **Service**: Returns unified results to caller + +## Error Handling + +### Common Exceptions + +**RegistryError**: Raised when: +- Registry data is not loaded when accessing operations +- No accessor can handle the registry data format +- Registry operations fail due to data inconsistencies + +**VersionConstraintError**: Raised when: +- No package version satisfies the given constraint +- Version constraint format is invalid + +### Best Practices + +```python +from hatch_validator.registry.registry_service import RegistryService, RegistryError +from hatch_validator.utils.version_utils import VersionConstraintError + +try: + service = RegistryService(registry_data) + if service.package_exists("my-package"): + version = service.find_compatible_version("my-package", ">=1.0.0") + uri = service.get_package_uri("my-package", version) +except RegistryError as e: + # Handle registry data or loading errors + print(f"Registry operation failed: {e}") +except VersionConstraintError as e: + # Handle version constraint errors + print(f"Version resolution failed: {e}") +``` + +## Performance Considerations + +### Efficient Package Discovery + +- Use `package_exists()` before attempting version resolution +- Cache registry service instances when working with the same registry data +- Leverage repository-specific operations when working with known repositories + +### Version Resolution Optimization + +- Use specific version constraints when possible to reduce resolution time +- Consider caching resolved versions for frequently accessed packages + +## Real-World Usage Examples + +For comprehensive examples of RegistryService usage in production environments, including integration with dependency orchestrators and environment managers, see [Programmatic Usage](../integration/ProgrammaticUsage.md). + +## Related Documentation + +- [PackageService Guide](PackageService.md) - Version-agnostic package metadata access +- [Version-Agnostic Access Concepts](VersionAgnosticAccess.md) - Core principles and benefits +- [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) - Architectural foundation +- [Programmatic Usage](../integration/ProgrammaticUsage.md) - Real-world integration examples diff --git a/docs/articles/users/data_access/VersionAgnosticAccess.md b/docs/articles/users/data_access/VersionAgnosticAccess.md new file mode 100644 index 0000000..c888d9f --- /dev/null +++ b/docs/articles/users/data_access/VersionAgnosticAccess.md @@ -0,0 +1,226 @@ +# Version-Agnostic Access Concepts + +This article is about: +- Core concept of version-agnostic data access in Hatch-Validator +- How Chain of Responsibility enables schema transparency for consumers +- Benefits for consumers and ecosystem stability +- Migration scenarios and backward compatibility guarantees + +## Core Concept + +Version-agnostic access is the fundamental principle that **consumers don't need to know about schema versions**. When you use Hatch-Validator's services, your code remains stable regardless of whether you're working with v1.1.0, v1.2.0, v1.2.1, or future schema versions. + +### The Problem Version-Agnostic Access Solves + +Without version-agnostic access, consumer code would need to handle schema differences manually: + +```python +# Without version-agnostic access (problematic approach) +if schema_version == "1.1.0": + hatch_deps = metadata.get('hatch_dependencies', []) + python_deps = metadata.get('python_dependencies', []) + dependencies = {'hatch': hatch_deps, 'python': python_deps} +elif schema_version == "1.2.0": + dependencies = metadata.get('dependencies', {}) +elif schema_version == "1.2.1": + dependencies = metadata.get('dependencies', {}) + # Handle dual entry points... +``` + +### The Version-Agnostic Solution + +With Hatch-Validator's version-agnostic access, the same code works across all schema versions: + +```python +# With version-agnostic access (recommended approach) +from hatch_validator.package.package_service import PackageService + +service = PackageService(metadata) +dependencies = service.get_dependencies() # Works with any schema version +``` + +## How Chain of Responsibility Enables Schema Transparency + +### Automatic Schema Detection + +The system automatically detects schema versions from metadata and creates appropriate processing chains: + +1. **Detection**: Extract `package_schema_version` from metadata +2. **Chain Creation**: Build accessor/validator chain starting from detected version +3. **Delegation**: Each component handles its concerns or delegates to older versions +4. **Unified Response**: Return data through consistent interfaces + +### Delegation Mechanisms + +Each component in the chain implements version-specific logic while delegating unchanged concerns: + +**Package Accessors Example:** +- **v1.2.1 Accessor**: Handles dual entry point metadata → delegates dependency access to v1.2.0 +- **v1.2.0 Accessor**: Handles unified dependency structure → delegates basic fields to v1.1.0 +- **v1.1.0 Accessor**: Handles all basic metadata access (terminal accessor) + +**Result**: Consumer gets unified dependency data regardless of schema version. + +### Schema Evolution Handling + +When new schema versions are added: + +1. **New Components**: Create version-specific accessors/validators for changed functionality +2. **Delegation Setup**: New components delegate unchanged logic to previous versions +3. **Automatic Discovery**: Factory classes automatically discover and register new components +4. **Consumer Transparency**: Existing consumer code continues working without changes + +## Benefits for Consumers + +### Code Stability + +Consumer code remains stable across schema evolution: + +```python +# This code works with v1.1.0, v1.2.0, v1.2.1, and future versions +service = PackageService(metadata) +dependencies = service.get_dependencies() +name = service.get_field('name') +``` + +### Reduced Complexity + +Consumers focus on business logic rather than schema version management: + +- **No Version Checks**: No need to check `package_schema_version` +- **No Conditional Logic**: No version-specific code paths +- **Consistent APIs**: Same method signatures across all versions + +### Future-Proof Integration + +Code written today continues working with future schema versions: + +- **Automatic Compatibility**: New schema versions work through delegation +- **Gradual Migration**: Mix of schema versions can coexist +- **Zero Breaking Changes**: Consumer APIs remain stable + +## Benefits for Ecosystem Stability + +### Gradual Schema Migration + +The ecosystem can evolve schemas gradually without breaking existing tools: + +1. **New Schema Introduction**: Add new schema version with enhanced features +2. **Backward Compatibility**: Existing packages continue working +3. **Gradual Adoption**: Packages migrate to new schema at their own pace +4. **Tool Compatibility**: All tools work with all schema versions + +### Reduced Breaking Changes + +Schema evolution doesn't require coordinated updates across the ecosystem: + +- **Independent Updates**: Tools and packages can update independently +- **Mixed Environments**: Different schema versions can coexist +- **Stable Interfaces**: Consumer-facing APIs remain consistent + +### Ecosystem Resilience + +The architecture provides resilience against schema evolution challenges: + +- **Incremental Development**: New features can be added incrementally +- **Risk Reduction**: Schema changes have minimal impact on consumers +- **Adoption Flexibility**: No forced migrations or breaking changes + +## Migration Scenarios + +### Package Schema Migration + +When a package migrates from v1.1.0 to v1.2.0: + +**Before Migration (v1.1.0):** +```json +{ + "package_schema_version": "1.1.0", + "hatch_dependencies": [...], + "python_dependencies": [...] +} +``` + +**After Migration (v1.2.0):** +```json +{ + "package_schema_version": "1.2.0", + "dependencies": { + "hatch": [...], + "python": [...], + "system": [...], + "docker": [...] + } +} +``` + +**Consumer Code Impact:** None - the same PackageService calls work with both versions. + +### Tool Integration Migration + +When integrating Hatch-Validator into existing tools: + +1. **Replace Version-Specific Logic**: Remove manual schema version handling +2. **Use Service Classes**: Adopt PackageService and RegistryService +3. **Maintain Functionality**: Same functionality with simplified code +4. **Future Compatibility**: Automatic support for new schema versions + +## Backward Compatibility Guarantees + +### API Stability + +Consumer-facing APIs maintain stability: + +- **Method Signatures**: Service method signatures remain consistent +- **Return Formats**: Data structures returned by services remain compatible +- **Error Handling**: Exception types and error handling patterns remain stable + +### Data Access Patterns + +Data access patterns work across schema versions: + +- **Dependency Access**: `get_dependencies()` returns unified structure for all versions +- **Field Access**: `get_field()` works with any metadata field across versions +- **Registry Operations**: Registry methods work with any supported registry format + +### Delegation Guarantees + +The Chain of Responsibility pattern guarantees: + +- **Complete Coverage**: Every schema version has appropriate handling +- **Fallback Behavior**: Requests always reach a component that can handle them +- **Consistent Results**: Same logical operations produce consistent results + +## Implementation Transparency + +### Consumer Perspective + +From the consumer's perspective, version-agnostic access is completely transparent: + +```python +# Consumer code - no schema version awareness needed +service = PackageService(metadata) +dependencies = service.get_dependencies() + +# Works regardless of whether metadata is v1.1.0, v1.2.0, or v1.2.1 +``` + +### System Perspective + +Behind the scenes, the system handles all schema complexity: + +1. **Automatic Detection**: Schema version detected from metadata +2. **Chain Construction**: Appropriate accessor chain created +3. **Request Delegation**: Request flows through chain with proper delegation +4. **Unified Response**: Result returned through consistent interface + +## Real-World Impact + +For concrete examples of how version-agnostic access benefits real-world integrations, including dependency orchestrators, environment managers, and CLI tools, see [Programmatic Usage](../integration/ProgrammaticUsage.md). + +## Related Documentation + +- [PackageService Guide](PackageService.md) - Version-agnostic package metadata access +- [RegistryService Guide](RegistryService.md) - Version-agnostic registry data access +- [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) - Architectural foundation +- [Component Types](../../devs/architecture/ComponentTypes.md) - How different components work together diff --git a/docs/articles/users/integration/ProgrammaticUsage.md b/docs/articles/users/integration/ProgrammaticUsage.md new file mode 100644 index 0000000..a2171f8 --- /dev/null +++ b/docs/articles/users/integration/ProgrammaticUsage.md @@ -0,0 +1,454 @@ +# Programmatic Usage + +This article is about: + +- Real-world integration patterns from first-party consumers +- Dependency Installation Orchestrator usage of PackageService and RegistryService +- Environment Manager integration with RegistryService and HatchPackageValidator +- CLI integration patterns and validation workflows +- Best practices derived from actual production implementations + +## Overview + +This guide provides comprehensive examples of how Hatch-Validator is integrated in production environments. All examples are derived from actual first-party consumer implementations, demonstrating the practical benefits of version-agnostic data access and the Chain of Responsibility architecture. + +## Dependency Installation Orchestrator Integration + +### PackageService Usage Patterns + +The Dependency Installation Orchestrator uses PackageService to access package metadata without schema version awareness: + +```python +from hatch_validator.package.package_service import PackageService + +class DependencyInstallerOrchestrator: + def _resolve_package_location(self, package_path_or_name: str, + version_constraint: Optional[str] = None, + force_download: bool = False) -> Tuple[Path, Dict[str, Any]]: + """Resolve package location and load metadata using PackageService.""" + + if Path(package_path_or_name).exists(): + # Local package - load metadata directly + metadata_path = Path(package_path_or_name) / "hatch_metadata.json" + with open(metadata_path, 'r') as f: + metadata = json.load(f) + + # PackageService automatically handles schema version detection + self.package_service = PackageService(metadata) + return Path(package_path_or_name), metadata + + else: + # Remote package - resolve through registry + compatible_version = self.registry_service.find_compatible_version( + package_path_or_name, version_constraint) + + location = self.registry_service.get_package_uri( + package_path_or_name, compatible_version) + + downloaded_path = self.package_loader.download_package( + location, package_path_or_name, compatible_version, + force_download=force_download) + + # Load metadata and initialize PackageService + metadata_path = downloaded_path / "hatch_metadata.json" + with open(metadata_path, 'r') as f: + metadata = json.load(f) + + # Version-agnostic metadata access + self.package_service = PackageService(metadata) + return downloaded_path, metadata +``` + +### Version-Agnostic Dependency Access + +The orchestrator accesses dependencies without knowing the schema version: + +```python +def _build_dependency_graph(self, package_path: Path, metadata: Dict[str, Any]) -> Dict[str, Any]: + """Build dependency graph using version-agnostic PackageService.""" + + # PackageService abstracts schema version differences + all_deps = self.package_service.get_dependencies() + + # Process dependencies by type - works with any schema version + install_plan = { + "dependencies_to_install": {}, + "main_package": { + "path": package_path, + "metadata": metadata + } + } + + # Handle all dependency types uniformly + for dep_type, dependencies in all_deps.items(): + if dependencies: + install_plan["dependencies_to_install"][dep_type] = dependencies + self.logger.info(f"Found {len(dependencies)} {dep_type} dependencies") + + return install_plan +``` + +**Key Benefits:** + +- **Schema Transparency**: Orchestrator doesn't need to know about v1.1.0 vs v1.2.0 vs v1.2.1 differences +- **Unified Processing**: Same code handles separate dependencies (v1.1.0) and unified dependencies (v1.2.0+) +- **Future Compatibility**: New schema versions work without orchestrator changes + +### RegistryService Integration + +The orchestrator uses RegistryService for version-agnostic registry operations: + +```python +def install_dependencies(self, package_path_or_name: str, env_path: Path, + env_name: str, existing_packages: Dict[str, str], + version_constraint: Optional[str] = None, + force_download: bool = False, + auto_approve: bool = False) -> Tuple[bool, List[Dict[str, Any]]]: + """Install dependencies using version-agnostic registry operations.""" + + try: + # Step 1: Resolve package location using RegistryService + package_path, metadata = self._resolve_package_location( + package_path_or_name, version_constraint, force_download) + + # Step 2: Check package existence without schema awareness + if not Path(package_path_or_name).exists(): + if not self.registry_service.package_exists(package_path_or_name): + raise DependencyInstallationError( + f"Package {package_path_or_name} does not exist in registry") + + # Step 3: Build dependency graph using PackageService + install_plan = self._build_dependency_graph(package_path, metadata) + + # Step 4: Execute installation plan + installed_packages = self._execute_install_plan(install_plan, env_path, env_name) + + return True, installed_packages + + except Exception as e: + self.logger.error(f"Dependency installation failed: {e}") + raise DependencyInstallationError(f"Installation failed: {e}") from e +``` + +## Environment Manager Integration + +### RegistryService Initialization + +The Environment Manager initializes RegistryService for version-agnostic registry access: + +```python +from hatch_validator.registry.registry_service import RegistryService + +class HatchEnvironmentManager: + def __init__(self, cache_dir: Path = None, cache_ttl: int = 3600, + simulation_mode: bool = False, + local_registry_cache_path: Optional[Path] = None): + """Initialize environment manager with registry service.""" + + # Initialize registry retriever and get registry data + self.retriever = RegistryRetriever( + cache_ttl=cache_ttl, + local_cache_dir=cache_dir, + simulation_mode=simulation_mode, + local_registry_cache_path=local_registry_cache_path + ) + self.registry_data = self.retriever.get_registry() + + # Initialize RegistryService with automatic schema detection + self.registry_service = RegistryService(self.registry_data) + + # Initialize dependency orchestrator with registry service + self.dependency_orchestrator = DependencyInstallerOrchestrator( + package_loader=self.package_loader, + registry_service=self.registry_service, + registry_data=self.registry_data + ) +``` + +### Registry Data Refresh + +The environment manager handles registry updates transparently: + +```python +def refresh_registry_data(self, force_refresh: bool = False) -> None: + """Refresh registry data and update services.""" + + self.logger.info("Refreshing registry data...") + try: + # Get updated registry data + self.registry_data = self.retriever.get_registry(force_refresh=force_refresh) + + # Update RegistryService with new data - automatic schema detection + self.registry_service = RegistryService(self.registry_data) + + # Update orchestrator with new registry service + self.dependency_orchestrator.registry_service = self.registry_service + self.dependency_orchestrator.registry_data = self.registry_data + + self.logger.info("Registry data refreshed successfully") + except Exception as e: + self.logger.error(f"Failed to refresh registry data: {e}") + raise +``` + +### Package Installation Integration + +The environment manager uses the dependency orchestrator for package installation: + +```python +def install_package(self, package_path_or_name: str, env_name: str, + version_constraint: Optional[str] = None, + force_download: bool = False, + auto_approve: bool = False) -> bool: + """Install package using version-agnostic services.""" + + try: + env_path = self.get_environment_path(env_name) + existing_packages = self.get_installed_packages(env_name) + + # Use dependency orchestrator with version-agnostic services + success, installed_packages = self.dependency_orchestrator.install_dependencies( + package_path_or_name=package_path_or_name, + env_path=env_path, + env_name=env_name, + existing_packages=existing_packages, + version_constraint=version_constraint, + force_download=force_download, + auto_approve=auto_approve + ) + + if success: + self._save_environments() + self.logger.info(f"Successfully installed package in environment {env_name}") + + return success + + except Exception as e: + self.logger.error(f"Package installation failed: {e}") + return False +``` + +## CLI Integration Patterns + +### HatchPackageValidator Usage + +The CLI uses HatchPackageValidator for comprehensive package validation: + +```python +from hatch_validator import HatchPackageValidator + +def main(): + """Main CLI entry point with validation integration.""" + + # Initialize environment manager for registry data + env_manager = HatchEnvironmentManager() + + # Parse command line arguments + args = parse_arguments() + + if args.command == "validate": + package_path = Path(args.package_dir).resolve() + + # Create validator with registry data from environment manager + validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True, + registry_data=env_manager.registry_data # Version-agnostic registry data + ) + + # Validate package - automatic schema version detection + is_valid, validation_results = validator.validate_package(package_path) + + if is_valid: + print(f"Package validation SUCCESSFUL: {package_path}") + return 0 + else: + print(f"Package validation FAILED: {package_path}") + + # Print detailed validation results + if validation_results and isinstance(validation_results, dict): + for category, result in validation_results.items(): + if category not in ['valid', 'metadata'] and isinstance(result, dict): + if not result.get('valid', True) and result.get('errors'): + print(f"\n{category.replace('_', ' ').title()} errors:") + for error in result['errors']: + print(f" - {error}") + + return 1 +``` + +### Validation Error Handling + +The CLI implements comprehensive error handling for validation results: + +```python +def handle_validation_results(validation_results: Dict[str, Any]) -> int: + """Handle and display validation results.""" + + if validation_results.get('valid', False): + print("✓ Package validation successful") + return 0 + + print("✗ Package validation failed") + + # Handle schema validation errors + if not validation_results.get('metadata_schema', {}).get('valid', True): + print("\nSchema Validation Errors:") + for error in validation_results['metadata_schema'].get('errors', []): + print(f" - {error}") + + # Handle entry point validation errors + if not validation_results.get('entry_point', {}).get('valid', True): + print("\nEntry Point Validation Errors:") + for error in validation_results['entry_point'].get('errors', []): + print(f" - {error}") + + # Handle dependency validation errors + if not validation_results.get('dependencies', {}).get('valid', True): + print("\nDependency Validation Errors:") + for error in validation_results['dependencies'].get('errors', []): + print(f" - {error}") + + # Handle tools validation errors + if not validation_results.get('tools', {}).get('valid', True): + print("\nTools Validation Errors:") + for error in validation_results['tools'].get('errors', []): + print(f" - {error}") + + return 1 +``` + +## Best Practices from Production Usage + +### Service Initialization Patterns + +**Centralized Service Management:** + +```python +class ServiceManager: + """Centralized management of Hatch-Validator services.""" + + def __init__(self, registry_data: Dict[str, Any]): + self.registry_service = RegistryService(registry_data) + self.package_service = None # Initialized per package + + def load_package(self, metadata: Dict[str, Any]) -> PackageService: + """Load package with version-agnostic service.""" + self.package_service = PackageService(metadata) + return self.package_service + + def validate_package(self, package_path: Path) -> Tuple[bool, Dict[str, Any]]: + """Validate package using integrated services.""" + validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True, + registry_data=self.registry_service._registry_data + ) + return validator.validate_package(package_path) +``` + +### Error Handling Patterns + +**Graceful Degradation:** + +```python +def safe_package_operation(package_path: Path, registry_data: Dict[str, Any]) -> bool: + """Perform package operations with graceful error handling.""" + + try: + # Primary operation with full services + service = PackageService() + with open(package_path / "hatch_metadata.json", 'r') as f: + metadata = json.load(f) + + service.load_metadata(metadata) + dependencies = service.get_dependencies() + return True + + except ValueError as e: + # Handle schema version issues + logger.warning(f"Schema version issue: {e}") + return False + + except Exception as e: + # Handle other errors gracefully + logger.error(f"Package operation failed: {e}") + return False +``` + +### Performance Optimization Patterns + +**Service Reuse:** + +```python +class OptimizedPackageProcessor: + """Optimized package processing with service reuse.""" + + def __init__(self, registry_data: Dict[str, Any]): + # Initialize registry service once + self.registry_service = RegistryService(registry_data) + + # Initialize validator once + self.validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True, + registry_data=registry_data + ) + + def process_packages(self, package_paths: List[Path]) -> List[Dict[str, Any]]: + """Process multiple packages efficiently.""" + results = [] + + for package_path in package_paths: + # Reuse validator instance + is_valid, validation_results = self.validator.validate_package(package_path) + + # Create new PackageService per package + with open(package_path / "hatch_metadata.json", 'r') as f: + metadata = json.load(f) + + package_service = PackageService(metadata) + dependencies = package_service.get_dependencies() + + results.append({ + 'path': package_path, + 'valid': is_valid, + 'dependencies': dependencies, + 'validation_results': validation_results + }) + + return results +``` + +## Integration Benefits Demonstrated + +### Schema Version Transparency + +All production integrations demonstrate that consumer code remains stable across schema versions: + +- **Dependency Orchestrator**: Same code processes v1.1.0 (separate dependencies) and v1.2.0+ (unified dependencies) +- **Environment Manager**: Registry operations work regardless of registry schema version +- **CLI Validation**: Validation commands work with any package schema version + +### Reduced Complexity + +Production code focuses on business logic rather than schema management: + +- **No Version Checks**: No conditional logic based on schema versions +- **Consistent APIs**: Same method signatures across all integrations +- **Unified Error Handling**: Consistent error patterns across schema versions + +### Future Compatibility + +All integrations automatically support new schema versions: + +- **Automatic Discovery**: New schema versions are detected and handled automatically +- **Delegation Benefits**: New functionality is added without breaking existing code +- **Zero Migration**: No code changes required when new schema versions are released + +## Related Documentation + +- [PackageService Guide](../data_access/PackageService.md) - Detailed PackageService API +- [RegistryService Guide](../data_access/RegistryService.md) - Detailed RegistryService API +- [Version-Agnostic Access Concepts](../data_access/VersionAgnosticAccess.md) - Core principles +- [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) - Architectural foundation diff --git a/docs/articles/users/validation/PackageValidation.md b/docs/articles/users/validation/PackageValidation.md new file mode 100644 index 0000000..dee2855 --- /dev/null +++ b/docs/articles/users/validation/PackageValidation.md @@ -0,0 +1,249 @@ +# Package Validation Guide + +This article is about: +- Package validation workflow concepts using HatchPackageValidator +- Validation result interpretation and error handling +- Integration with the Chain of Responsibility validation system +- Cross-reference to real-world CLI usage examples + +## Overview + +Package validation in Hatch-Validator uses the Chain of Responsibility pattern to provide comprehensive validation across different schema versions. The HatchPackageValidator class serves as the main entry point for validation operations, automatically handling schema version detection and delegation. + +## Validation Workflow Concepts + +### Automatic Schema Version Detection + +The HatchPackageValidator automatically detects the package schema version and creates the appropriate validator chain: + +```python +from hatch_validator import HatchPackageValidator +from pathlib import Path + +# Validator automatically detects and handles schema versions +validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True +) + +# Validation works regardless of package schema version +package_path = Path("./my-package") +is_valid, results = validator.validate_package(package_path) +``` + +### Chain of Responsibility Validation + +The validation process follows these steps: + +1. **Metadata Loading**: Load package metadata from hatch_metadata.json +2. **Schema Detection**: Extract `package_schema_version` from metadata +3. **Chain Creation**: Create validator chain starting from detected version +4. **Validation Execution**: Execute validation through the chain with delegation +5. **Result Aggregation**: Collect and return comprehensive validation results + +### Validation Categories + +The validator performs comprehensive validation across multiple categories: + +- **Metadata Schema**: Validates metadata structure against schema requirements +- **Entry Points**: Validates entry point configuration and file existence +- **Tools**: Validates tools configuration and requirements +- **Dependencies**: Validates dependency structure and registry availability + +## Validation Result Interpretation + +### Result Structure + +Validation results are returned as a tuple containing: + +```python +is_valid, results = validator.validate_package(package_path) + +# is_valid: bool - Overall validation success +# results: Dict[str, Any] - Detailed validation results +``` + +### Result Dictionary Format + +The results dictionary contains category-specific validation information: + +```python +{ + 'valid': bool, # Overall validation status + 'metadata_schema': { + 'valid': bool, # Schema validation status + 'errors': List[str] # Schema validation errors + }, + 'entry_point': { + 'valid': bool, # Entry point validation status + 'errors': List[str] # Entry point validation errors + }, + 'tools': { + 'valid': bool, # Tools validation status + 'errors': List[str] # Tools validation errors + }, + 'dependencies': { + 'valid': bool, # Dependency validation status + 'errors': List[str] # Dependency validation errors + }, + 'metadata': Dict[str, Any] # Loaded package metadata +} +``` + +### Error Handling Patterns + +#### Basic Error Handling + +```python +is_valid, results = validator.validate_package(package_path) + +if not is_valid: + print("Package validation failed:") + for category, result in results.items(): + if category not in ['valid', 'metadata'] and isinstance(result, dict): + if not result.get('valid', True) and result.get('errors'): + print(f"{category.replace('_', ' ').title()} errors:") + for error in result['errors']: + print(f" - {error}") +``` + +#### Category-Specific Error Handling + +```python +if not results['metadata_schema']['valid']: + print("Schema validation failed:") + for error in results['metadata_schema']['errors']: + print(f" Schema error: {error}") + +if not results['dependencies']['valid']: + print("Dependency validation failed:") + for error in results['dependencies']['errors']: + print(f" Dependency error: {error}") +``` + +## Validator Configuration + +### Constructor Parameters + +```python +HatchPackageValidator( + version: str = "latest", + allow_local_dependencies: bool = True, + force_schema_update: bool = False, + registry_data: Optional[Dict] = None +) +``` + +**Parameters:** +- `version`: Schema version to target ("latest" for newest available) +- `allow_local_dependencies`: Whether to allow local dependency validation +- `force_schema_update`: Whether to force schema cache updates +- `registry_data`: Registry data for dependency validation + +### Registry Integration + +For dependency validation against registries: + +```python +# Validator with registry data for comprehensive dependency validation +validator = HatchPackageValidator( + version="latest", + allow_local_dependencies=True, + registry_data=registry_data # From environment manager +) +``` + +## Schema Version Handling + +### Version-Specific Validation + +The validator automatically handles different schema versions through delegation: + +**v1.1.0 Validation:** +- Basic entry point validation +- Separate hatch and python dependency validation +- Standard tools validation + +**v1.2.0 Validation:** +- Enhanced dependency structure validation +- Support for hatch, python, system, and docker dependencies +- Delegates entry point and tools validation to v1.1.0 + +**v1.2.1 Validation:** +- Dual entry point validation (mcp_server and hatch_mcp_server) +- Enhanced tools validation +- Delegates dependency validation to v1.2.0 + +### Transparent Version Handling + +Consumer code remains the same regardless of schema version: + +```python +# This validation code works with any supported schema version +validator = HatchPackageValidator() +is_valid, results = validator.validate_package(package_path) +``` + +## Integration with Chain of Responsibility + +### Validator Chain Construction + +When validating a package, the system: + +1. **Loads Metadata**: Reads hatch_metadata.json from package directory +2. **Detects Version**: Extracts `package_schema_version` from metadata +3. **Creates Chain**: Uses ValidatorFactory to create validator chain +4. **Links Validators**: Each validator points to the next older version +5. **Executes Validation**: Runs validation through the chain with delegation + +### Delegation Flow Example + +For a v1.2.1 package validation: + +1. **v1.2.1 Validator**: Validates dual entry points and tools → delegates dependencies to v1.2.0 +2. **v1.2.0 Validator**: Validates unified dependency structure → delegates entry points to v1.1.0 +3. **v1.1.0 Validator**: Provides base validation for delegated concerns +4. **Result Aggregation**: Combines validation results from all validators + +## Validation Context + +### Context Management + +The validation system uses ValidationContext to manage state and resources: + +- **Registry Data**: Available registry information for dependency validation +- **Local Dependencies**: Configuration for local dependency handling +- **Validation State**: Tracking validation progress and results + +### Resource Integration + +The validator integrates with external resources: + +- **Schema Cache**: Cached schema definitions for validation +- **Registry Service**: Registry data for dependency existence validation +- **File System**: Package files and metadata validation + +## Performance Considerations + +### Efficient Validation + +- **Lazy Loading**: Validators are created only when needed +- **Chain Optimization**: Validation stops at the first capable validator +- **Resource Caching**: Schema and registry data are cached for reuse + +### Validation Optimization + +- **Early Termination**: Validation can stop on first critical error +- **Parallel Validation**: Independent validation categories can run concurrently +- **Resource Reuse**: Validator instances can be reused for multiple packages + +## Real-World Usage Examples + +For comprehensive examples of package validation in production environments, including CLI integration and automated validation workflows, see [Programmatic Usage](../integration/ProgrammaticUsage.md). + +## Related Documentation + +- [Schema Management](SchemaManagement.md) - Schema fetching and version handling +- [Programmatic Usage](../integration/ProgrammaticUsage.md) - Real-world validation examples +- [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) - Validation architecture +- [Component Types](../../devs/architecture/ComponentTypes.md) - How validators work with other components diff --git a/docs/articles/users/validation/SchemaManagement.md b/docs/articles/users/validation/SchemaManagement.md new file mode 100644 index 0000000..624e188 --- /dev/null +++ b/docs/articles/users/validation/SchemaManagement.md @@ -0,0 +1,302 @@ +# Schema Management + +This article is about: +- Automatic schema version detection and resolution +- Schema fetching and caching mechanisms through SchemaFetcher and SchemaCache +- Integration with Hatch-Schemas repository for schema updates +- Schema evolution handling without breaking consumer code + +## Overview + +Hatch-Validator's schema management system provides automatic schema fetching, caching, and version resolution. The system integrates with the external Hatch-Schemas repository to ensure validators always have access to the latest schema definitions while maintaining local caches for offline operation. + +## Schema Management Components + +### SchemaRetriever + +The SchemaRetriever class serves as the main interface for schema operations, coordinating between fetching and caching: + +```python +from hatch_validator.schemas.schemas_retriever import SchemaRetriever + +# Initialize with default cache directory +retriever = SchemaRetriever() + +# Get latest package schema +package_schema = retriever.get_schema("package", "latest") + +# Get specific version +package_schema_v120 = retriever.get_schema("package", "v1.2.0") +``` + +### SchemaFetcher + +The SchemaFetcher class handles network operations to retrieve schemas from the Hatch-Schemas GitHub repository: + +**Key Features:** +- Discovers latest schema versions via GitHub API +- Downloads schemas directly from GitHub releases +- Handles network errors and timeouts gracefully + +**Schema Types Supported:** +- **Package Schemas**: `hatch_pkg_metadata_schema.json` files +- **Registry Schemas**: `hatch_all_pkg_metadata_schema.json` files + +### SchemaCache + +The SchemaCache class manages local schema storage and retrieval: + +**Key Features:** +- Caches schemas locally for offline use +- Manages schema versioning and updates +- Provides cache freshness validation +- Supports version-specific schema storage + +**Cache Location:** +- Default: `~/.hatch/schemas/` +- Configurable through constructor parameter + +## Automatic Schema Version Detection + +### Version Resolution Process + +The schema management system automatically resolves schema versions: + +1. **Latest Version Discovery**: Query GitHub API for latest schema releases +2. **Version Mapping**: Map schema types to their latest available versions +3. **Cache Validation**: Check if cached schemas are fresh and up-to-date +4. **Automatic Updates**: Download new schemas when cache is stale or missing + +### Schema Version Handling + +```python +from hatch_validator.schemas.schemas_retriever import get_package_schema, get_registry_schema + +# Get latest package schema (automatically resolves to newest version) +latest_package_schema = get_package_schema("latest") + +# Get specific version +v121_package_schema = get_package_schema("v1.2.1") + +# Force update check +fresh_schema = get_package_schema("latest", force_update=True) +``` + +## Integration with Hatch-Schemas Repository + +### GitHub Integration + +The schema management system integrates with the Hatch-Schemas repository: + +**Repository Structure:** +- **Package Schemas**: Tagged with `schemas-package-` prefix (e.g., `schemas-package-v1.2.1`) +- **Registry Schemas**: Tagged with `schemas-registry-` prefix (e.g., `schemas-registry-v1.1.0`) + +**API Endpoints:** +- **Releases API**: `https://api.github.com/repos/CrackingShells/Hatch-Schemas/releases` +- **Download URLs**: `https://github.com/CrackingShells/Hatch-Schemas/releases/download/{tag}/{filename}` + +### Automatic Schema Discovery + +The system automatically discovers available schema versions: + +```python +from hatch_validator.schemas.schema_fetcher import SchemaFetcher + +fetcher = SchemaFetcher() + +# Get latest schema information from GitHub +schema_info = fetcher.get_latest_schema_info() + +# Returns structure like: +# { +# "latest_package_version": "v1.2.1", +# "latest_registry_version": "v1.1.0", +# "package": { +# "version": "v1.2.1", +# "url": "https://github.com/.../schemas-package-v1.2.1/hatch_pkg_metadata_schema.json" +# }, +# "registry": { +# "version": "v1.1.0", +# "url": "https://github.com/.../schemas-registry-v1.1.0/hatch_all_pkg_metadata_schema.json" +# } +# } +``` + +## Schema Caching and Updates + +### Cache Management + +The schema cache provides efficient local storage: + +**Cache Structure:** +``` +~/.hatch/schemas/ +├── schema_info.json # Cache metadata and version info +├── hatch_pkg_metadata_schema.json # Latest package schema +├── hatch_all_pkg_metadata_schema.json # Latest registry schema +└── v1.2.1/ # Version-specific schemas + ├── hatch_pkg_metadata_schema.json + └── hatch_all_pkg_metadata_schema.json +``` + +### Cache Freshness + +The system automatically manages cache freshness: + +```python +from hatch_validator.schemas.schema_cache import SchemaCache + +cache = SchemaCache() + +# Check if cache is fresh (default: 24 hours) +is_fresh = cache.is_fresh() + +# Check with custom TTL (12 hours) +is_fresh = cache.is_fresh(max_age=43200) +``` + +**Default Cache TTL**: 24 hours (86400 seconds) + +### Automatic Updates + +Schema updates happen automatically: + +1. **Cache Check**: Verify cache freshness on schema requests +2. **Update Check**: Query GitHub for latest schema versions if cache is stale +3. **Download**: Fetch new schemas if newer versions are available +4. **Cache Update**: Store new schemas locally with version information + +## Schema Evolution Handling + +### Backward Compatibility + +The schema management system ensures backward compatibility: + +**Version-Specific Storage:** +- Schemas are stored both in version-specific directories and as latest versions +- Older schema versions remain accessible for legacy package validation +- Version resolution handles both `v1.2.1` and `1.2.1` format variations + +**Graceful Degradation:** +- If latest schema is unavailable, system falls back to cached versions +- Network failures don't prevent validation with cached schemas +- Missing schemas trigger automatic download attempts + +### Schema Version Migration + +When new schema versions are released: + +1. **Automatic Discovery**: System detects new schema versions from GitHub +2. **Incremental Download**: Only new or updated schemas are downloaded +3. **Version Coexistence**: Multiple schema versions can coexist in cache +4. **Transparent Updates**: Consumer code continues working without changes + +## Error Handling and Resilience + +### Network Error Handling + +The schema management system handles network issues gracefully: + +```python +# Network errors are logged but don't prevent operation +try: + schema = get_package_schema("latest", force_update=True) +except Exception as e: + # Falls back to cached schema if available + schema = get_package_schema("latest", force_update=False) +``` + +### Cache Corruption Recovery + +The system recovers from cache corruption: + +- **Validation**: JSON parsing errors trigger cache invalidation +- **Redownload**: Corrupted schemas are automatically redownloaded +- **Fallback**: System attempts multiple schema sources before failing + +### Offline Operation + +Schema management supports offline operation: + +- **Local Cache**: Schemas are cached locally for offline use +- **Graceful Degradation**: Network unavailability doesn't prevent validation +- **Cache Persistence**: Schemas remain available across application restarts + +## Configuration and Customization + +### Custom Cache Directory + +```python +from pathlib import Path +from hatch_validator.schemas.schemas_retriever import SchemaRetriever + +# Use custom cache directory +custom_cache = Path("/custom/cache/path") +retriever = SchemaRetriever(cache_dir=custom_cache) +``` + +### Force Updates + +```python +# Force schema update regardless of cache freshness +schema = get_package_schema("latest", force_update=True) + +# Force update for specific version +schema = get_package_schema("v1.2.1", force_update=True) +``` + +### Cache TTL Configuration + +```python +from hatch_validator.schemas.schema_cache import SchemaCache + +# Custom cache TTL (6 hours) +cache = SchemaCache() +is_fresh = cache.is_fresh(max_age=21600) +``` + +## Integration with Validation System + +### Automatic Schema Loading + +The validation system automatically loads appropriate schemas: + +```python +from hatch_validator import HatchPackageValidator + +# Validator automatically loads latest schemas +validator = HatchPackageValidator( + version="latest", + force_schema_update=True # Force schema cache update +) +``` + +### Schema Version Coordination + +The schema management system coordinates with the Chain of Responsibility validation: + +1. **Schema Detection**: Validator detects package schema version from metadata +2. **Schema Loading**: Appropriate schema is loaded from cache or downloaded +3. **Validation**: Package is validated against the correct schema version +4. **Chain Delegation**: Validation delegates through version-appropriate validators + +## Performance Considerations + +### Efficient Caching + +- **Lazy Loading**: Schemas are loaded only when needed +- **Version Caching**: Multiple schema versions cached simultaneously +- **Network Optimization**: Only updated schemas are downloaded + +### Background Updates + +- **Asynchronous Updates**: Schema updates can happen in background +- **Cache Warming**: Schemas can be pre-loaded for better performance +- **Batch Operations**: Multiple schemas updated in single network operation + +## Related Documentation + +- [Package Validation Guide](PackageValidation.md) - How validation uses schema management +- [Chain of Responsibility Pattern](../../devs/architecture/ChainOfResponsibilityPattern.md) - Validation architecture +- [Schema Integration](../../devs/architecture/SchemaIntegration.md) - Technical integration details diff --git a/docs/resources/diagrams/chain_of_responsibility_overview.puml b/docs/resources/diagrams/chain_of_responsibility_overview.puml new file mode 100644 index 0000000..aa6e02a --- /dev/null +++ b/docs/resources/diagrams/chain_of_responsibility_overview.puml @@ -0,0 +1,238 @@ +@startuml Chain of Responsibility Overview +!theme plain +skinparam backgroundColor white +skinparam classBackgroundColor white +skinparam classBorderColor black +skinparam arrowColor black + +title Chain of Responsibility + Strategy Pattern - Dual Architecture + +package "Strategy Interfaces" { + abstract class ValidationStrategy { + <> + } + + abstract class DependencyValidationStrategy { + + {abstract} validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + abstract class EntryPointValidationStrategy { + + {abstract} validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + abstract class ToolsValidationStrategy { + + {abstract} validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + abstract class SchemaValidationStrategy { + + {abstract} validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } +} + +package "Abstract Base Classes" { + abstract class ComponentBase { + - next_component: ComponentBase + + set_next(component: ComponentBase): ComponentBase + + {abstract} can_handle(version_or_data): bool + + operation(data): Any + } +} + +package "Validators" { + abstract class Validator { + - next_validator: Validator + + {abstract} can_handle(schema_version: str): bool + + {abstract} validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V121Validator { + - schema_strategy: SchemaValidation + - entry_point_strategy: EntryPointValidation + - tools_strategy: ToolsValidation + + can_handle(schema_version: str): bool + + validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V120Validator { + - schema_strategy: SchemaValidation + - dependency_strategy: DependencyValidation + + can_handle(schema_version: str): bool + + validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V110Validator { + - schema_strategy: SchemaValidation + - dependency_strategy: DependencyValidation + - entry_point_strategy: EntryPointValidation + - tools_strategy: ToolsValidation + + can_handle(schema_version: str): bool + + validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } +} + +package "Package Accessors" { + abstract class HatchPkgAccessorBase { + - next_accessor: HatchPkgAccessorBase + + {abstract} can_handle(schema_version: str): bool + + get_dependencies(metadata: Dict): Dict + + get_entry_points(metadata: Dict): Dict + + get_name(metadata: Dict): str + } + + class V121PackageAccessor { + + can_handle(schema_version: str): bool + + get_entry_points(metadata: Dict): Dict + + get_dependencies(metadata: Dict): Dict + } + + class V120PackageAccessor { + + can_handle(schema_version: str): bool + + get_dependencies(metadata: Dict): Dict + + get_name(metadata: Dict): str + } + + class V110PackageAccessor { + + can_handle(schema_version: str): bool + + get_dependencies(metadata: Dict): Dict + + get_entry_points(metadata: Dict): Dict + + get_name(metadata: Dict): str + + get_all_fields(metadata: Dict): Dict + } +} + +package "Registry Accessors" { + abstract class RegistryAccessorBase { + - _successor: RegistryAccessorBase + + {abstract} can_handle(registry_data: Dict): bool + + handle_request(registry_data: Dict): RegistryAccessorBase + + package_exists(registry_data: Dict, package_name: str): bool + + find_compatible_version(registry_data: Dict, package_name: str, constraint: str): str + } + + class V110RegistryAccessor { + + can_handle(registry_data: Dict): bool + + package_exists(registry_data: Dict, package_name: str): bool + + find_compatible_version(registry_data: Dict, package_name: str, constraint: str): str + + get_package_uri(registry_data: Dict, package_name: str, version: str): str + } +} + +package "Factory Classes" { + class ValidatorFactory { + - {static} _validator_registry: Dict[str, Type[Validator]] + - {static} _version_order: List[str] + + {static} create_validator_chain(target_version: str): Validator + + {static} register_validator(version: str, validator_class: Type[Validator]): void + } + + class HatchPkgAccessorFactory { + - {static} _accessor_registry: Dict[str, Type[HatchPkgAccessorBase]] + - {static} _version_order: List[str] + + {static} create_accessor_chain(target_version: str): HatchPkgAccessorBase + + {static} register_accessor(version: str, accessor_class: Type[HatchPkgAccessorBase]): void + } + + class RegistryAccessorFactory { + - {static} _accessor_registry: Dict[str, Type[RegistryAccessorBase]] + + {static} create_accessor_for_data(registry_data: Dict): RegistryAccessorBase + + {static} register_accessor(version: str, accessor_class: Type[RegistryAccessorBase]): void + } +} + +' Strategy interface inheritance +ValidationStrategy <|-- DependencyValidationStrategy +ValidationStrategy <|-- EntryPointValidationStrategy +ValidationStrategy <|-- ToolsValidationStrategy +ValidationStrategy <|-- SchemaValidationStrategy + +' Component inheritance relationships +ComponentBase <|-- Validator +ComponentBase <|-- HatchPkgAccessorBase +ComponentBase <|-- RegistryAccessorBase + +Validator <|-- V121Validator +Validator <|-- V120Validator +Validator <|-- V110Validator + +HatchPkgAccessorBase <|-- V121PackageAccessor +HatchPkgAccessorBase <|-- V120PackageAccessor +HatchPkgAccessorBase <|-- V110PackageAccessor + +RegistryAccessorBase <|-- V110RegistryAccessor + +' Strategy composition relationships (solid lines) +V121Validator --> SchemaValidationStrategy : composes +V121Validator --> EntryPointValidationStrategy : composes +V121Validator --> ToolsValidationStrategy : composes + +V120Validator --> SchemaValidationStrategy : composes +V120Validator --> DependencyValidationStrategy : composes + +V110Validator --> SchemaValidationStrategy : composes +V110Validator --> DependencyValidationStrategy : composes +V110Validator --> EntryPointValidationStrategy : composes +V110Validator --> ToolsValidationStrategy : composes + +' Chain delegation relationships (dashed lines) +V121Validator ..> V120Validator : delegates dependencies +V120Validator ..> V110Validator : delegates entry_point, tools + +V121PackageAccessor --> V120PackageAccessor : delegates to +V120PackageAccessor --> V110PackageAccessor : delegates to + +' Factory relationships +ValidatorFactory ..> V121Validator : creates +ValidatorFactory ..> V120Validator : creates +ValidatorFactory ..> V110Validator : creates + +HatchPkgAccessorFactory ..> V121PackageAccessor : creates +HatchPkgAccessorFactory ..> V120PackageAccessor : creates +HatchPkgAccessorFactory ..> V110PackageAccessor : creates + +RegistryAccessorFactory ..> V110RegistryAccessor : creates + +note top of ComponentBase : Universal base pattern\nimplemented by all\nthree component types + +note top of ValidationStrategy : Strategy Pattern interfaces\nencapsulate validation algorithms\nfor specific concerns + +note right of V121Validator : Dual Pattern Architecture:\n• Composes strategies for changed concerns\n• Delegates unchanged concerns via chain\n• Handles v1.2.1 schema features + +note right of V120Validator : Dual Pattern Architecture:\n• Composes strategies for changed concerns\n• Delegates unchanged concerns via chain\n• Handles v1.2.0 unified dependencies + +note right of V110Validator : Terminal validator\nImplements all strategies\nNo delegation needed + +note right of V121PackageAccessor : Handles v1.2.1 dual entry points\nDelegates dependencies to v1.2.0 + +note right of V120PackageAccessor : Handles v1.2.0 unified dependencies\nDelegates basic fields to v1.1.0 + +note right of V110PackageAccessor : Terminal accessor\nImplements all metadata access + +note right of V110RegistryAccessor : Terminal registry accessor\nHandles CrackingShells registry format + +note bottom of ValidatorFactory : Automatically discovers\nand links validators\nfrom newest to oldest + +note as DualPattern +**Dual Pattern Architecture** +• Strategy Pattern: Encapsulates validation algorithms +• Chain of Responsibility: Enables version delegation +• Composition: Changed concerns use strategies +• Delegation: Unchanged concerns use chain +end note + +@enduml diff --git a/docs/resources/diagrams/three_component_architecture.puml b/docs/resources/diagrams/three_component_architecture.puml new file mode 100644 index 0000000..4c5caf3 --- /dev/null +++ b/docs/resources/diagrams/three_component_architecture.puml @@ -0,0 +1,217 @@ +@startuml Three Component Architecture +!theme plain +skinparam backgroundColor white +skinparam componentBackgroundColor white +skinparam componentBorderColor black +skinparam arrowColor black + +title Hatch-Validator Dual-Pattern Architecture + +package "Service Layer" { + component [PackageService] as PS { + Version-agnostic package\nmetadata access + } + + component [RegistryService] as RS { + Version-agnostic registry\ndata access + } + + component [HatchPackageValidator] as HPV { + Comprehensive package\nvalidation orchestration + } +} + +package "Strategy Layer" { + package "Validation Strategies" { + component [SchemaValidation] as SV { + Schema structure\nvalidation + } + + component [DependencyValidation] as DV { + Dependency structure\nvalidation + } + + component [EntryPointValidation] as EPV { + Entry point\nvalidation + } + + component [ToolsValidation] as TV { + Tools configuration\nvalidation + } + } +} + +package "Component Chains" { + package "Package Accessor Chain" { + component [V121PackageAccessor] as PA121 + component [V120PackageAccessor] as PA120 + component [V110PackageAccessor] as PA110 + + PA121 --> PA120 : delegates unchanged\nconcerns + PA120 --> PA110 : delegates unchanged\nconcerns + } + + package "Validator Chain" { + component [V121Validator] as V121 { + Composes: Schema, EntryPoint, Tools\nDelegates: Dependencies + } + component [V120Validator] as V120 { + Composes: Schema, Dependencies\nDelegates: EntryPoint, Tools + } + component [V110Validator] as V110 { + Composes: All strategies\nNo delegation + } + + V121 ..> V120 : delegates dependencies + V120 ..> V110 : delegates entry_point, tools + } + + package "Registry Accessor Chain" { + component [V110RegistryAccessor] as RA110 + } +} + +package "Factory Layer" { + component [HatchPkgAccessorFactory] as PAF { + Creates package\naccessor chains + } + + component [ValidatorFactory] as VF { + Creates validator\nchains + } + + component [RegistryAccessorFactory] as RAF { + Creates registry\naccessor chains + } +} + +package "Schema Management" { + component [SchemaRetriever] as SR { + Coordinates schema\nfetching and caching + } + + component [SchemaFetcher] as SF { + Downloads schemas\nfrom GitHub + } + + component [SchemaCache] as SC { + Local schema\nstorage and retrieval + } + + SR --> SF : fetches schemas + SR --> SC : caches schemas +} + +package "External Dependencies" { + database "Hatch-Schemas\nRepository" as HSR { + GitHub repository with\nversioned schema definitions + } + + database "Package\nMetadata" as PM { + hatch_metadata.json\nfiles with schema versions + } + + database "Registry\nData" as RD { + CrackingShells Package\nRegistry format + } +} + +package "Consumer Applications" { + component [Dependency Installation\nOrchestrator] as DIO { + Uses PackageService and\nRegistryService for\ndependency resolution + } + + component [Environment\nManager] as EM { + Uses RegistryService and\nHatchPackageValidator for\nenvironment management + } + + component [CLI Tools] as CLI { + Uses HatchPackageValidator\nfor package validation\ncommands + } +} + +' Strategy composition relationships +V121 --> SV : composes +V121 --> EPV : composes +V121 --> TV : composes + +V120 --> SV : composes +V120 --> DV : composes + +V110 --> SV : composes +V110 --> DV : composes +V110 --> EPV : composes +V110 --> TV : composes + +' Service Layer to Component Chains +PS --> PAF : creates chains +RS --> RAF : creates chains +HPV --> VF : creates chains +HPV --> RS : uses for validation + +' Factory to Component relationships +PAF ..> PA121 : creates and links +PAF ..> PA120 : creates and links +PAF ..> PA110 : creates and links + +VF ..> V121 : creates and links +VF ..> V120 : creates and links +VF ..> V110 : creates and links + +RAF ..> RA110 : creates + +' Schema Management relationships +V121 --> SR : loads schemas +V120 --> SR : loads schemas +V110 --> SR : loads schemas + +SF --> HSR : downloads from +SC --> PM : validates against + +' External Data relationships +PA121 --> PM : accesses +PA120 --> PM : accesses +PA110 --> PM : accesses + +RA110 --> RD : accesses + +' Consumer relationships +DIO --> PS : uses +DIO --> RS : uses + +EM --> RS : uses +EM --> HPV : uses + +CLI --> HPV : uses + +note top of PS : Provides unified interface\nto package metadata\nregardless of schema version + +note top of RS : Provides unified interface\nto registry data\nregardless of registry format + +note top of HPV : Orchestrates validation\nacross all component types\nwith automatic schema detection + +note top of SV : Strategy Layer:\nEncapsulates validation algorithms\nfor specific concerns + +note right of PA121 : Handles v1.2.1 features:\n- Dual entry points\n- Delegates dependencies + +note right of PA120 : Handles v1.2.0 features:\n- Unified dependencies\n- Delegates basic fields + +note right of PA110 : Terminal accessor:\n- All basic metadata\n- Separate dependencies + +note left of V121 : Dual Pattern Architecture:\n• Composes: Schema, EntryPoint, Tools\n• Delegates: Dependencies to V120\n• Handles v1.2.1 features + +note left of V120 : Dual Pattern Architecture:\n• Composes: Schema, Dependencies\n• Delegates: EntryPoint, Tools to V110\n• Handles v1.2.0 features + +note left of V110 : Terminal validator:\n• Composes all strategies\n• No delegation needed\n• Complete validation logic + +note bottom of RA110 : Handles CrackingShells\nregistry format:\n- Repository structure\n- Package existence\n- Version resolution + +note top of SR : Automatic schema management:\n- Version detection\n- Cache freshness\n- GitHub integration + +note bottom of DIO : Real-world usage:\n- Version-agnostic dependency access\n- Registry operations\n- Package resolution + +note bottom of EM : Real-world usage:\n- Registry data refresh\n- Package validation\n- Environment coordination + +note bottom of CLI : Real-world usage:\n- Package validation commands\n- Error reporting\n- Registry integration + +@enduml diff --git a/docs/resources/diagrams/version_agnostic_access.puml b/docs/resources/diagrams/version_agnostic_access.puml new file mode 100644 index 0000000..dcdc2e0 --- /dev/null +++ b/docs/resources/diagrams/version_agnostic_access.puml @@ -0,0 +1,210 @@ +@startuml Version Agnostic Access +!theme plain +skinparam backgroundColor white +skinparam participantBackgroundColor white +skinparam participantBorderColor black +skinparam arrowColor black + +title Version-Agnostic Access & Dual Pattern Validation Flow + +actor "Consumer\nApplication" as Consumer +participant "PackageService" as PS +participant "HatchPkgAccessorFactory" as PAF +participant "V121PackageAccessor" as PA121 +participant "V120PackageAccessor" as PA120 +participant "V110PackageAccessor" as PA110 +participant "RegistryService" as RS +participant "RegistryAccessorFactory" as RAF +participant "V110RegistryAccessor" as RA110 + +== Package Metadata Access (v1.2.1 Package) == + +Consumer -> PS : PackageService(metadata) +note right : metadata contains\npackage_schema_version: "1.2.1" + +PS -> PAF : create_accessor_chain("1.2.1") +PAF -> PA121 : create V121PackageAccessor() +PAF -> PA120 : create V120PackageAccessor() +PAF -> PA110 : create V110PackageAccessor() +PAF -> PA121 : set_next(PA120) +PAF -> PA120 : set_next(PA110) +PAF --> PS : return PA121 (chain head) + +Consumer -> PS : get_dependencies() +PS -> PA121 : get_dependencies(metadata) + +alt v1.2.1 doesn't handle dependencies + PA121 -> PA120 : get_dependencies(metadata) + note right : Delegates to v1.2.0\nfor unified dependencies + PA120 --> PA121 : return unified dependencies +end + +PA121 --> PS : return dependencies +PS --> Consumer : return dependencies +note left : Consumer receives unified\ndependency structure\nwithout knowing schema version + +== Entry Point Access (v1.2.1 Package) == + +Consumer -> PS : get_entry_points() +PS -> PA121 : get_entry_points(metadata) + +alt v1.2.1 handles dual entry points + PA121 -> PA121 : extract mcp_server and hatch_mcp_server + PA121 --> PS : return dual entry points +end + +PS --> Consumer : return entry_points +note left : Consumer receives dual\nentry point configuration\nspecific to v1.2.1 + +== Registry Operations == + +Consumer -> RS : RegistryService(registry_data) +RS -> RAF : create_accessor_for_data(registry_data) +RAF -> RA110 : create V110RegistryAccessor() +RAF --> RS : return RA110 + +Consumer -> RS : package_exists("example-package") +RS -> RA110 : package_exists(registry_data, "example-package") +RA110 -> RA110 : check CrackingShells registry format +RA110 --> RS : return True/False +RS --> Consumer : return exists + +== Alternative Flow: v1.2.0 Package == + +Consumer -> PS : PackageService(v120_metadata) +note right : metadata contains\npackage_schema_version: "1.2.0" + +PS -> PAF : create_accessor_chain("1.2.0") +PAF -> PA120 : create V120PackageAccessor() +PAF -> PA110 : create V110PackageAccessor() +PAF -> PA120 : set_next(PA110) +PAF --> PS : return PA120 (chain head) + +Consumer -> PS : get_dependencies() +PS -> PA120 : get_dependencies(metadata) + +alt v1.2.0 handles unified dependencies + PA120 -> PA120 : extract unified dependencies + PA120 --> PS : return unified dependencies +end + +PS --> Consumer : return dependencies +note left : Same consumer code\nworks with v1.2.0\nand v1.2.1 packages + +== Alternative Flow: v1.1.0 Package == + +Consumer -> PS : PackageService(v110_metadata) +note right : metadata contains\npackage_schema_version: "1.1.0" + +PS -> PAF : create_accessor_chain("1.1.0") +PAF -> PA110 : create V110PackageAccessor() +PAF --> PS : return PA110 (terminal) + +Consumer -> PS : get_dependencies() +PS -> PA110 : get_dependencies(metadata) + +alt v1.1.0 handles separate dependencies + PA110 -> PA110 : convert separate to unified format + note right : hatch_dependencies +\npython_dependencies →\nunified structure + PA110 --> PS : return unified dependencies +end + +PS --> Consumer : return dependencies +note left : Consumer receives\nsame unified format\nregardless of schema version + +== Error Handling Flow == + +Consumer -> PS : get_unknown_field() +PS -> PA121 : get_unknown_field(metadata) + +alt PA121 cannot handle + PA121 -> PA120 : get_unknown_field(metadata) + + alt PA120 cannot handle + PA120 -> PA110 : get_unknown_field(metadata) + + alt PA110 cannot handle (terminal) + PA110 --> PA120 : raise NotImplementedError + end + + PA120 --> PA121 : propagate error + end + + PA121 --> PS : propagate error +end + +PS --> Consumer : raise NotImplementedError +note left : Graceful error handling\nthrough delegation chain + +== Schema Version Detection == + +Consumer -> PS : PackageService(metadata_without_version) +note right : Legacy package without\nexplicit schema version + +PS -> PAF : create_accessor_chain(None) +note right : None triggers\nlatest version chain + +PAF -> PA121 : create latest chain (v1.2.1) +PAF --> PS : return PA121 chain + +Consumer -> PS : get_dependencies() +PS -> PA121 : get_dependencies(metadata) + +alt PA121 cannot handle legacy format + PA121 -> PA120 : get_dependencies(metadata) + + alt PA120 cannot handle legacy format + PA120 -> PA110 : get_dependencies(metadata) + PA110 -> PA110 : handle legacy separate dependencies + PA110 --> PA120 : return converted dependencies + end + + PA120 --> PA121 : return dependencies +end + +PA121 --> PS : return dependencies +PS --> Consumer : return dependencies +note left : Legacy packages work\nthrough delegation to\nterminal v1.1.0 accessor + +== Validation with Dual Pattern Architecture == + +participant "HatchPackageValidator" as HPV +participant "ValidatorFactory" as VF +participant "V121Validator" as V121 +participant "V120Validator" as V120 +participant "V110Validator" as V110 +participant "SchemaValidation" as SV +participant "EntryPointValidation" as EPV +participant "DependencyValidation" as DV + +Consumer -> HPV : validate(v121_metadata) +HPV -> VF : create_validator_chain("1.2.1") +VF -> V121 : create V121Validator() +VF -> V120 : create V120Validator() +VF -> V110 : create V110Validator() +VF -> V121 : set_next(V120) +VF -> V120 : set_next(V110) +VF --> HPV : return V121 (chain head) + +HPV -> V121 : validate(metadata, context) + +== Strategy Composition (V121) == +V121 -> SV : validate_schema(metadata, context) +SV --> V121 : schema validation results +V121 -> EPV : validate_entry_point(metadata, context) +EPV --> V121 : entry point validation results + +== Chain Delegation (V121 → V120) == +V121 -> V120 : validate_dependencies(metadata, context) +note right : Delegates dependency validation\nto V120 via chain + +V120 -> DV : validate_dependencies(metadata, context) +DV --> V120 : dependency validation results +V120 --> V121 : return dependency results + +V121 --> HPV : return aggregated results +HPV --> Consumer : return validation results + +note over Consumer, DV : Dual Pattern Benefits:\n• Strategy Pattern: Encapsulates validation algorithms\n• Chain of Responsibility: Enables selective delegation\n• Composition: Changed concerns use strategies\n• Delegation: Unchanged concerns use chain\n• Version-agnostic validation interface + +@enduml From 7d0f98a088c237f7cfd9d3eef5e4e16237ca1d97 Mon Sep 17 00:00:00 2001 From: LittleCoinCoin Date: Tue, 9 Sep 2025 00:52:20 +0900 Subject: [PATCH 3/3] docs: diagrams Original diagrams `chain_of_responsibility_overview.puml`, `three_component_architecture.puml`, `version_agnostic_access.puml` were too complicated. Replacing them in favor several PlantUML diagrams to inform separately about - the objects involved in the chain of responsibility pattern (overview and detailed) - the objects involved in the strategy pattern - the objects involved in the creation of the chain of responsibility - the sequence through the chain of responsibility (overview and detailed) - Add the rendered svg to the documentation --- .../ChainOfResponsibilityPattern.md | 16 +- .../devs/architecture/ComponentTypes.md | 8 + docs/articles/users/GettingStarted.md | 4 + .../data_access/VersionAgnosticAccess.md | 4 + .../users/validation/PackageValidation.md | 6 + ...of_responsibility_delegation_sequence.puml | 62 +++++ .../chain_of_responsibility_overview.puml | 238 ------------------ .../chain_of_responsibility_simplified.puml | 96 +++++++ .../component_architecture_simplified.puml | 78 ++++++ .../diagrams/data_access_patterns_focus.puml | 84 +++++++ .../diagrams/factory_pattern_focus.puml | 109 ++++++++ .../diagrams/strategy_pattern_focus.puml | 146 +++++++++++ .../three_component_architecture.puml | 217 ---------------- .../diagrams/validation_execution_focus.puml | 74 ++++++ .../diagrams/version_agnostic_access.puml | 210 ---------------- .../version_agnostic_access_simplified.puml | 53 ++++ ..._of_responsibility_delegation_sequence.svg | 1 + .../chain_of_responsibility_simplified.svg | 1 + .../component_architecture_simplified.svg | 1 + .../images/data_access_patterns_focus.svg | 1 + .../images/factory_pattern_focus.svg | 1 + .../images/strategy_pattern_focus.svg | 1 + .../images/validation_execution_focus.svg | 1 + .../version_agnostic_access_simplified.svg | 1 + 24 files changed, 746 insertions(+), 667 deletions(-) create mode 100644 docs/resources/diagrams/chain_of_responsibility_delegation_sequence.puml delete mode 100644 docs/resources/diagrams/chain_of_responsibility_overview.puml create mode 100644 docs/resources/diagrams/chain_of_responsibility_simplified.puml create mode 100644 docs/resources/diagrams/component_architecture_simplified.puml create mode 100644 docs/resources/diagrams/data_access_patterns_focus.puml create mode 100644 docs/resources/diagrams/factory_pattern_focus.puml create mode 100644 docs/resources/diagrams/strategy_pattern_focus.puml delete mode 100644 docs/resources/diagrams/three_component_architecture.puml create mode 100644 docs/resources/diagrams/validation_execution_focus.puml delete mode 100644 docs/resources/diagrams/version_agnostic_access.puml create mode 100644 docs/resources/diagrams/version_agnostic_access_simplified.puml create mode 100644 docs/resources/images/chain_of_responsibility_delegation_sequence.svg create mode 100644 docs/resources/images/chain_of_responsibility_simplified.svg create mode 100644 docs/resources/images/component_architecture_simplified.svg create mode 100644 docs/resources/images/data_access_patterns_focus.svg create mode 100644 docs/resources/images/factory_pattern_focus.svg create mode 100644 docs/resources/images/strategy_pattern_focus.svg create mode 100644 docs/resources/images/validation_execution_focus.svg create mode 100644 docs/resources/images/version_agnostic_access_simplified.svg diff --git a/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md b/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md index 493317b..7c35760 100644 --- a/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md +++ b/docs/articles/devs/architecture/ChainOfResponsibilityPattern.md @@ -13,6 +13,10 @@ This article is about: The Chain of Responsibility pattern is the central architectural feature of Hatch-Validator, implemented consistently across three major component types. This pattern enables extensible functionality by allowing new components to inherit and modify only the changed logic from previous versions, creating a maintainable and scalable system. +![Chain of Responsibility Pattern Overview](../../../resources/images/chain_of_responsibility_simplified.svg) + +*The diagram above shows the simplified Chain of Responsibility pattern structure across all three component types: Validators, Package Accessors, and Registry Accessors.* + ### Core Principles **Delegation Over Inheritance**: Components delegate unchanged concerns to previous versions rather than using traditional class inheritance. @@ -51,6 +55,10 @@ Validators delegate to the chain for validation concerns that remain unchanged: - **No new requirements**: No new validation requirements introduced - **Previous implementation sufficient**: Previous version's strategy meets current needs +![Chain Delegation Sequence](../../../resources/images/chain_of_responsibility_delegation_sequence.svg) + +*The diagram above shows the detailed delegation flow through the validator chain, demonstrating how components check if they can handle a request and delegate to the next component when needed.* + ## Universal Implementation Pattern ### Three Component Types @@ -74,7 +82,7 @@ The Chain of Responsibility pattern is implemented identically across three comp ### Abstract Base Classes -All component types follow the same abstract base class pattern: +All component types follow the same abstract base class pattern (replace `ComponentBase` with the actual base class name for each component type) ```python # Universal pattern implemented by all three component types @@ -102,7 +110,7 @@ class ComponentBase(ABC): ### Factory Pattern Integration -All component types use identical factory patterns for chain construction: +All component types use identical factory patterns for chain construction (replace `ComponentFactory` and `ComponentBase` with the actual factory and base class names for each component type) ```python # Universal factory pattern used by all three component types @@ -254,6 +262,10 @@ components[1].set_next(components[2]) # v1.2.0 → v1.1.0 Validators implement the Strategy Pattern alongside Chain of Responsibility to encapsulate validation algorithms. This dual-pattern architecture provides fine-grained control over which validation concerns use strategy composition versus chain delegation. +![Strategy Pattern Implementation](../../../resources/images/strategy_pattern_focus.svg) + +*The diagram above shows how validation strategies are organized and implemented within the validator architecture, demonstrating the interface hierarchy and concrete strategy implementations.* + ### Strategy Interface Hierarchy Located in `hatch_validator/core/validation_strategy.py`: diff --git a/docs/articles/devs/architecture/ComponentTypes.md b/docs/articles/devs/architecture/ComponentTypes.md index 894b4d7..8faa0d1 100644 --- a/docs/articles/devs/architecture/ComponentTypes.md +++ b/docs/articles/devs/architecture/ComponentTypes.md @@ -11,6 +11,10 @@ This article is about: Hatch-Validator implements the Chain of Responsibility pattern across three distinct component types, each serving a specific purpose in the validation and data access ecosystem. These components work together to provide comprehensive, version-agnostic functionality for package management and validation. +![Component Architecture Overview](../../../resources/images/component_architecture_simplified.svg) + +*The diagram above shows the three-component architecture with unified Chain of Responsibility patterns across Validators, Package Accessors, and Registry Accessors.* + ## Validators ### Purpose and Scope @@ -259,6 +263,10 @@ class DependencyValidation: Factory classes coordinate component creation: +![Factory Pattern Implementation](../../../resources/images/factory_pattern_focus.svg) + +*The diagram above shows how factory classes automatically discover components, handle version precedence, and build chains with proper linking across all three component types.* + ```python # Coordinated factory usage def create_validation_system(metadata: Dict[str, Any], registry_data: Dict[str, Any]): diff --git a/docs/articles/users/GettingStarted.md b/docs/articles/users/GettingStarted.md index d288bf1..18f63a9 100644 --- a/docs/articles/users/GettingStarted.md +++ b/docs/articles/users/GettingStarted.md @@ -34,6 +34,10 @@ The validator uses the Chain of Responsibility design pattern to handle differen 3. Delegates requests through the chain 4. Returns results using a consistent interface +![Version-Agnostic Access Flow](../../resources/images/version_agnostic_access_simplified.svg) + +*The diagram above shows how client requests are handled through version-agnostic access, where factories create appropriate chains and components delegate to maintain consistent interfaces.* + ## Basic Package Validation ### Simple Validation Example diff --git a/docs/articles/users/data_access/VersionAgnosticAccess.md b/docs/articles/users/data_access/VersionAgnosticAccess.md index c888d9f..81b2e89 100644 --- a/docs/articles/users/data_access/VersionAgnosticAccess.md +++ b/docs/articles/users/data_access/VersionAgnosticAccess.md @@ -54,6 +54,10 @@ The system automatically detects schema versions from metadata and creates appro Each component in the chain implements version-specific logic while delegating unchanged concerns: +![Data Access Patterns](../../../resources/images/data_access_patterns_focus.svg) + +*The diagram above shows how data access flows through the accessor chain, with each accessor handling its version-specific concerns and delegating unchanged operations to previous versions.* + **Package Accessors Example:** - **v1.2.1 Accessor**: Handles dual entry point metadata → delegates dependency access to v1.2.0 - **v1.2.0 Accessor**: Handles unified dependency structure → delegates basic fields to v1.1.0 diff --git a/docs/articles/users/validation/PackageValidation.md b/docs/articles/users/validation/PackageValidation.md index dee2855..65ed88e 100644 --- a/docs/articles/users/validation/PackageValidation.md +++ b/docs/articles/users/validation/PackageValidation.md @@ -41,6 +41,12 @@ The validation process follows these steps: 4. **Validation Execution**: Execute validation through the chain with delegation 5. **Result Aggregation**: Collect and return comprehensive validation results +The following diagram illustrates how the validation execution integrates both Chain of Responsibility (for delegation) and Strategy Pattern (for validation algorithms): + +![Validation Execution Flow](../../../resources/images/validation_execution_focus.svg) + +*The diagram above shows how validation requests flow through the validator chain, with validators using strategies for changed concerns and delegating unchanged concerns to previous versions.* + ### Validation Categories The validator performs comprehensive validation across multiple categories: diff --git a/docs/resources/diagrams/chain_of_responsibility_delegation_sequence.puml b/docs/resources/diagrams/chain_of_responsibility_delegation_sequence.puml new file mode 100644 index 0000000..6e29b85 --- /dev/null +++ b/docs/resources/diagrams/chain_of_responsibility_delegation_sequence.puml @@ -0,0 +1,62 @@ +@startuml Chain Delegation Focus +!theme plain +skinparam backgroundColor white +skinparam participantBackgroundColor white +skinparam participantBorderColor black +skinparam arrowColor black + +title Chain of Responsibility - Delegation Flow + +participant "Client" as C +participant "V1.2.1 Validator" as V121 +participant "V1.2.0 Validator" as V120 +participant "V1.1.0 Validator" as V110 + +== Validation Request == +C -> V121 : validate(v1.2.1_metadata) +activate V121 + +note over V121 : **Can Handle Check**\nif schema_version == "1.2.1":\n return True + +V121 -> V121 : validate_entry_points()\n[Strategy Pattern] +V121 -> V121 : validate_tools()\n[Strategy Pattern] + +note over V121 : **Delegation Decision**\nFor dependencies validation:\nDelegate to v1.2.0 + +V121 -> V120 : validate_dependencies(metadata) +activate V120 + +note over V120 : **Can Handle Check**\nif schema_version in ["1.2.0", "1.2.1"]:\n return True + +V120 -> V120 : validate_dependencies()\n[Strategy Pattern] + +note over V120 : **Delegation Decision**\nFor schema validation:\nDelegate to v1.1.0 + +V120 -> V110 : validate_schema(metadata) +activate V110 + +note over V110 : **Terminal Handler**\nImplements all base validation\nNo further delegation + +V110 -> V110 : validate_schema()\n[Strategy Pattern] +V110 --> V120 : schema_result +deactivate V110 + +V120 --> V121 : dependency_result +deactivate V120 + +V121 --> C : combined_result +deactivate V121 + +== Alternative Flow: Direct Handling == +C -> V110 : validate(v1.1.0_metadata) +activate V110 + +note over V110 : **Can Handle Check**\nif schema_version == "1.1.0":\n return True + +V110 -> V110 : validate_all_concerns()\n[All Strategies] +V110 --> C : complete_result +deactivate V110 + +note over C, V110 : **Chain Benefits:**\n• **Automatic Routing**: Requests go to appropriate handler\n• **Code Reuse**: Unchanged logic is delegated\n• **Extensibility**: New versions extend without modification\n• **Fallback**: Older versions handle their specific cases + +@enduml diff --git a/docs/resources/diagrams/chain_of_responsibility_overview.puml b/docs/resources/diagrams/chain_of_responsibility_overview.puml deleted file mode 100644 index aa6e02a..0000000 --- a/docs/resources/diagrams/chain_of_responsibility_overview.puml +++ /dev/null @@ -1,238 +0,0 @@ -@startuml Chain of Responsibility Overview -!theme plain -skinparam backgroundColor white -skinparam classBackgroundColor white -skinparam classBorderColor black -skinparam arrowColor black - -title Chain of Responsibility + Strategy Pattern - Dual Architecture - -package "Strategy Interfaces" { - abstract class ValidationStrategy { - <> - } - - abstract class DependencyValidationStrategy { - + {abstract} validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } - - abstract class EntryPointValidationStrategy { - + {abstract} validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } - - abstract class ToolsValidationStrategy { - + {abstract} validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } - - abstract class SchemaValidationStrategy { - + {abstract} validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } -} - -package "Abstract Base Classes" { - abstract class ComponentBase { - - next_component: ComponentBase - + set_next(component: ComponentBase): ComponentBase - + {abstract} can_handle(version_or_data): bool - + operation(data): Any - } -} - -package "Validators" { - abstract class Validator { - - next_validator: Validator - + {abstract} can_handle(schema_version: str): bool - + {abstract} validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } - - class V121Validator { - - schema_strategy: SchemaValidation - - entry_point_strategy: EntryPointValidation - - tools_strategy: ToolsValidation - + can_handle(schema_version: str): bool - + validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } - - class V120Validator { - - schema_strategy: SchemaValidation - - dependency_strategy: DependencyValidation - + can_handle(schema_version: str): bool - + validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } - - class V110Validator { - - schema_strategy: SchemaValidation - - dependency_strategy: DependencyValidation - - entry_point_strategy: EntryPointValidation - - tools_strategy: ToolsValidation - + can_handle(schema_version: str): bool - + validate(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_entry_point(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - + validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] - } -} - -package "Package Accessors" { - abstract class HatchPkgAccessorBase { - - next_accessor: HatchPkgAccessorBase - + {abstract} can_handle(schema_version: str): bool - + get_dependencies(metadata: Dict): Dict - + get_entry_points(metadata: Dict): Dict - + get_name(metadata: Dict): str - } - - class V121PackageAccessor { - + can_handle(schema_version: str): bool - + get_entry_points(metadata: Dict): Dict - + get_dependencies(metadata: Dict): Dict - } - - class V120PackageAccessor { - + can_handle(schema_version: str): bool - + get_dependencies(metadata: Dict): Dict - + get_name(metadata: Dict): str - } - - class V110PackageAccessor { - + can_handle(schema_version: str): bool - + get_dependencies(metadata: Dict): Dict - + get_entry_points(metadata: Dict): Dict - + get_name(metadata: Dict): str - + get_all_fields(metadata: Dict): Dict - } -} - -package "Registry Accessors" { - abstract class RegistryAccessorBase { - - _successor: RegistryAccessorBase - + {abstract} can_handle(registry_data: Dict): bool - + handle_request(registry_data: Dict): RegistryAccessorBase - + package_exists(registry_data: Dict, package_name: str): bool - + find_compatible_version(registry_data: Dict, package_name: str, constraint: str): str - } - - class V110RegistryAccessor { - + can_handle(registry_data: Dict): bool - + package_exists(registry_data: Dict, package_name: str): bool - + find_compatible_version(registry_data: Dict, package_name: str, constraint: str): str - + get_package_uri(registry_data: Dict, package_name: str, version: str): str - } -} - -package "Factory Classes" { - class ValidatorFactory { - - {static} _validator_registry: Dict[str, Type[Validator]] - - {static} _version_order: List[str] - + {static} create_validator_chain(target_version: str): Validator - + {static} register_validator(version: str, validator_class: Type[Validator]): void - } - - class HatchPkgAccessorFactory { - - {static} _accessor_registry: Dict[str, Type[HatchPkgAccessorBase]] - - {static} _version_order: List[str] - + {static} create_accessor_chain(target_version: str): HatchPkgAccessorBase - + {static} register_accessor(version: str, accessor_class: Type[HatchPkgAccessorBase]): void - } - - class RegistryAccessorFactory { - - {static} _accessor_registry: Dict[str, Type[RegistryAccessorBase]] - + {static} create_accessor_for_data(registry_data: Dict): RegistryAccessorBase - + {static} register_accessor(version: str, accessor_class: Type[RegistryAccessorBase]): void - } -} - -' Strategy interface inheritance -ValidationStrategy <|-- DependencyValidationStrategy -ValidationStrategy <|-- EntryPointValidationStrategy -ValidationStrategy <|-- ToolsValidationStrategy -ValidationStrategy <|-- SchemaValidationStrategy - -' Component inheritance relationships -ComponentBase <|-- Validator -ComponentBase <|-- HatchPkgAccessorBase -ComponentBase <|-- RegistryAccessorBase - -Validator <|-- V121Validator -Validator <|-- V120Validator -Validator <|-- V110Validator - -HatchPkgAccessorBase <|-- V121PackageAccessor -HatchPkgAccessorBase <|-- V120PackageAccessor -HatchPkgAccessorBase <|-- V110PackageAccessor - -RegistryAccessorBase <|-- V110RegistryAccessor - -' Strategy composition relationships (solid lines) -V121Validator --> SchemaValidationStrategy : composes -V121Validator --> EntryPointValidationStrategy : composes -V121Validator --> ToolsValidationStrategy : composes - -V120Validator --> SchemaValidationStrategy : composes -V120Validator --> DependencyValidationStrategy : composes - -V110Validator --> SchemaValidationStrategy : composes -V110Validator --> DependencyValidationStrategy : composes -V110Validator --> EntryPointValidationStrategy : composes -V110Validator --> ToolsValidationStrategy : composes - -' Chain delegation relationships (dashed lines) -V121Validator ..> V120Validator : delegates dependencies -V120Validator ..> V110Validator : delegates entry_point, tools - -V121PackageAccessor --> V120PackageAccessor : delegates to -V120PackageAccessor --> V110PackageAccessor : delegates to - -' Factory relationships -ValidatorFactory ..> V121Validator : creates -ValidatorFactory ..> V120Validator : creates -ValidatorFactory ..> V110Validator : creates - -HatchPkgAccessorFactory ..> V121PackageAccessor : creates -HatchPkgAccessorFactory ..> V120PackageAccessor : creates -HatchPkgAccessorFactory ..> V110PackageAccessor : creates - -RegistryAccessorFactory ..> V110RegistryAccessor : creates - -note top of ComponentBase : Universal base pattern\nimplemented by all\nthree component types - -note top of ValidationStrategy : Strategy Pattern interfaces\nencapsulate validation algorithms\nfor specific concerns - -note right of V121Validator : Dual Pattern Architecture:\n• Composes strategies for changed concerns\n• Delegates unchanged concerns via chain\n• Handles v1.2.1 schema features - -note right of V120Validator : Dual Pattern Architecture:\n• Composes strategies for changed concerns\n• Delegates unchanged concerns via chain\n• Handles v1.2.0 unified dependencies - -note right of V110Validator : Terminal validator\nImplements all strategies\nNo delegation needed - -note right of V121PackageAccessor : Handles v1.2.1 dual entry points\nDelegates dependencies to v1.2.0 - -note right of V120PackageAccessor : Handles v1.2.0 unified dependencies\nDelegates basic fields to v1.1.0 - -note right of V110PackageAccessor : Terminal accessor\nImplements all metadata access - -note right of V110RegistryAccessor : Terminal registry accessor\nHandles CrackingShells registry format - -note bottom of ValidatorFactory : Automatically discovers\nand links validators\nfrom newest to oldest - -note as DualPattern -**Dual Pattern Architecture** -• Strategy Pattern: Encapsulates validation algorithms -• Chain of Responsibility: Enables version delegation -• Composition: Changed concerns use strategies -• Delegation: Unchanged concerns use chain -end note - -@enduml diff --git a/docs/resources/diagrams/chain_of_responsibility_simplified.puml b/docs/resources/diagrams/chain_of_responsibility_simplified.puml new file mode 100644 index 0000000..02238d6 --- /dev/null +++ b/docs/resources/diagrams/chain_of_responsibility_simplified.puml @@ -0,0 +1,96 @@ +@startuml Chain of Responsibility Overview - Simplified +!theme plain +skinparam backgroundColor white +skinparam classBackgroundColor white +skinparam classBorderColor black +skinparam arrowColor black + +title Chain of Responsibility Pattern - Simplified Overview + +package "Core Pattern" { + abstract class Validator { + + can_handle(version): bool + + validate(data): result + + set_next(validator): void + } + + abstract class RegistryAccessorBase { + + can_handle(data): bool + + process(data): result + } + abstract class HatchPkgAccessor { + + can_handle(version): bool + + get_data(metadata): data + + set_next(accessor): void + } + +} + +package "Version Implementations" { + class V1_2_1_Validator { + + can_handle(): bool + + validate(): result + } + + class V1_2_0_Validator { + + can_handle(): bool + + validate(): result + } + + class V1_1_0_Validator { + + can_handle(): bool + + validate(): result + } + + class V1_2_1_PackageAccessor { + + can_handle(): bool + + get_data(): data + } + + class V1_2_0_PackageAccessor { + + can_handle(): bool + + get_data(): data + } + + class V1_1_0_PackageAccessor { + + can_handle(): bool + + get_data(): data + } + + class V1_1_0_RegistryAccessor { + + can_handle(): bool + + process(): result + } +} + +' Inheritance +Validator <|-- V1_2_1_Validator +Validator <|-- V1_2_0_Validator +Validator <|-- V1_1_0_Validator + +HatchPkgAccessor <|-- V1_2_1_PackageAccessor +HatchPkgAccessor <|-- V1_2_0_PackageAccessor +HatchPkgAccessor <|-- V1_1_0_PackageAccessor + +RegistryAccessorBase <|-- V1_1_0_RegistryAccessor + +' Chain relationships (delegation flow) +V1_2_1_Validator ..> V1_2_0_Validator : delegates to +V1_2_0_Validator ..> V1_1_0_Validator : delegates to + +V1_2_1_PackageAccessor ..> V1_2_0_PackageAccessor : delegates to +V1_2_0_PackageAccessor ..> V1_1_0_PackageAccessor : delegates to + +note top of Validator : **Chain of Responsibility Pattern**\nEach component can handle specific versions\nor delegate to the next component in chain + +note bottom of V1_1_0_Validator : **Terminal Handler**\nImplements all base functionality\nNo further delegation + +note as ChainPattern +**Key Benefits:** +• **Extensibility**: Add new versions without modifying existing code +• **Delegation**: Reuse logic from previous versions +• **Flexibility**: Handle multiple schema versions seamlessly +• **Maintainability**: Each version focuses on its changes only +end note + +@enduml diff --git a/docs/resources/diagrams/component_architecture_simplified.puml b/docs/resources/diagrams/component_architecture_simplified.puml new file mode 100644 index 0000000..0682712 --- /dev/null +++ b/docs/resources/diagrams/component_architecture_simplified.puml @@ -0,0 +1,78 @@ +@startuml Component Architecture - Simplified +!theme plain +skinparam backgroundColor white +skinparam componentBackgroundColor white +skinparam componentBorderColor black +skinparam arrowColor black +skinparam componentStyle uml2 + +title Three-Component Architecture - Simplified Overview + +note as Architecture +**Three-Component Architecture:** +• **Validators**: Business logic for validation rules +• **Package Accessors**: Data extraction from package metadata +• **Registry Accessors**: Data processing from package registries +• **Unified Pattern**: All use Chain of Responsibility +end note + +package "Client Layer" { + [HatchPackageValidator] as HPV + [PackageService] as PS + [RegistryService] as RS +} + +package "Chain Components" { + [**Validator Chain**\nHandles validation logic for\ndifferent schema versions] as VC + [**Package Accessor Chain**\nExtracts metadata fields from\ndifferent schema formats] as PAC + [**Registry Accessor Chain**\nProcesses registry data\nfrom different sources] as RAC +} + +package "Factory Layer" { + [ValidatorFactory] as VF + [HatchPkgAccessorFactory] as HPAF + [RegistryAccessorFactory] as RAF +} + +package "Schema Management" { + [SchemaFetcher] as SF + [SchemaCache] as SC + [SchemaRetriever] as SR +} + +package "External Dependencies" { + database "Hatch-Schemas\nRepository" as HSR + cloud "Package Registry\n(CrackingShells)" as PR +} + +' Placement of Chain Components +VC -[hidden]down- PAC +PAC -[hidden]down- RAC + +' Placement of Factory Layer +VF -[hidden]down- HPAF +HPAF -[hidden]down- RAF + +' Client to Chain relationships +HPV --> VC : uses +PS --> PAC : uses +RS --> RAC : uses + +' Factory relationships +VF ..> VC : creates +HPAF ..> PAC : creates +RAF ..> RAC : creates + +' Schema management relationships +VC --> SF : fetches schemas +SF --> SC : caches +SF --> SR : retrieves +SR --> HSR : accesses + +' External data flow +RAC --> PR : accesses +PAC --> PR : reads metadata + +note top of "Factory Layer" : Automatically discovers\nand chains components\nfrom newest to oldest + +@enduml diff --git a/docs/resources/diagrams/data_access_patterns_focus.puml b/docs/resources/diagrams/data_access_patterns_focus.puml new file mode 100644 index 0000000..a8a4a5a --- /dev/null +++ b/docs/resources/diagrams/data_access_patterns_focus.puml @@ -0,0 +1,84 @@ +@startuml Data Access Patterns Focus +!theme plain +skinparam backgroundColor white +skinparam participantBackgroundColor white +skinparam participantBorderColor black +skinparam arrowColor black + +title Data Access Patterns - Version-Agnostic Operations + +participant "PackageService" as PS +participant "V1.2.1 PackageAccessor" as PA121 +participant "V1.2.0 PackageAccessor" as PA120 +participant "V1.1.0 PackageAccessor" as PA110 +participant "RegistryService" as RS +participant "V1.1.0 RegistryAccessor" as RA110 +database "Package Registry" as PR + +== Package Metadata Access == +PS -> PA121 : get_dependencies(v1.2.1_metadata) +activate PA121 + +note over PA121 : **Version Check**\nif schema_version == "1.2.1":\n handle dual entry points\nelse: delegate + +alt v1.2.1 specific handling + PA121 -> PA121 : extract_dual_entry_points() + PA121 -> PA120 : get_dependencies(metadata) + activate PA120 + + note over PA120 : **Version Check**\nif schema_version in ["1.2.0", "1.2.1"]:\n handle unified dependencies\nelse: delegate + + PA120 -> PA120 : extract_unified_dependencies() + PA120 --> PA121 : dependency_data + deactivate PA120 + +else direct delegation + PA121 -> PA120 : get_dependencies(metadata) + activate PA120 + PA120 -> PA110 : get_dependencies(metadata) + activate PA110 + + note over PA110 : **Terminal Handler**\nImplements all base\nmetadata extraction + + PA110 -> PA110 : extract_basic_dependencies() + PA110 --> PA120 : dependency_data + deactivate PA110 + PA120 --> PA121 : dependency_data + deactivate PA120 +end + +PA121 --> PS : processed_dependencies +deactivate PA121 + +== Registry Data Access == +RS -> RA110 : find_compatible_version(registry_data, "package", ">=1.0") +activate RA110 + +RA110 -> PR : query_package_versions("package") +activate PR +PR --> RA110 : available_versions +deactivate PR + +RA110 -> RA110 : resolve_version_constraint(">=1.0", available_versions) +RA110 --> RS : compatible_version +deactivate RA110 + +== Cross-Component Integration == +PS -> PA121 : get_entry_points(metadata) +activate PA121 +PA121 -> PA121 : extract_entry_points() +PA121 --> PS : entry_points +deactivate PA121 + +PS -> RS : validate_dependencies(entry_points) +activate RS +RS -> RA110 : package_exists(registry_data, dependency) +activate RA110 +RA110 --> RS : exists_result +deactivate RA110 +RS --> PS : validation_result +deactivate RS + +note over PS, PR : **Version-Agnostic Benefits:**\n• **Unified API**: Same interface across all versions\n• **Automatic Routing**: Requests go to appropriate handler\n• **Transparent Delegation**: Client unaware of version complexity\n• **Data Consistency**: Normalized output format + +@enduml diff --git a/docs/resources/diagrams/factory_pattern_focus.puml b/docs/resources/diagrams/factory_pattern_focus.puml new file mode 100644 index 0000000..d95e3c5 --- /dev/null +++ b/docs/resources/diagrams/factory_pattern_focus.puml @@ -0,0 +1,109 @@ +@startuml Factory Pattern Focus +!theme plain +skinparam backgroundColor white +skinparam classBackgroundColor white +skinparam classBorderColor black +skinparam arrowColor black + +title Factory Pattern - Component Creation and Chaining + +note as FactoryBenefits +**Factory Pattern Benefits:** +• **Automatic Discovery**: Finds all registered components +• **Chain Assembly**: Links components in correct order +• **Version Management**: Handles version precedence +• **Extensibility**: New versions auto-register +• **Encapsulation**: Hides complex creation logic +end note + +package "Factory Classes" { + class ValidatorFactory { + //Factory Pattern: Automatically discovers and chains components from newest to oldest// + .. + - {static} _validator_registry: Dict[str, Type[Validator]] + - {static} _version_order: List[str] = ["1.2.1", "1.2.0", "1.1.0"] + + {static} create_validator_chain(target_version: str): Validator + + {static} register_validator(version: str, validator_class: Type[Validator]): void + + {static} _build_chain(validators: List[Validator]): Validator + } + + class HatchPkgAccessorFactory { + - {static} _accessor_registry: Dict[str, Type[HatchPkgAccessor]] + - {static} _version_order: List[str] = ["1.2.1", "1.2.0", "1.1.0"] + + {static} create_accessor_chain(target_version: str): HatchPkgAccessor + + {static} register_accessor(version: str, accessor_class: Type[HatchPkgAccessor]): void + + {static} _build_chain(accessors: List[HatchPkgAccessor]): HatchPkgAccessor + } + + class RegistryAccessorFactory { + //Dynamic Creation: Detects registry format and creates appropriate accessor instance// + .. + - {static} _accessor_registry: Dict[str, Type[RegistryAccessorBase]] + + {static} create_accessor_for_data(registry_data: Dict): RegistryAccessorBase + + {static} register_accessor(version: str, accessor_class: Type[RegistryAccessorBase]): void + + {static} _detect_registry_format(registry_data: Dict): str + } +} + +ValidatorFactory -[hidden]down- RegistryAccessorFactory +RegistryAccessorFactory -[hidden]down- HatchPkgAccessorFactory + +package "Created Components" { + class V121Validator + class V120Validator + class V110Validator + + class V121PackageAccessor + class V120PackageAccessor + class V110PackageAccessor + + class V110RegistryAccessor +} + +V121Validator -[hidden]down- V120Validator +V120Validator -[hidden]down- V110Validator + +V110Validator -[hidden]down- V110RegistryAccessor + +V110RegistryAccessor -[hidden]down- V121PackageAccessor +V121PackageAccessor -[hidden]down- V120PackageAccessor +V120PackageAccessor -[hidden]down- V110PackageAccessor + + +package "Chain Structure" { + object "Validator Chain" as VC { + head: V121Validator + V121 -> V120 -> V110 + } + + object "Package Accessor Chain" as PAC { + head: V121PackageAccessor + V121 -> V120 -> V110 + } + + object "Registry Accessor" as RA { + single: V110RegistryAccessor + } +} + +VC -[hidden]down- RA +RA -[hidden]down- PAC + +"Created Components" -[hidden]right- "Factory Classes" +"Factory Classes" -[hidden]right- "Chain Structure" + +' Factory creation relationships +ValidatorFactory ..> V121Validator : creates +ValidatorFactory ..> V120Validator : creates +ValidatorFactory ..> V110Validator : creates +ValidatorFactory ..> VC : builds chain + +RegistryAccessorFactory ..> RA : provides +RegistryAccessorFactory ..> V110RegistryAccessor : creates + +HatchPkgAccessorFactory ..> V121PackageAccessor : creates +HatchPkgAccessorFactory ..> V120PackageAccessor : creates +HatchPkgAccessorFactory ..> V110PackageAccessor : creates +HatchPkgAccessorFactory ..> PAC : builds chain + +@enduml diff --git a/docs/resources/diagrams/strategy_pattern_focus.puml b/docs/resources/diagrams/strategy_pattern_focus.puml new file mode 100644 index 0000000..b02a09a --- /dev/null +++ b/docs/resources/diagrams/strategy_pattern_focus.puml @@ -0,0 +1,146 @@ +@startuml Strategy Pattern Focus +!theme plain +skinparam backgroundColor white +skinparam classBackgroundColor white +skinparam classBorderColor black +skinparam arrowColor black + +title Strategy Pattern Implementation - Validation Strategies + +package "Strategy Interfaces" { + abstract class ValidationStrategy { + <> + .. + //Strategy Pattern: Encapsulates validation algorithms for specific concerns// + .. + + {abstract} execute(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + rectangle "Main Strategies" { + abstract class DependencyValidationStrategy { + + {abstract} validate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V120DependencyValidation { + + validate_dependencies(): result + } + + class V110DependencyValidation { + + validate_dependencies(): result + } + + abstract class EntryPointValidationStrategy { + + {abstract} validate_entry_points(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V121EntryPointValidation { + + validate_entry_points(): result + } + + class V110EntryPointValidation { + + validate_entry_points(): result + } + + abstract class ToolsValidationStrategy { + + {abstract} validate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V121ToolsValidation { + + validate_tools(): result + } + + class V110ToolsValidation { + + validate_tools(): result + } + + abstract class SchemaValidationStrategy { + + {abstract} validate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]] + } + + class V110SchemaValidation { + + validate_schema(): result + } + } +} + + +"Main Strategies" -[hidden]down- ValidationStrategy +DependencyValidationStrategy -[hidden]down- V120DependencyValidation +DependencyValidationStrategy -[hidden]down- V110DependencyValidation + +V110DependencyValidation -[hidden]down- EntryPointValidationStrategy + +EntryPointValidationStrategy -[hidden]down- V121EntryPointValidation +EntryPointValidationStrategy -[hidden]down- V110EntryPointValidation + +V110EntryPointValidation -[hidden]down- ToolsValidationStrategy + + +ToolsValidationStrategy -[hidden]down- V121ToolsValidation +ToolsValidationStrategy -[hidden]down- V110ToolsValidation + +V110ToolsValidation -[hidden]down- SchemaValidationStrategy + +package "Context Classes" { + class V121Validator { + - entry_point_strategy: EntryPointValidationStrategy + - tools_strategy: ToolsValidationStrategy + + validate(metadata, context): result + } + + class V120Validator { + - dependency_strategy: DependencyValidationStrategy + + validate(metadata, context): result + } + + class V110Validator { + //Terminal Validator: Implements all strategies. No delegation needed.// + .. + - schema_strategy: SchemaValidationStrategy + - dependency_strategy: DependencyValidationStrategy + - entry_point_strategy: EntryPointValidationStrategy + - tools_strategy: ToolsValidationStrategy + + validate(metadata, context): result + } +} + +V121Validator -[hidden]down- V120Validator +V120Validator -[hidden]down- V110Validator + +"Context Classes" -[hidden]left- "Strategy Interfaces" + +' Strategy inheritance +ValidationStrategy <|-- DependencyValidationStrategy +ValidationStrategy <|-- EntryPointValidationStrategy +ValidationStrategy <|-- ToolsValidationStrategy +ValidationStrategy <|-- SchemaValidationStrategy + +' Strategy implementations +DependencyValidationStrategy <|.. V120DependencyValidation +DependencyValidationStrategy <|.. V110DependencyValidation +EntryPointValidationStrategy <|.. V121EntryPointValidation +EntryPointValidationStrategy <|.. V110EntryPointValidation +ToolsValidationStrategy <|.. V121ToolsValidation +ToolsValidationStrategy <|.. V110ToolsValidation +SchemaValidationStrategy <|.. V110SchemaValidation + +' Strategy composition +V121Validator --> EntryPointValidationStrategy : composes +V121Validator --> ToolsValidationStrategy : composes +V120Validator --> DependencyValidationStrategy : composes +V110Validator --> SchemaValidationStrategy : composes +V110Validator --> DependencyValidationStrategy : composes +V110Validator --> EntryPointValidationStrategy : composes +V110Validator --> ToolsValidationStrategy : composes + +note top of V121Validator : **Strategy Composition**\nUses strategies for changed\nvalidation concerns only + +note as StrategyBenefits +**Strategy Pattern Benefits:** +• **Encapsulation**: Each algorithm is isolated +• **Flexibility**: Easy to swap implementations +• **Testability**: Strategies can be tested independently +• **Reusability**: Strategies can be shared across versions +end note + +@enduml diff --git a/docs/resources/diagrams/three_component_architecture.puml b/docs/resources/diagrams/three_component_architecture.puml deleted file mode 100644 index 4c5caf3..0000000 --- a/docs/resources/diagrams/three_component_architecture.puml +++ /dev/null @@ -1,217 +0,0 @@ -@startuml Three Component Architecture -!theme plain -skinparam backgroundColor white -skinparam componentBackgroundColor white -skinparam componentBorderColor black -skinparam arrowColor black - -title Hatch-Validator Dual-Pattern Architecture - -package "Service Layer" { - component [PackageService] as PS { - Version-agnostic package\nmetadata access - } - - component [RegistryService] as RS { - Version-agnostic registry\ndata access - } - - component [HatchPackageValidator] as HPV { - Comprehensive package\nvalidation orchestration - } -} - -package "Strategy Layer" { - package "Validation Strategies" { - component [SchemaValidation] as SV { - Schema structure\nvalidation - } - - component [DependencyValidation] as DV { - Dependency structure\nvalidation - } - - component [EntryPointValidation] as EPV { - Entry point\nvalidation - } - - component [ToolsValidation] as TV { - Tools configuration\nvalidation - } - } -} - -package "Component Chains" { - package "Package Accessor Chain" { - component [V121PackageAccessor] as PA121 - component [V120PackageAccessor] as PA120 - component [V110PackageAccessor] as PA110 - - PA121 --> PA120 : delegates unchanged\nconcerns - PA120 --> PA110 : delegates unchanged\nconcerns - } - - package "Validator Chain" { - component [V121Validator] as V121 { - Composes: Schema, EntryPoint, Tools\nDelegates: Dependencies - } - component [V120Validator] as V120 { - Composes: Schema, Dependencies\nDelegates: EntryPoint, Tools - } - component [V110Validator] as V110 { - Composes: All strategies\nNo delegation - } - - V121 ..> V120 : delegates dependencies - V120 ..> V110 : delegates entry_point, tools - } - - package "Registry Accessor Chain" { - component [V110RegistryAccessor] as RA110 - } -} - -package "Factory Layer" { - component [HatchPkgAccessorFactory] as PAF { - Creates package\naccessor chains - } - - component [ValidatorFactory] as VF { - Creates validator\nchains - } - - component [RegistryAccessorFactory] as RAF { - Creates registry\naccessor chains - } -} - -package "Schema Management" { - component [SchemaRetriever] as SR { - Coordinates schema\nfetching and caching - } - - component [SchemaFetcher] as SF { - Downloads schemas\nfrom GitHub - } - - component [SchemaCache] as SC { - Local schema\nstorage and retrieval - } - - SR --> SF : fetches schemas - SR --> SC : caches schemas -} - -package "External Dependencies" { - database "Hatch-Schemas\nRepository" as HSR { - GitHub repository with\nversioned schema definitions - } - - database "Package\nMetadata" as PM { - hatch_metadata.json\nfiles with schema versions - } - - database "Registry\nData" as RD { - CrackingShells Package\nRegistry format - } -} - -package "Consumer Applications" { - component [Dependency Installation\nOrchestrator] as DIO { - Uses PackageService and\nRegistryService for\ndependency resolution - } - - component [Environment\nManager] as EM { - Uses RegistryService and\nHatchPackageValidator for\nenvironment management - } - - component [CLI Tools] as CLI { - Uses HatchPackageValidator\nfor package validation\ncommands - } -} - -' Strategy composition relationships -V121 --> SV : composes -V121 --> EPV : composes -V121 --> TV : composes - -V120 --> SV : composes -V120 --> DV : composes - -V110 --> SV : composes -V110 --> DV : composes -V110 --> EPV : composes -V110 --> TV : composes - -' Service Layer to Component Chains -PS --> PAF : creates chains -RS --> RAF : creates chains -HPV --> VF : creates chains -HPV --> RS : uses for validation - -' Factory to Component relationships -PAF ..> PA121 : creates and links -PAF ..> PA120 : creates and links -PAF ..> PA110 : creates and links - -VF ..> V121 : creates and links -VF ..> V120 : creates and links -VF ..> V110 : creates and links - -RAF ..> RA110 : creates - -' Schema Management relationships -V121 --> SR : loads schemas -V120 --> SR : loads schemas -V110 --> SR : loads schemas - -SF --> HSR : downloads from -SC --> PM : validates against - -' External Data relationships -PA121 --> PM : accesses -PA120 --> PM : accesses -PA110 --> PM : accesses - -RA110 --> RD : accesses - -' Consumer relationships -DIO --> PS : uses -DIO --> RS : uses - -EM --> RS : uses -EM --> HPV : uses - -CLI --> HPV : uses - -note top of PS : Provides unified interface\nto package metadata\nregardless of schema version - -note top of RS : Provides unified interface\nto registry data\nregardless of registry format - -note top of HPV : Orchestrates validation\nacross all component types\nwith automatic schema detection - -note top of SV : Strategy Layer:\nEncapsulates validation algorithms\nfor specific concerns - -note right of PA121 : Handles v1.2.1 features:\n- Dual entry points\n- Delegates dependencies - -note right of PA120 : Handles v1.2.0 features:\n- Unified dependencies\n- Delegates basic fields - -note right of PA110 : Terminal accessor:\n- All basic metadata\n- Separate dependencies - -note left of V121 : Dual Pattern Architecture:\n• Composes: Schema, EntryPoint, Tools\n• Delegates: Dependencies to V120\n• Handles v1.2.1 features - -note left of V120 : Dual Pattern Architecture:\n• Composes: Schema, Dependencies\n• Delegates: EntryPoint, Tools to V110\n• Handles v1.2.0 features - -note left of V110 : Terminal validator:\n• Composes all strategies\n• No delegation needed\n• Complete validation logic - -note bottom of RA110 : Handles CrackingShells\nregistry format:\n- Repository structure\n- Package existence\n- Version resolution - -note top of SR : Automatic schema management:\n- Version detection\n- Cache freshness\n- GitHub integration - -note bottom of DIO : Real-world usage:\n- Version-agnostic dependency access\n- Registry operations\n- Package resolution - -note bottom of EM : Real-world usage:\n- Registry data refresh\n- Package validation\n- Environment coordination - -note bottom of CLI : Real-world usage:\n- Package validation commands\n- Error reporting\n- Registry integration - -@enduml diff --git a/docs/resources/diagrams/validation_execution_focus.puml b/docs/resources/diagrams/validation_execution_focus.puml new file mode 100644 index 0000000..8e5502b --- /dev/null +++ b/docs/resources/diagrams/validation_execution_focus.puml @@ -0,0 +1,74 @@ +@startuml Validation Execution Focus +!theme plain +skinparam backgroundColor white +skinparam participantBackgroundColor white +skinparam participantBorderColor black +skinparam arrowColor black + +title Validation Execution - Dual Pattern Integration + +participant "HatchPackageValidator" as HPV +participant "V1.2.1 Validator" as V121 +participant "EntryPointStrategy" as EPS +participant "ToolsStrategy" as TS +participant "V1.2.0 Validator" as V120 +participant "DependencyStrategy" as DS +participant "V1.1.0 Validator" as V110 +participant "SchemaStrategy" as SS + +HPV -> V121 : validate(v1.2.1_metadata, context) +activate V121 + +== Strategy Pattern: Changed Concerns == +note over V121 : **Strategy Composition**\nHandle changed validation concerns\nusing specific strategies + +V121 -> EPS : validate_entry_points(metadata, context) +activate EPS +EPS --> V121 : entry_point_result +deactivate EPS + +V121 -> TS : validate_tools(metadata, context) +activate TS +TS --> V121 : tools_result +deactivate TS + +== Chain of Responsibility: Unchanged Concerns == +note over V121 : **Chain Delegation**\nDelegate unchanged concerns\nto previous version + +V121 -> V120 : validate_dependencies(metadata, context) +activate V120 + +note over V120 : **Strategy Composition**\nHandle v1.2.0 dependency changes\nusing specific strategy + +V120 -> DS : validate_dependencies(metadata, context) +activate DS +DS --> V120 : dependency_result +deactivate DS + +note over V120 : **Chain Delegation**\nDelegate schema validation\nto base version + +V120 -> V110 : validate_schema(metadata, context) +activate V110 + +note over V110 : **Strategy Implementation**\nTerminal validator implements\nall base strategies + +V110 -> SS : validate_schema(metadata, context) +activate SS +SS --> V110 : schema_result +deactivate SS + +V110 --> V120 : schema_result +deactivate V110 + +V120 --> V121 : dependency_result +deactivate V120 + +== Result Aggregation == +note over V121 : **Result Combination**\nAggregate all validation results\ninto final response + +V121 --> HPV : (is_valid, error_list) +deactivate V121 + +note over HPV, SS : **Dual Pattern Benefits:**\n• **Strategy**: Encapsulates changed validation logic\n• **Chain**: Reuses unchanged validation logic\n• **Composition**: New versions focus only on changes\n• **Delegation**: Automatic fallback to proven implementations + +@enduml diff --git a/docs/resources/diagrams/version_agnostic_access.puml b/docs/resources/diagrams/version_agnostic_access.puml deleted file mode 100644 index dcdc2e0..0000000 --- a/docs/resources/diagrams/version_agnostic_access.puml +++ /dev/null @@ -1,210 +0,0 @@ -@startuml Version Agnostic Access -!theme plain -skinparam backgroundColor white -skinparam participantBackgroundColor white -skinparam participantBorderColor black -skinparam arrowColor black - -title Version-Agnostic Access & Dual Pattern Validation Flow - -actor "Consumer\nApplication" as Consumer -participant "PackageService" as PS -participant "HatchPkgAccessorFactory" as PAF -participant "V121PackageAccessor" as PA121 -participant "V120PackageAccessor" as PA120 -participant "V110PackageAccessor" as PA110 -participant "RegistryService" as RS -participant "RegistryAccessorFactory" as RAF -participant "V110RegistryAccessor" as RA110 - -== Package Metadata Access (v1.2.1 Package) == - -Consumer -> PS : PackageService(metadata) -note right : metadata contains\npackage_schema_version: "1.2.1" - -PS -> PAF : create_accessor_chain("1.2.1") -PAF -> PA121 : create V121PackageAccessor() -PAF -> PA120 : create V120PackageAccessor() -PAF -> PA110 : create V110PackageAccessor() -PAF -> PA121 : set_next(PA120) -PAF -> PA120 : set_next(PA110) -PAF --> PS : return PA121 (chain head) - -Consumer -> PS : get_dependencies() -PS -> PA121 : get_dependencies(metadata) - -alt v1.2.1 doesn't handle dependencies - PA121 -> PA120 : get_dependencies(metadata) - note right : Delegates to v1.2.0\nfor unified dependencies - PA120 --> PA121 : return unified dependencies -end - -PA121 --> PS : return dependencies -PS --> Consumer : return dependencies -note left : Consumer receives unified\ndependency structure\nwithout knowing schema version - -== Entry Point Access (v1.2.1 Package) == - -Consumer -> PS : get_entry_points() -PS -> PA121 : get_entry_points(metadata) - -alt v1.2.1 handles dual entry points - PA121 -> PA121 : extract mcp_server and hatch_mcp_server - PA121 --> PS : return dual entry points -end - -PS --> Consumer : return entry_points -note left : Consumer receives dual\nentry point configuration\nspecific to v1.2.1 - -== Registry Operations == - -Consumer -> RS : RegistryService(registry_data) -RS -> RAF : create_accessor_for_data(registry_data) -RAF -> RA110 : create V110RegistryAccessor() -RAF --> RS : return RA110 - -Consumer -> RS : package_exists("example-package") -RS -> RA110 : package_exists(registry_data, "example-package") -RA110 -> RA110 : check CrackingShells registry format -RA110 --> RS : return True/False -RS --> Consumer : return exists - -== Alternative Flow: v1.2.0 Package == - -Consumer -> PS : PackageService(v120_metadata) -note right : metadata contains\npackage_schema_version: "1.2.0" - -PS -> PAF : create_accessor_chain("1.2.0") -PAF -> PA120 : create V120PackageAccessor() -PAF -> PA110 : create V110PackageAccessor() -PAF -> PA120 : set_next(PA110) -PAF --> PS : return PA120 (chain head) - -Consumer -> PS : get_dependencies() -PS -> PA120 : get_dependencies(metadata) - -alt v1.2.0 handles unified dependencies - PA120 -> PA120 : extract unified dependencies - PA120 --> PS : return unified dependencies -end - -PS --> Consumer : return dependencies -note left : Same consumer code\nworks with v1.2.0\nand v1.2.1 packages - -== Alternative Flow: v1.1.0 Package == - -Consumer -> PS : PackageService(v110_metadata) -note right : metadata contains\npackage_schema_version: "1.1.0" - -PS -> PAF : create_accessor_chain("1.1.0") -PAF -> PA110 : create V110PackageAccessor() -PAF --> PS : return PA110 (terminal) - -Consumer -> PS : get_dependencies() -PS -> PA110 : get_dependencies(metadata) - -alt v1.1.0 handles separate dependencies - PA110 -> PA110 : convert separate to unified format - note right : hatch_dependencies +\npython_dependencies →\nunified structure - PA110 --> PS : return unified dependencies -end - -PS --> Consumer : return dependencies -note left : Consumer receives\nsame unified format\nregardless of schema version - -== Error Handling Flow == - -Consumer -> PS : get_unknown_field() -PS -> PA121 : get_unknown_field(metadata) - -alt PA121 cannot handle - PA121 -> PA120 : get_unknown_field(metadata) - - alt PA120 cannot handle - PA120 -> PA110 : get_unknown_field(metadata) - - alt PA110 cannot handle (terminal) - PA110 --> PA120 : raise NotImplementedError - end - - PA120 --> PA121 : propagate error - end - - PA121 --> PS : propagate error -end - -PS --> Consumer : raise NotImplementedError -note left : Graceful error handling\nthrough delegation chain - -== Schema Version Detection == - -Consumer -> PS : PackageService(metadata_without_version) -note right : Legacy package without\nexplicit schema version - -PS -> PAF : create_accessor_chain(None) -note right : None triggers\nlatest version chain - -PAF -> PA121 : create latest chain (v1.2.1) -PAF --> PS : return PA121 chain - -Consumer -> PS : get_dependencies() -PS -> PA121 : get_dependencies(metadata) - -alt PA121 cannot handle legacy format - PA121 -> PA120 : get_dependencies(metadata) - - alt PA120 cannot handle legacy format - PA120 -> PA110 : get_dependencies(metadata) - PA110 -> PA110 : handle legacy separate dependencies - PA110 --> PA120 : return converted dependencies - end - - PA120 --> PA121 : return dependencies -end - -PA121 --> PS : return dependencies -PS --> Consumer : return dependencies -note left : Legacy packages work\nthrough delegation to\nterminal v1.1.0 accessor - -== Validation with Dual Pattern Architecture == - -participant "HatchPackageValidator" as HPV -participant "ValidatorFactory" as VF -participant "V121Validator" as V121 -participant "V120Validator" as V120 -participant "V110Validator" as V110 -participant "SchemaValidation" as SV -participant "EntryPointValidation" as EPV -participant "DependencyValidation" as DV - -Consumer -> HPV : validate(v121_metadata) -HPV -> VF : create_validator_chain("1.2.1") -VF -> V121 : create V121Validator() -VF -> V120 : create V120Validator() -VF -> V110 : create V110Validator() -VF -> V121 : set_next(V120) -VF -> V120 : set_next(V110) -VF --> HPV : return V121 (chain head) - -HPV -> V121 : validate(metadata, context) - -== Strategy Composition (V121) == -V121 -> SV : validate_schema(metadata, context) -SV --> V121 : schema validation results -V121 -> EPV : validate_entry_point(metadata, context) -EPV --> V121 : entry point validation results - -== Chain Delegation (V121 → V120) == -V121 -> V120 : validate_dependencies(metadata, context) -note right : Delegates dependency validation\nto V120 via chain - -V120 -> DV : validate_dependencies(metadata, context) -DV --> V120 : dependency validation results -V120 --> V121 : return dependency results - -V121 --> HPV : return aggregated results -HPV --> Consumer : return validation results - -note over Consumer, DV : Dual Pattern Benefits:\n• Strategy Pattern: Encapsulates validation algorithms\n• Chain of Responsibility: Enables selective delegation\n• Composition: Changed concerns use strategies\n• Delegation: Unchanged concerns use chain\n• Version-agnostic validation interface - -@enduml diff --git a/docs/resources/diagrams/version_agnostic_access_simplified.puml b/docs/resources/diagrams/version_agnostic_access_simplified.puml new file mode 100644 index 0000000..755d1ff --- /dev/null +++ b/docs/resources/diagrams/version_agnostic_access_simplified.puml @@ -0,0 +1,53 @@ +@startuml Version Agnostic Access - Simplified +!theme plain +skinparam backgroundColor white +skinparam participantBackgroundColor white +skinparam participantBorderColor black +skinparam arrowColor black + +title Version-Agnostic Data Access - Simplified Flow + +actor Client +participant "HatchPackageValidator" as HPV +participant "ValidatorFactory" as VF +participant "Validator Chain" as VC +participant "HatchPkgAccessorFactory" as HPAF +participant "Package Accessor Chain" as PAC + +Client -> HPV : validate_package(metadata) +activate HPV + +HPV -> VF : create_validator_chain(target_version) +activate VF +VF --> HPV : validator_chain +deactivate VF + +HPV -> HPAF : create_accessor_chain(target_version) +activate HPAF +HPAF --> HPV : accessor_chain +deactivate HPAF + +HPV -> VC : validate(metadata, context) +activate VC + +VC -> PAC : get_dependencies(metadata) +activate PAC +PAC --> VC : dependencies_data +deactivate PAC + +VC -> PAC : get_entry_points(metadata) +activate PAC +PAC --> VC : entry_points_data +deactivate PAC + +note over VC : **Chain Delegation**\nEach validator handles\nits version or delegates\nto next in chain + +VC --> HPV : validation_result +deactivate VC + +HPV --> Client : (is_valid, errors) +deactivate HPV + +note over Client, PAC : **Key Benefits:**\n• Client doesn't need to know schema versions\n• Automatic delegation to appropriate handlers\n• Consistent API across all versions\n• Extensible for future schema changes + +@enduml diff --git a/docs/resources/images/chain_of_responsibility_delegation_sequence.svg b/docs/resources/images/chain_of_responsibility_delegation_sequence.svg new file mode 100644 index 0000000..3b0b3f3 --- /dev/null +++ b/docs/resources/images/chain_of_responsibility_delegation_sequence.svg @@ -0,0 +1 @@ +Chain of Responsibility - Delegation FlowChain of Responsibility - Delegation FlowV1.2.1 ValidatorV1.2.0 ValidatorV1.1.0 ValidatorV1.1.0 ValidatorClientV1.2.1 ValidatorV1.2.0 ValidatorV1.1.0 ValidatorClientClientV1.2.1 ValidatorV1.2.1 ValidatorV1.2.0 ValidatorV1.2.0 ValidatorV1.1.0 ValidatorV1.1.0 ValidatorV1.2.1 ValidatorV1.2.0 ValidatorV1.1.0 ValidatorV1.1.0 ValidatorValidation Requestvalidate(v1.2.1_metadata)Can Handle Checkif schema_version == "1.2.1":return Truevalidate_entry_points()[Strategy Pattern]validate_tools()[Strategy Pattern]Delegation DecisionFor dependencies validation:Delegate to v1.2.0validate_dependencies(metadata)Can Handle Checkif schema_version in ["1.2.0", "1.2.1"]:return Truevalidate_dependencies()[Strategy Pattern]Delegation DecisionFor schema validation:Delegate to v1.1.0validate_schema(metadata)Terminal HandlerImplements all base validationNo further delegationvalidate_schema()[Strategy Pattern]schema_resultdependency_resultcombined_resultAlternative Flow: Direct Handlingvalidate(v1.1.0_metadata)Can Handle Checkif schema_version == "1.1.0":return Truevalidate_all_concerns()[All Strategies]complete_resultChain Benefits:Automatic Routing: Requests go to appropriate handlerCode Reuse: Unchanged logic is delegatedExtensibility: New versions extend without modificationFallback: Older versions handle their specific cases \ No newline at end of file diff --git a/docs/resources/images/chain_of_responsibility_simplified.svg b/docs/resources/images/chain_of_responsibility_simplified.svg new file mode 100644 index 0000000..b664a98 --- /dev/null +++ b/docs/resources/images/chain_of_responsibility_simplified.svg @@ -0,0 +1 @@ +Chain of Responsibility Pattern - Simplified OverviewChain of Responsibility Pattern - Simplified OverviewCore PatternVersion ImplementationsValidatorcan_handle(version): boolvalidate(data): resultset_next(validator): voidRegistryAccessorBasecan_handle(data): boolprocess(data): resultHatchPkgAccessorcan_handle(version): boolget_data(metadata): dataset_next(accessor): voidV1_2_1_Validatorcan_handle(): boolvalidate(): resultV1_2_0_Validatorcan_handle(): boolvalidate(): resultV1_1_0_Validatorcan_handle(): boolvalidate(): resultV1_2_1_PackageAccessorcan_handle(): boolget_data(): dataV1_2_0_PackageAccessorcan_handle(): boolget_data(): dataV1_1_0_PackageAccessorcan_handle(): boolget_data(): dataV1_1_0_RegistryAccessorcan_handle(): boolprocess(): resultChain of Responsibility PatternEach component can handle specific versionsor delegate to the next component in chainTerminal HandlerImplements all base functionalityNo further delegationKey Benefits:Extensibility: Add new versions without modifying existing codeDelegation: Reuse logic from previous versionsFlexibility: Handle multiple schema versions seamlesslyMaintainability: Each version focuses on its changes onlydelegates todelegates todelegates todelegates to \ No newline at end of file diff --git a/docs/resources/images/component_architecture_simplified.svg b/docs/resources/images/component_architecture_simplified.svg new file mode 100644 index 0000000..96f04cf --- /dev/null +++ b/docs/resources/images/component_architecture_simplified.svg @@ -0,0 +1 @@ +Three-Component Architecture - Simplified OverviewThree-Component Architecture - Simplified OverviewClient LayerChain ComponentsFactory LayerSchema ManagementExternal DependenciesHatchPackageValidatorPackageServiceRegistryServiceValidator ChainHandles validation logic fordifferent schema versionsPackage Accessor ChainExtracts metadata fields fromdifferent schema formatsRegistry Accessor ChainProcesses registry datafrom different sourcesValidatorFactoryHatchPkgAccessorFactoryRegistryAccessorFactorySchemaFetcherSchemaCacheSchemaRetrieverHatch-SchemasRepositoryPackage Registry(CrackingShells)Three-Component Architecture:Validators: Business logic for validation rulesPackage Accessors: Data extraction from package metadataRegistry Accessors: Data processing from package registriesUnified Pattern: All use Chain of ResponsibilityAutomatically discoversand chains componentsfrom newest to oldestusesusesusescreatescreatescreatesfetches schemascachesretrievesaccessesaccessesreads metadata \ No newline at end of file diff --git a/docs/resources/images/data_access_patterns_focus.svg b/docs/resources/images/data_access_patterns_focus.svg new file mode 100644 index 0000000..6dff983 --- /dev/null +++ b/docs/resources/images/data_access_patterns_focus.svg @@ -0,0 +1 @@ +Data Access Patterns - Version-Agnostic OperationsData Access Patterns - Version-Agnostic OperationsV1.2.1 PackageAccessorV1.2.1 PackageAccessorV1.2.0 PackageAccessorV1.2.0 PackageAccessorV1.1.0 PackageAccessorRegistryServiceV1.1.0 RegistryAccessorV1.1.0 RegistryAccessorPackage RegistryPackageServiceV1.2.1 PackageAccessorV1.2.0 PackageAccessorV1.1.0 PackageAccessorRegistryServiceV1.1.0 RegistryAccessorPackage RegistryPackageServicePackageServiceV1.2.1 PackageAccessorV1.2.1 PackageAccessorV1.2.0 PackageAccessorV1.2.0 PackageAccessorV1.1.0 PackageAccessorV1.1.0 PackageAccessorRegistryServiceRegistryServiceV1.1.0 RegistryAccessorV1.1.0 RegistryAccessorPackage RegistryPackage RegistryV1.2.1 PackageAccessorV1.2.1 PackageAccessorV1.2.0 PackageAccessorV1.2.0 PackageAccessorV1.1.0 PackageAccessorRegistryServiceV1.1.0 RegistryAccessorV1.1.0 RegistryAccessorPackage RegistryPackage Metadata Accessget_dependencies(v1.2.1_metadata)Version Checkif schema_version == "1.2.1":handle dual entry pointselse: delegatealt[v1.2.1 specific handling]extract_dual_entry_points()get_dependencies(metadata)Version Checkif schema_version in ["1.2.0", "1.2.1"]:handle unified dependencieselse: delegateextract_unified_dependencies()dependency_data[direct delegation]get_dependencies(metadata)get_dependencies(metadata)Terminal HandlerImplements all basemetadata extractionextract_basic_dependencies()dependency_datadependency_dataprocessed_dependenciesRegistry Data Accessfind_compatible_version(registry_data, "package", ">=1.0")query_package_versions("package")available_versionsresolve_version_constraint(">=1.0", available_versions)compatible_versionCross-Component Integrationget_entry_points(metadata)extract_entry_points()entry_pointsvalidate_dependencies(entry_points)package_exists(registry_data, dependency)exists_resultvalidation_resultVersion-Agnostic Benefits:Unified API: Same interface across all versionsAutomatic Routing: Requests go to appropriate handlerTransparent Delegation: Client unaware of version complexityData Consistency: Normalized output format \ No newline at end of file diff --git a/docs/resources/images/factory_pattern_focus.svg b/docs/resources/images/factory_pattern_focus.svg new file mode 100644 index 0000000..e468645 --- /dev/null +++ b/docs/resources/images/factory_pattern_focus.svg @@ -0,0 +1 @@ +Factory Pattern - Component Creation and ChainingFactory Pattern - Component Creation and ChainingFactory ClassesCreated ComponentsChain StructureValidatorFactoryFactory Pattern: Automatically discovers and chains components from newest to oldest_validator_registry: Dict[str, Type[Validator]]_version_order: List[str] = ["1.2.1", "1.2.0", "1.1.0"]create_validator_chain(target_version: str): Validatorregister_validator(version: str, validator_class: Type[Validator]): void_build_chain(validators: List[Validator]): ValidatorHatchPkgAccessorFactory_accessor_registry: Dict[str, Type[HatchPkgAccessor]]_version_order: List[str] = ["1.2.1", "1.2.0", "1.1.0"]create_accessor_chain(target_version: str): HatchPkgAccessorregister_accessor(version: str, accessor_class: Type[HatchPkgAccessor]): void_build_chain(accessors: List[HatchPkgAccessor]): HatchPkgAccessorRegistryAccessorFactoryDynamic Creation: Detects registry format and creates appropriate accessor instance_accessor_registry: Dict[str, Type[RegistryAccessorBase]]create_accessor_for_data(registry_data: Dict): RegistryAccessorBaseregister_accessor(version: str, accessor_class: Type[RegistryAccessorBase]): void_detect_registry_format(registry_data: Dict): strV121ValidatorV120ValidatorV110ValidatorV121PackageAccessorV120PackageAccessorV110PackageAccessorV110RegistryAccessorValidator Chainhead: V121ValidatorV121 -> V120 -> V110Package Accessor Chainhead: V121PackageAccessorV121 -> V120 -> V110Registry Accessorsingle: V110RegistryAccessorFactory Pattern Benefits:Automatic Discovery: Finds all registered componentsChain Assembly: Links components in correct orderVersion Management: Handles version precedenceExtensibility: New versions auto-registerEncapsulation: Hides complex creation logiccreatescreatescreatesbuilds chainprovidescreatescreatescreatescreatesbuilds chain \ No newline at end of file diff --git a/docs/resources/images/strategy_pattern_focus.svg b/docs/resources/images/strategy_pattern_focus.svg new file mode 100644 index 0000000..028026e --- /dev/null +++ b/docs/resources/images/strategy_pattern_focus.svg @@ -0,0 +1 @@ +Strategy Pattern Implementation - Validation StrategiesStrategy Pattern Implementation - Validation StrategiesStrategy InterfacesMain StrategiesContext ClassesValidationStrategy«interface»Strategy Pattern: Encapsulates validation algorithms for specific concernsexecute(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]]DependencyValidationStrategyvalidate_dependencies(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]]V120DependencyValidationvalidate_dependencies(): resultV110DependencyValidationvalidate_dependencies(): resultEntryPointValidationStrategyvalidate_entry_points(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]]V121EntryPointValidationvalidate_entry_points(): resultV110EntryPointValidationvalidate_entry_points(): resultToolsValidationStrategyvalidate_tools(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]]V121ToolsValidationvalidate_tools(): resultV110ToolsValidationvalidate_tools(): resultSchemaValidationStrategyvalidate_schema(metadata: Dict, context: ValidationContext): Tuple[bool, List[str]]V110SchemaValidationvalidate_schema(): resultV121Validatorentry_point_strategy: EntryPointValidationStrategytools_strategy: ToolsValidationStrategyvalidate(metadata, context): resultV120Validatordependency_strategy: DependencyValidationStrategyvalidate(metadata, context): resultV110ValidatorTerminal Validator: Implements all strategies. No delegation needed.schema_strategy: SchemaValidationStrategydependency_strategy: DependencyValidationStrategyentry_point_strategy: EntryPointValidationStrategytools_strategy: ToolsValidationStrategyvalidate(metadata, context): resultStrategy CompositionUses strategies for changedvalidation concerns onlyStrategy Pattern Benefits:Encapsulation: Each algorithm is isolatedFlexibility: Easy to swap implementationsTestability: Strategies can be tested independentlyReusability: Strategies can be shared across versionscomposescomposescomposescomposescomposescomposescomposes \ No newline at end of file diff --git a/docs/resources/images/validation_execution_focus.svg b/docs/resources/images/validation_execution_focus.svg new file mode 100644 index 0000000..58e811e --- /dev/null +++ b/docs/resources/images/validation_execution_focus.svg @@ -0,0 +1 @@ +Validation Execution - Dual Pattern IntegrationValidation Execution - Dual Pattern IntegrationV1.2.1 ValidatorEntryPointStrategyToolsStrategyV1.2.0 ValidatorDependencyStrategyV1.1.0 ValidatorSchemaStrategyHatchPackageValidatorV1.2.1 ValidatorEntryPointStrategyToolsStrategyV1.2.0 ValidatorDependencyStrategyV1.1.0 ValidatorSchemaStrategyHatchPackageValidatorHatchPackageValidatorV1.2.1 ValidatorV1.2.1 ValidatorEntryPointStrategyEntryPointStrategyToolsStrategyToolsStrategyV1.2.0 ValidatorV1.2.0 ValidatorDependencyStrategyDependencyStrategyV1.1.0 ValidatorV1.1.0 ValidatorSchemaStrategySchemaStrategyV1.2.1 ValidatorEntryPointStrategyToolsStrategyV1.2.0 ValidatorDependencyStrategyV1.1.0 ValidatorSchemaStrategyvalidate(v1.2.1_metadata, context)Strategy Pattern: Changed ConcernsStrategy CompositionHandle changed validation concernsusing specific strategiesvalidate_entry_points(metadata, context)entry_point_resultvalidate_tools(metadata, context)tools_resultChain of Responsibility: Unchanged ConcernsChain DelegationDelegate unchanged concernsto previous versionvalidate_dependencies(metadata, context)Strategy CompositionHandle v1.2.0 dependency changesusing specific strategyvalidate_dependencies(metadata, context)dependency_resultChain DelegationDelegate schema validationto base versionvalidate_schema(metadata, context)Strategy ImplementationTerminal validator implementsall base strategiesvalidate_schema(metadata, context)schema_resultschema_resultdependency_resultResult AggregationResult CombinationAggregate all validation resultsinto final response(is_valid, error_list)Dual Pattern Benefits:Strategy: Encapsulates changed validation logicChain: Reuses unchanged validation logicComposition: New versions focus only on changesDelegation: Automatic fallback to proven implementations \ No newline at end of file diff --git a/docs/resources/images/version_agnostic_access_simplified.svg b/docs/resources/images/version_agnostic_access_simplified.svg new file mode 100644 index 0000000..dd91914 --- /dev/null +++ b/docs/resources/images/version_agnostic_access_simplified.svg @@ -0,0 +1 @@ +Version-Agnostic Data Access - Simplified FlowVersion-Agnostic Data Access - Simplified FlowHatchPackageValidatorValidatorFactoryValidator ChainHatchPkgAccessorFactoryPackage Accessor ChainPackage Accessor ChainClientHatchPackageValidatorValidatorFactoryValidator ChainHatchPkgAccessorFactoryPackage Accessor ChainClientClientHatchPackageValidatorHatchPackageValidatorValidatorFactoryValidatorFactoryValidator ChainValidator ChainHatchPkgAccessorFactoryHatchPkgAccessorFactoryPackage Accessor ChainPackage Accessor ChainHatchPackageValidatorValidatorFactoryValidator ChainHatchPkgAccessorFactoryPackage Accessor ChainPackage Accessor Chainvalidate_package(metadata)create_validator_chain(target_version)validator_chaincreate_accessor_chain(target_version)accessor_chainvalidate(metadata, context)get_dependencies(metadata)dependencies_dataget_entry_points(metadata)entry_points_dataChain DelegationEach validator handlesits version or delegatesto next in chainvalidation_result(is_valid, errors)Key Benefits:• Client doesn't need to know schema versions• Automatic delegation to appropriate handlers• Consistent API across all versions• Extensible for future schema changes \ No newline at end of file