├── .github ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── codeql-analysis.yml │ ├── dependency-submission-example.yml │ ├── publish.yml │ └── test.yml ├── .gitignore ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── action.yml ├── biome.json ├── example ├── index.ts ├── npm-detector.test.ts ├── npm-detector.ts ├── package.json └── tsconfig.json ├── ownership.yaml ├── package-lock.json ├── package.json ├── src ├── index.ts ├── manifest.test.ts ├── manifest.ts ├── package-cache.test.ts ├── package-cache.ts ├── package.test.ts ├── package.ts ├── snapshot.test.ts └── snapshot.ts ├── tsconfig.json └── tsup.config.ts /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: github-actions 5 | directory: "/" 6 | schedule: 7 | interval: weekly 8 | 9 | - package-ecosystem: npm 10 | directory: "/" 11 | schedule: 12 | interval: weekly 13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | _Describe the purpose of this pull request_ 4 | 5 | ## Related Issues 6 | 7 | _What issues does this PR close or relate to?_ 8 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '36 10 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v3 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v3 73 | -------------------------------------------------------------------------------- /.github/workflows/dependency-submission-example.yml: -------------------------------------------------------------------------------- 1 | name: Example Dependency Submission 2 | 3 | on: push 4 | 5 | permissions: 6 | contents: write 7 | 8 | jobs: 9 | example-submission: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions/setup-node@v4 14 | with: 15 | node-version: 20 16 | - name: Install NPM dependencies 17 | run: npm ci 18 | - name: Run all NPM build/test actions 19 | run: npm run --workspace example all 20 | - name: Run dependency submission 21 | uses: ./ 22 | with: 23 | npm-package-directory: ./ 24 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | publish-npm: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/setup-node@v4 13 | with: 14 | node-version: 20 15 | registry-url: https://registry.npmjs.org 16 | - run: npm ci 17 | - run: npm test 18 | - run: npm version ${TAG_NAME} --git-tag-version=false --allow-same-version 19 | env: 20 | TAG_NAME: ${{ github.event.release.tag_name }} 21 | - run: npm whoami; npm publish --access public 22 | env: 23 | NODE_AUTH_TOKEN: ${{ secrets.npm_token }} 24 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: 'build-test' 2 | 3 | on: # rebuild any PRs and main branch changes 4 | pull_request: 5 | branches: 6 | - main 7 | - 'releases/*' 8 | push: 9 | branches: 10 | - main 11 | - 'releases/*' 12 | 13 | jobs: 14 | build: # make sure build/ci work properly 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | - name: Install NPM dependencies 22 | run: npm ci 23 | - name: Run all NPM build/test actions 24 | run: npm run all 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | .env.test 71 | 72 | # parcel-bundler cache (https://parceljs.org/) 73 | .cache 74 | 75 | # next.js build output 76 | .next 77 | 78 | # nuxt.js build output 79 | .nuxt 80 | 81 | # vuepress build output 82 | .vuepress/dist 83 | 84 | # Serverless directories 85 | .serverless/ 86 | 87 | # FuseBox cache 88 | .fusebox/ 89 | 90 | # DynamoDB Local files 91 | .dynamodb/ 92 | 93 | # OS metadata 94 | .DS_Store 95 | Thumbs.db 96 | 97 | # Ignore built ts files 98 | __tests__/runner/* 99 | lib/**/* 100 | 101 | # Ignore output files 102 | dist 103 | example/action-dist -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @github/dependency-graph-reviewers 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | opensource@github.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | [fork]: https://github.com/github/dependency-submission-toolkit/fork 4 | [pr]: https://github.com/github/dependency-submission-toolkit/compare 5 | [code-of-conduct]: CODE_OF_CONDUCT.md 6 | 7 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. 8 | 9 | Contributions to this project are 10 | [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) 11 | to the public under the [project's open source license](LICENSE). 12 | 13 | Please note that this project is released with a [Contributor Code of 14 | Conduct][code-of-conduct]. By participating in this project you agree 15 | to abide by its terms. 16 | 17 | ## Bug reports and other issues 18 | 19 | If you've encountered a problem, please let us know by [submitting an issue](https://github.com/github/dependency-submission-toolkit/issues/new)! 20 | 21 | ## Enhancements and feature requests 22 | 23 | If you've got an idea for a new feature or a significant change to the code or its dependencies, please submit as [an issue](https://github.com/github/dependency-submission-toolkit/issues/new) so that the community can see it, and we can discuss it there. We may not be able to respond to every single issue, but will make a best effort! 24 | 25 | If you'd like to make a contribution yourself, we ask that before significant effort is put into code changes, that we have agreement that the change aligns with our strategy. Since this is a repository owned and primarily maintained by GitHub, we want to make sure that contributions are high quality, and that they maintain consistency with the rest of it's behavior. 26 | 27 | 1. Create an [issue discussing the idea](https://github.com/github/dependency-submission-toolkit/issues/new), so that we can discuss it there. 28 | 2. If we agree to incorporate the idea into the project, please write-up a high level summary of the approach that you plan to take so we can review 29 | 30 | 31 | ### Bootstrapping the project 32 | 33 | ``` 34 | git clone https://github.com/github/dependency-submission-toolkit.git 35 | cd dependency-submission-toolkit 36 | npm install 37 | ``` 38 | 39 | ### Running the tests 40 | 41 | ``` 42 | npm run test 43 | ``` 44 | 45 | ## Submitting a pull request 46 | 47 | 0. [Fork][fork] and clone the repository 48 | 1. Configure and install the dependencies: `npm install` 49 | 2. Make sure the tests pass on your machine: `npm run test` 50 | 3. Create a new branch: `git checkout -b my-branch-name` 51 | 4. Make your change, add tests, and make sure the tests still pass 52 | 5. Make sure to build and package before pushing: `npm run all` 53 | 6. Push to your fork and [submit a pull request][pr] 54 | 7. Pat your self on the back and wait for your pull request to be reviewed and merged. 55 | 56 | Here are a few things you can do that will increase the likelihood of your pull request being accepted: 57 | 58 | - Write tests. 59 | - Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. 60 | - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 61 | 62 | ## Cutting a new release 63 | 64 | 1. Update the version number in [package.json](https://github.com/github/dependency-submission-toolkit/blob/main/package.json). 65 | 1. Go to [Draft a new 66 | release](https://github.com/github/dependency-submission-toolkit/releases/new) 67 | in the Releases page. 68 | 1. Make sure that the `Publish this Action to the GitHub Marketplace` 69 | checkbox is enabled 70 | 3. Click "Choose a tag" and then "Create new tag", where the tag name 71 | will be your version prefixed by a `v` (e.g. `v1.2.3`). 72 | 4. Use a version number for the release title (e.g. "v1.2.3"). 73 | 5. Add your release notes. If this is a major version make sure to 74 | include a small description of the biggest changes in the new version. 75 | 6. Click "Publish Release". 76 | 77 | ## Resources 78 | 79 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) 80 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) 81 | - [GitHub Help](https://help.github.com) 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 GitHub 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dependency Submission Toolkit 2 | 3 | `@github/dependency-submission-toolkit` is a TypeScript library for creating 4 | dependency snapshots and submitting them to the dependency submission API. 5 | Snapshots are a set of dependencies grouped by manifest with some related 6 | metadata. A manifest can be a physical file or a more abstract representation of 7 | a dependency grouping (such processing of program outputs). After submission to 8 | the API, the included dependencies appear in the repository's 9 | [dependency graph](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph). 10 | 11 | ## Installation 12 | 13 | ``` 14 | npm install @github/dependency-submission-toolkit 15 | ``` 16 | 17 | ## Writing Your Own Dependency Submission Action 18 | 19 | You may use classes from `@github/dependency-submission-toolkit` to help in 20 | building your own GitHub Action for submitting dependencies to the Dependency 21 | Submission API. At a high level, the steps to use the classes are: 22 | 23 | 1. Create a `PackageCache` of all of the packages that could be included in your 24 | manifest, as well define as the relationships between them. 25 | 26 | 2. Using the packages defined in `PackageCache`, create a `Manifest` or a 27 | `BuildTarget`, which defines the dependencies of the build environment or 28 | specific build artifact. 29 | 30 | 3. Create a `Snapshot` to include one or more `Manifests` or `BuildTargets`. The 31 | snapshot is the base container for submitting dependencies to the Dependency 32 | Submission API. 33 | 34 | 4. Follow the instructions for 35 | [Creating a JavaScript Action](https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action). 36 | These include: 37 | 38 | - Defining an `action.yml` action metadata file 39 | - Compiling the JavaScript into a single script using `ncc` 40 | - Testing your action in a workflow 41 | 42 | A full example action using this library is included in the `example/` 43 | directory. This example uses the output from the `npm list` to create an 44 | accurate and complete graph of the dependencies used in this library. This 45 | action is also included in a workflow in this repository and runs for each 46 | commit to the `main` branch. 47 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Example Dependency Submission Action' 2 | description: 'Example action using the dependency-submission-toolkit and npm' 3 | inputs: 4 | token: 5 | description: "GitHub Personal Access Token (PAT). Defaults to PAT provided by Action runner" 6 | required: false 7 | default: ${{ github.token }} 8 | npm-package-directory: 9 | description: 'NPM package directory (directory with package.json)' 10 | required: true 11 | default: './' 12 | runs: 13 | using: 'node20' 14 | main: 'example/dist/index.js' 15 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/@biomejs/biome/configuration_schema.json", 3 | "formatter": { 4 | "enabled": true, 5 | "indentStyle": "space" 6 | }, 7 | "javascript": { 8 | "formatter": { 9 | "quoteStyle": "single", 10 | "semicolons": "asNeeded", 11 | "trailingComma": "none" 12 | } 13 | }, 14 | "linter": { 15 | "enabled": true, 16 | "rules": { 17 | "recommended": true 18 | } 19 | }, 20 | "organizeImports": { 21 | "enabled": true 22 | }, 23 | "vcs": { 24 | "clientKind": "git", 25 | "enabled": true, 26 | "useIgnoreFile": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/index.ts: -------------------------------------------------------------------------------- 1 | import { main } from './npm-detector.js' 2 | 3 | main() 4 | -------------------------------------------------------------------------------- /example/npm-detector.test.ts: -------------------------------------------------------------------------------- 1 | import { PackageCache } from '@github/dependency-submission-toolkit' 2 | import { describe, expect, test } from 'vitest' 3 | 4 | import { 5 | createBuildTarget, 6 | parseDependencies, 7 | parseNameAndNamespace 8 | } from './npm-detector.js' 9 | 10 | describe('parseNameAndNamespace', () => { 11 | test('parses single name, no namespace', () => { 12 | expect(parseNameAndNamespace('left-pad')).toEqual(['', 'left-pad']) 13 | }) 14 | 15 | test('parses namespace and name', () => { 16 | expect(parseNameAndNamespace('beware/left-pad')).toEqual([ 17 | 'beware', 18 | 'left-pad' 19 | ]) 20 | }) 21 | 22 | test('url-encodes namespace and name', () => { 23 | expect(parseNameAndNamespace('@actions/core')).toEqual([ 24 | '%40actions', 25 | 'core' 26 | ]) 27 | }) 28 | 29 | test('throws error if multiple slashes', () => { 30 | expect(() => { 31 | parseNameAndNamespace('foo/bar/baz') 32 | }).toThrow() 33 | }) 34 | }) 35 | 36 | describe('parseDependencies', () => { 37 | test('parse single dependency', () => { 38 | const dependencies = { foo: { version: '1.0' } } 39 | const cache = new PackageCache() 40 | const pkgs = parseDependencies(cache, dependencies) 41 | 42 | expect(pkgs).toHaveLength(1) 43 | expect(pkgs[0]?.packageID()).toEqual('pkg:npm/foo@1.0') 44 | expect(cache.countPackages()).toEqual(1) 45 | }) 46 | 47 | test('parse multiple dependencies, single depth', () => { 48 | const dependencies = { foo: { version: '1.0' }, bar: { version: '2.0' } } 49 | const cache = new PackageCache() 50 | const pkgs = parseDependencies(cache, dependencies) 51 | 52 | expect(pkgs).toHaveLength(2) 53 | expect(pkgs[0]?.packageID()).toEqual('pkg:npm/foo@1.0') 54 | expect(pkgs[1]?.packageID()).toEqual('pkg:npm/bar@2.0') 55 | expect(cache.countPackages()).toEqual(2) 56 | }) 57 | 58 | test('parse multiple depth', () => { 59 | const dependencies = { 60 | foo: { version: '1.0', dependencies: { bar: { version: '2.0' } } } 61 | } 62 | const cache = new PackageCache() 63 | const pkgs = parseDependencies(cache, dependencies) 64 | 65 | expect(pkgs).toHaveLength(1) 66 | expect(pkgs[0]?.packageID()).toEqual('pkg:npm/foo@1.0') 67 | expect(pkgs[0]?.packageDependencyIDs).toHaveLength(1) 68 | expect(pkgs[0]?.packageDependencyIDs[0]).toEqual('pkg:npm/bar@2.0') 69 | expect(cache.countPackages()).toEqual(2) 70 | }) 71 | }) 72 | 73 | describe('createBuildTarget', () => { 74 | test('parse npm package', () => { 75 | const npmPackage = { 76 | name: 'example-package', 77 | version: '0.0', 78 | dependencies: { 79 | foo: { version: '1.0', dependencies: { bar: { version: '2.0' } } }, 80 | baz: { version: '3.0' } 81 | } 82 | } 83 | 84 | const buildTarget = createBuildTarget(npmPackage) 85 | expect(buildTarget.name).toEqual('example-package') 86 | expect(buildTarget.directDependencies()).toHaveLength(2) 87 | expect(buildTarget.indirectDependencies()).toHaveLength(1) 88 | }) 89 | }) 90 | -------------------------------------------------------------------------------- /example/npm-detector.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import * as exec from '@actions/exec' 3 | import { 4 | BuildTarget, 5 | type Package, 6 | PackageCache, 7 | Snapshot, 8 | submitSnapshot 9 | } from '@github/dependency-submission-toolkit' 10 | import { PackageURL } from 'packageurl-js' 11 | 12 | // top-level structure from the output of 'npm list' 13 | type NpmPackage = { name: string; version: string; dependencies: Dependencies } 14 | 15 | type Dependency = { 16 | version: string 17 | dependencies?: Dependencies 18 | } 19 | 20 | type Dependencies = { [name: string]: Dependency } 21 | 22 | /** 23 | * parseNameAndNamespace parses the name and namespace from a NPM package name. 24 | * Namespace and name are URL-safe encoded, as expected by PackageURL 25 | * 26 | * @param {string} npmDepName 27 | * @returns {[string, string]} tuple of namespace and name 28 | */ 29 | export function parseNameAndNamespace(npmDepName: string): [string, string] { 30 | const namespaceAndName = npmDepName.split('/') 31 | 32 | if (namespaceAndName.length === 1) { 33 | // biome-ignore lint/style/noNonNullAssertion: exist because of the if statement 34 | return ['', encodeURIComponent(namespaceAndName[0]!)] 35 | } 36 | if (namespaceAndName.length === 2) { 37 | return [ 38 | // biome-ignore lint/style/noNonNullAssertion: exist because of the if statement 39 | encodeURIComponent(namespaceAndName[0]!), 40 | // biome-ignore lint/style/noNonNullAssertion: exist because of the if statement 41 | encodeURIComponent(namespaceAndName[1]!) 42 | ] 43 | } 44 | throw new Error( 45 | `expectation violated: package '${npmDepName}' has more than one slash (/) in name` 46 | ) 47 | } 48 | 49 | /** 50 | * parseDependencies recursively parses the dependency tree provided by 'npm 51 | * list' and returns an array of the top-level parent packages. If a package 52 | * has already been added to the PackageCache, it does not reprocess its dependencies. 53 | */ 54 | export function parseDependencies( 55 | cache: PackageCache, 56 | dependencies: Dependencies 57 | ): Array { 58 | return Object.entries(dependencies).map(([depName, dep]) => { 59 | const [namespace, name] = parseNameAndNamespace(depName) 60 | const purl = new PackageURL('npm', namespace, name, dep.version, null, null) 61 | 62 | // if the package has already been added to the cache, return the package early 63 | if (cache.hasPackage(purl)) { 64 | return cache.package(purl) 65 | } 66 | 67 | const pkgs = [] 68 | // post-order traversal of the dependency tree with recursion. 69 | // recursion is not expected to blow the stack as dependency trees are 70 | // unlikely to have significant depth 71 | if (dep.dependencies !== undefined) { 72 | pkgs.push(...parseDependencies(cache, dep.dependencies)) 73 | } 74 | 75 | return cache 76 | .package(new PackageURL('npm', namespace, name, dep.version, null, null)) 77 | .dependsOnPackages(pkgs) 78 | }) 79 | } 80 | 81 | /** 82 | * createBuildTarget creates a BuildTarget--a specialized sub-class of Manifest 83 | * intended to capture the dependencies of a specific build-target, rather 84 | * than all packages provided by the manifest environment. It parses the output 85 | * from 'npm list' and distinguishes between direct dependencies (those the 86 | * build-target explicity depends on) and indirect (transitive dependencies of 87 | * the direct dependencies). It identifies all dependency packages as 88 | * 'runtime', since no development packages are included in a build-target. 89 | * 90 | * @param {NpmPackage} npmPackage 91 | * @returns {BuildTarget} 92 | */ 93 | export function createBuildTarget(npmPackage: NpmPackage): BuildTarget { 94 | const cache = new PackageCache() 95 | const topLevelDependencies = parseDependencies(cache, npmPackage.dependencies) 96 | const buildTarget = new BuildTarget(npmPackage.name) 97 | for (const dep of topLevelDependencies) { 98 | buildTarget.addBuildDependency(dep) 99 | } 100 | return buildTarget 101 | } 102 | 103 | // This program uses 'npm list' to provide a list of all production 104 | // (non-development) dependencies and all transitive dependencies. This 105 | // provides transitive relationships unlike package.json, and output can be 106 | // configured to avoid issues present with parsing package-lock.json (such as 107 | // inclusion of workspace packages). This is provided as example to help guide 108 | // development. 109 | export async function main() { 110 | const npmPackageDirectory = core.getInput('npm-package-directory') 111 | const prodPackages = await exec.getExecOutput( 112 | 'npm', 113 | ['list', '--all', '--json', '--omit', 'dev'], 114 | { cwd: npmPackageDirectory } 115 | ) 116 | if (prodPackages.exitCode !== 0) { 117 | core.error(prodPackages.stderr) 118 | core.setFailed("'npm ls' failed!") 119 | return 120 | } 121 | const npmPackage = JSON.parse(prodPackages.stdout) as NpmPackage 122 | const buildTarget = createBuildTarget(npmPackage) 123 | const snapshot = new Snapshot({ 124 | name: 'example NPM detector', 125 | url: 'https://github.com/github/dependency-submission-toolkit/tree/main/example', 126 | version: '0.0.1' 127 | }) 128 | snapshot.addManifest(buildTarget) 129 | submitSnapshot(snapshot) 130 | } 131 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@github/npm-dependency-submission-example", 3 | "private": true, 4 | "description": "[UNPUBLISHED PACKAGE!] Example using the Dependency Submission Toolkit and npm list", 5 | "type": "module", 6 | "scripts": { 7 | "all": "npm run type-check && npm run build && npm run test", 8 | "build": "ncc build index.ts --source-map --license=LICENSE.txt --out dist", 9 | "test": "vitest run", 10 | "test:watch": "vitest watch", 11 | "type-check": "tsc" 12 | }, 13 | "dependencies": { 14 | "@actions/exec": "^1.1.1", 15 | "@github/dependency-submission-toolkit": "file:../", 16 | "packageurl-js": "^1.2.1" 17 | }, 18 | "devDependencies": { 19 | "@tsconfig/strictest": "^2.0.2", 20 | "@vercel/ncc": "^0.38.1", 21 | "typescript": "^5.3.3", 22 | "vitest": "^3.0.8" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "isolatedModules": true, 4 | "module": "ESNext", 5 | "moduleDetection": "force", 6 | "moduleResolution": "Bundler", 7 | "noEmit": true 8 | }, 9 | "exclude": ["dist", "node_modules"], 10 | "extends": "@tsconfig/strictest/tsconfig.json" 11 | } 12 | -------------------------------------------------------------------------------- /ownership.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 1 3 | ownership: 4 | - team: github/dependency-graph 5 | repo: https://github.com/github/dependency-submission-toolkit 6 | name: dependency-submission-toolkit 7 | kind: moda 8 | long_name: dependency-submission-toolkit 9 | description: 'A TypeScript library for creating dependency snapshots and submitting them to the dependency submission API.' 10 | maintainer: jovel 11 | exec_sponsor: nerdneha 12 | product_manager: ahpook 13 | team_slack: dependency-graph 14 | qos: experimental 15 | tier: 3 16 | sev1: 17 | tta: 30d 18 | issue: https://github.com/github/dependency-submission-toolkit/issues 19 | sev2: 20 | tta: 30d 21 | issue: https://github.com/github/dependency-submission-toolkit/issues 22 | sev3: 23 | tta: 30d 24 | issue: https://github.com/github/dependency-submission-toolkit/issues 25 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@github/dependency-submission-toolkit", 3 | "version": "2.0.5", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@github/dependency-submission-toolkit", 9 | "version": "2.0.5", 10 | "license": "MIT", 11 | "workspaces": [ 12 | "example" 13 | ], 14 | "dependencies": { 15 | "@actions/core": "^1.10.1", 16 | "@actions/github": "^6.0.0", 17 | "@octokit/request-error": "^6.1.1", 18 | "@octokit/webhooks-types": "^7.5.0", 19 | "packageurl-js": "^1.2.1" 20 | }, 21 | "devDependencies": { 22 | "@biomejs/biome": "^1.7.0", 23 | "@tsconfig/strictest": "^2.0.5", 24 | "@types/node": "^20.12.7", 25 | "tsup": "^8.4.0", 26 | "typescript": "^5.4.5", 27 | "vitest": "^3.0.8" 28 | } 29 | }, 30 | "example": { 31 | "name": "@github/npm-dependency-submission-example", 32 | "dependencies": { 33 | "@actions/exec": "^1.1.1", 34 | "@github/dependency-submission-toolkit": "file:../", 35 | "packageurl-js": "^1.2.1" 36 | }, 37 | "devDependencies": { 38 | "@tsconfig/strictest": "^2.0.2", 39 | "@vercel/ncc": "^0.38.1", 40 | "typescript": "^5.3.3", 41 | "vitest": "^3.0.8" 42 | } 43 | }, 44 | "node_modules/@actions/core": { 45 | "version": "1.10.1", 46 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", 47 | "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", 48 | "dependencies": { 49 | "@actions/http-client": "^2.0.1", 50 | "uuid": "^8.3.2" 51 | } 52 | }, 53 | "node_modules/@actions/exec": { 54 | "version": "1.1.1", 55 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", 56 | "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", 57 | "dependencies": { 58 | "@actions/io": "^1.0.1" 59 | } 60 | }, 61 | "node_modules/@actions/github": { 62 | "version": "6.0.0", 63 | "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", 64 | "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", 65 | "dependencies": { 66 | "@actions/http-client": "^2.2.0", 67 | "@octokit/core": "^5.0.1", 68 | "@octokit/plugin-paginate-rest": "^9.0.0", 69 | "@octokit/plugin-rest-endpoint-methods": "^10.0.0" 70 | } 71 | }, 72 | "node_modules/@actions/http-client": { 73 | "version": "2.2.1", 74 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", 75 | "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", 76 | "dependencies": { 77 | "tunnel": "^0.0.6", 78 | "undici": "^5.25.4" 79 | } 80 | }, 81 | "node_modules/@actions/io": { 82 | "version": "1.1.3", 83 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", 84 | "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" 85 | }, 86 | "node_modules/@biomejs/biome": { 87 | "version": "1.7.0", 88 | "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.7.0.tgz", 89 | "integrity": "sha512-mejiRhnAq6UrXtYvjWJUKdstcT58n0/FfKemFf3d2Ou0HxOdS88HQmWtQ/UgyZvOEPD572YbFTb6IheyROpqkw==", 90 | "dev": true, 91 | "hasInstallScript": true, 92 | "bin": { 93 | "biome": "bin/biome" 94 | }, 95 | "engines": { 96 | "node": ">=14.21.3" 97 | }, 98 | "funding": { 99 | "type": "opencollective", 100 | "url": "https://opencollective.com/biome" 101 | }, 102 | "optionalDependencies": { 103 | "@biomejs/cli-darwin-arm64": "1.7.0", 104 | "@biomejs/cli-darwin-x64": "1.7.0", 105 | "@biomejs/cli-linux-arm64": "1.7.0", 106 | "@biomejs/cli-linux-arm64-musl": "1.7.0", 107 | "@biomejs/cli-linux-x64": "1.7.0", 108 | "@biomejs/cli-linux-x64-musl": "1.7.0", 109 | "@biomejs/cli-win32-arm64": "1.7.0", 110 | "@biomejs/cli-win32-x64": "1.7.0" 111 | } 112 | }, 113 | "node_modules/@biomejs/cli-darwin-arm64": { 114 | "version": "1.7.0", 115 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.7.0.tgz", 116 | "integrity": "sha512-12TaeaKHU4SAZt0fQJ2bYk1jUb4foope7LmgDE5p3c0uMxd3mFkg1k7G721T+K6UHYULcSOQDsNNM8DhYi8Irg==", 117 | "cpu": [ 118 | "arm64" 119 | ], 120 | "dev": true, 121 | "optional": true, 122 | "os": [ 123 | "darwin" 124 | ], 125 | "engines": { 126 | "node": ">=14.21.3" 127 | } 128 | }, 129 | "node_modules/@biomejs/cli-darwin-x64": { 130 | "version": "1.7.0", 131 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.7.0.tgz", 132 | "integrity": "sha512-6Qq1BSIB0cpp0cQNqO/+EiUV7FE3jMpF6w7+AgIBXp0oJxUWb2Ff0RDZdO9bfzkimXD58j0vGpNHMGnCcjDV2Q==", 133 | "cpu": [ 134 | "x64" 135 | ], 136 | "dev": true, 137 | "optional": true, 138 | "os": [ 139 | "darwin" 140 | ], 141 | "engines": { 142 | "node": ">=14.21.3" 143 | } 144 | }, 145 | "node_modules/@biomejs/cli-linux-arm64": { 146 | "version": "1.7.0", 147 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.7.0.tgz", 148 | "integrity": "sha512-GwSci7xBJ2j1CrdDXDUVXnUtrvypEz/xmiYPpFeVdlX5p95eXx+7FekPPbJfhGGw5WKSsKZ+V8AAlbN+kUwJWw==", 149 | "cpu": [ 150 | "arm64" 151 | ], 152 | "dev": true, 153 | "optional": true, 154 | "os": [ 155 | "linux" 156 | ], 157 | "engines": { 158 | "node": ">=14.21.3" 159 | } 160 | }, 161 | "node_modules/@biomejs/cli-linux-arm64-musl": { 162 | "version": "1.7.0", 163 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.7.0.tgz", 164 | "integrity": "sha512-pwIY80nU7SAxrVVZ6HD9ah1pruwh9ZqlSR0Nvbg4ZJqQa0POhiB+RJx7+/1Ml2mTZdrl8kb/YiwQpD16uwb5wg==", 165 | "cpu": [ 166 | "arm64" 167 | ], 168 | "dev": true, 169 | "optional": true, 170 | "os": [ 171 | "linux" 172 | ], 173 | "engines": { 174 | "node": ">=14.21.3" 175 | } 176 | }, 177 | "node_modules/@biomejs/cli-linux-x64": { 178 | "version": "1.7.0", 179 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.7.0.tgz", 180 | "integrity": "sha512-1y+odKQsyHcw0JCGRuqhbx7Y6jxOVSh4lGIVDdJxW1b55yD22DY1kcMEfhUte6f95OIc2uqfkwtiI6xQAiZJdw==", 181 | "cpu": [ 182 | "x64" 183 | ], 184 | "dev": true, 185 | "optional": true, 186 | "os": [ 187 | "linux" 188 | ], 189 | "engines": { 190 | "node": ">=14.21.3" 191 | } 192 | }, 193 | "node_modules/@biomejs/cli-linux-x64-musl": { 194 | "version": "1.7.0", 195 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.7.0.tgz", 196 | "integrity": "sha512-KzCA0mW4LSbCd7XZWaEJvTOTTBjfJoVEXkfq1fsXxww1HB+ww5PGMbhbIcbYCsj2CTJUifeD5hOkyuBVppU1xQ==", 197 | "cpu": [ 198 | "x64" 199 | ], 200 | "dev": true, 201 | "optional": true, 202 | "os": [ 203 | "linux" 204 | ], 205 | "engines": { 206 | "node": ">=14.21.3" 207 | } 208 | }, 209 | "node_modules/@biomejs/cli-win32-arm64": { 210 | "version": "1.7.0", 211 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.7.0.tgz", 212 | "integrity": "sha512-AvLDUYZBpOUFgS/mni4VruIoVV3uSGbKSkZQBPXsHgL0w4KttLll3NBrVanmWxOHsom6C6ocHLyfAY8HUc8TXg==", 213 | "cpu": [ 214 | "arm64" 215 | ], 216 | "dev": true, 217 | "optional": true, 218 | "os": [ 219 | "win32" 220 | ], 221 | "engines": { 222 | "node": ">=14.21.3" 223 | } 224 | }, 225 | "node_modules/@biomejs/cli-win32-x64": { 226 | "version": "1.7.0", 227 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.7.0.tgz", 228 | "integrity": "sha512-Pylm00BAAuLVb40IH9PC17432BTsY8K4pSUvhvgR1eaalnMaD6ug9SYJTTzKDbT6r24MPAGCTiSZERyhGkGzFQ==", 229 | "cpu": [ 230 | "x64" 231 | ], 232 | "dev": true, 233 | "optional": true, 234 | "os": [ 235 | "win32" 236 | ], 237 | "engines": { 238 | "node": ">=14.21.3" 239 | } 240 | }, 241 | "node_modules/@esbuild/aix-ppc64": { 242 | "version": "0.25.1", 243 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", 244 | "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", 245 | "cpu": [ 246 | "ppc64" 247 | ], 248 | "dev": true, 249 | "license": "MIT", 250 | "optional": true, 251 | "os": [ 252 | "aix" 253 | ], 254 | "engines": { 255 | "node": ">=18" 256 | } 257 | }, 258 | "node_modules/@esbuild/android-arm": { 259 | "version": "0.25.1", 260 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", 261 | "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", 262 | "cpu": [ 263 | "arm" 264 | ], 265 | "dev": true, 266 | "license": "MIT", 267 | "optional": true, 268 | "os": [ 269 | "android" 270 | ], 271 | "engines": { 272 | "node": ">=18" 273 | } 274 | }, 275 | "node_modules/@esbuild/android-arm64": { 276 | "version": "0.25.1", 277 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", 278 | "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", 279 | "cpu": [ 280 | "arm64" 281 | ], 282 | "dev": true, 283 | "license": "MIT", 284 | "optional": true, 285 | "os": [ 286 | "android" 287 | ], 288 | "engines": { 289 | "node": ">=18" 290 | } 291 | }, 292 | "node_modules/@esbuild/android-x64": { 293 | "version": "0.25.1", 294 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", 295 | "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", 296 | "cpu": [ 297 | "x64" 298 | ], 299 | "dev": true, 300 | "license": "MIT", 301 | "optional": true, 302 | "os": [ 303 | "android" 304 | ], 305 | "engines": { 306 | "node": ">=18" 307 | } 308 | }, 309 | "node_modules/@esbuild/darwin-arm64": { 310 | "version": "0.25.1", 311 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", 312 | "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", 313 | "cpu": [ 314 | "arm64" 315 | ], 316 | "dev": true, 317 | "license": "MIT", 318 | "optional": true, 319 | "os": [ 320 | "darwin" 321 | ], 322 | "engines": { 323 | "node": ">=18" 324 | } 325 | }, 326 | "node_modules/@esbuild/darwin-x64": { 327 | "version": "0.25.1", 328 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", 329 | "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", 330 | "cpu": [ 331 | "x64" 332 | ], 333 | "dev": true, 334 | "license": "MIT", 335 | "optional": true, 336 | "os": [ 337 | "darwin" 338 | ], 339 | "engines": { 340 | "node": ">=18" 341 | } 342 | }, 343 | "node_modules/@esbuild/freebsd-arm64": { 344 | "version": "0.25.1", 345 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", 346 | "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", 347 | "cpu": [ 348 | "arm64" 349 | ], 350 | "dev": true, 351 | "license": "MIT", 352 | "optional": true, 353 | "os": [ 354 | "freebsd" 355 | ], 356 | "engines": { 357 | "node": ">=18" 358 | } 359 | }, 360 | "node_modules/@esbuild/freebsd-x64": { 361 | "version": "0.25.1", 362 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", 363 | "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", 364 | "cpu": [ 365 | "x64" 366 | ], 367 | "dev": true, 368 | "license": "MIT", 369 | "optional": true, 370 | "os": [ 371 | "freebsd" 372 | ], 373 | "engines": { 374 | "node": ">=18" 375 | } 376 | }, 377 | "node_modules/@esbuild/linux-arm": { 378 | "version": "0.25.1", 379 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", 380 | "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", 381 | "cpu": [ 382 | "arm" 383 | ], 384 | "dev": true, 385 | "license": "MIT", 386 | "optional": true, 387 | "os": [ 388 | "linux" 389 | ], 390 | "engines": { 391 | "node": ">=18" 392 | } 393 | }, 394 | "node_modules/@esbuild/linux-arm64": { 395 | "version": "0.25.1", 396 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", 397 | "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", 398 | "cpu": [ 399 | "arm64" 400 | ], 401 | "dev": true, 402 | "license": "MIT", 403 | "optional": true, 404 | "os": [ 405 | "linux" 406 | ], 407 | "engines": { 408 | "node": ">=18" 409 | } 410 | }, 411 | "node_modules/@esbuild/linux-ia32": { 412 | "version": "0.25.1", 413 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", 414 | "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", 415 | "cpu": [ 416 | "ia32" 417 | ], 418 | "dev": true, 419 | "license": "MIT", 420 | "optional": true, 421 | "os": [ 422 | "linux" 423 | ], 424 | "engines": { 425 | "node": ">=18" 426 | } 427 | }, 428 | "node_modules/@esbuild/linux-loong64": { 429 | "version": "0.25.1", 430 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", 431 | "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", 432 | "cpu": [ 433 | "loong64" 434 | ], 435 | "dev": true, 436 | "license": "MIT", 437 | "optional": true, 438 | "os": [ 439 | "linux" 440 | ], 441 | "engines": { 442 | "node": ">=18" 443 | } 444 | }, 445 | "node_modules/@esbuild/linux-mips64el": { 446 | "version": "0.25.1", 447 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", 448 | "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", 449 | "cpu": [ 450 | "mips64el" 451 | ], 452 | "dev": true, 453 | "license": "MIT", 454 | "optional": true, 455 | "os": [ 456 | "linux" 457 | ], 458 | "engines": { 459 | "node": ">=18" 460 | } 461 | }, 462 | "node_modules/@esbuild/linux-ppc64": { 463 | "version": "0.25.1", 464 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", 465 | "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", 466 | "cpu": [ 467 | "ppc64" 468 | ], 469 | "dev": true, 470 | "license": "MIT", 471 | "optional": true, 472 | "os": [ 473 | "linux" 474 | ], 475 | "engines": { 476 | "node": ">=18" 477 | } 478 | }, 479 | "node_modules/@esbuild/linux-riscv64": { 480 | "version": "0.25.1", 481 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", 482 | "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", 483 | "cpu": [ 484 | "riscv64" 485 | ], 486 | "dev": true, 487 | "license": "MIT", 488 | "optional": true, 489 | "os": [ 490 | "linux" 491 | ], 492 | "engines": { 493 | "node": ">=18" 494 | } 495 | }, 496 | "node_modules/@esbuild/linux-s390x": { 497 | "version": "0.25.1", 498 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", 499 | "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", 500 | "cpu": [ 501 | "s390x" 502 | ], 503 | "dev": true, 504 | "license": "MIT", 505 | "optional": true, 506 | "os": [ 507 | "linux" 508 | ], 509 | "engines": { 510 | "node": ">=18" 511 | } 512 | }, 513 | "node_modules/@esbuild/linux-x64": { 514 | "version": "0.25.1", 515 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", 516 | "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", 517 | "cpu": [ 518 | "x64" 519 | ], 520 | "dev": true, 521 | "license": "MIT", 522 | "optional": true, 523 | "os": [ 524 | "linux" 525 | ], 526 | "engines": { 527 | "node": ">=18" 528 | } 529 | }, 530 | "node_modules/@esbuild/netbsd-arm64": { 531 | "version": "0.25.1", 532 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", 533 | "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", 534 | "cpu": [ 535 | "arm64" 536 | ], 537 | "dev": true, 538 | "license": "MIT", 539 | "optional": true, 540 | "os": [ 541 | "netbsd" 542 | ], 543 | "engines": { 544 | "node": ">=18" 545 | } 546 | }, 547 | "node_modules/@esbuild/netbsd-x64": { 548 | "version": "0.25.1", 549 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", 550 | "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", 551 | "cpu": [ 552 | "x64" 553 | ], 554 | "dev": true, 555 | "license": "MIT", 556 | "optional": true, 557 | "os": [ 558 | "netbsd" 559 | ], 560 | "engines": { 561 | "node": ">=18" 562 | } 563 | }, 564 | "node_modules/@esbuild/openbsd-arm64": { 565 | "version": "0.25.1", 566 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", 567 | "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", 568 | "cpu": [ 569 | "arm64" 570 | ], 571 | "dev": true, 572 | "license": "MIT", 573 | "optional": true, 574 | "os": [ 575 | "openbsd" 576 | ], 577 | "engines": { 578 | "node": ">=18" 579 | } 580 | }, 581 | "node_modules/@esbuild/openbsd-x64": { 582 | "version": "0.25.1", 583 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", 584 | "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", 585 | "cpu": [ 586 | "x64" 587 | ], 588 | "dev": true, 589 | "license": "MIT", 590 | "optional": true, 591 | "os": [ 592 | "openbsd" 593 | ], 594 | "engines": { 595 | "node": ">=18" 596 | } 597 | }, 598 | "node_modules/@esbuild/sunos-x64": { 599 | "version": "0.25.1", 600 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", 601 | "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", 602 | "cpu": [ 603 | "x64" 604 | ], 605 | "dev": true, 606 | "license": "MIT", 607 | "optional": true, 608 | "os": [ 609 | "sunos" 610 | ], 611 | "engines": { 612 | "node": ">=18" 613 | } 614 | }, 615 | "node_modules/@esbuild/win32-arm64": { 616 | "version": "0.25.1", 617 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", 618 | "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", 619 | "cpu": [ 620 | "arm64" 621 | ], 622 | "dev": true, 623 | "license": "MIT", 624 | "optional": true, 625 | "os": [ 626 | "win32" 627 | ], 628 | "engines": { 629 | "node": ">=18" 630 | } 631 | }, 632 | "node_modules/@esbuild/win32-ia32": { 633 | "version": "0.25.1", 634 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", 635 | "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", 636 | "cpu": [ 637 | "ia32" 638 | ], 639 | "dev": true, 640 | "license": "MIT", 641 | "optional": true, 642 | "os": [ 643 | "win32" 644 | ], 645 | "engines": { 646 | "node": ">=18" 647 | } 648 | }, 649 | "node_modules/@esbuild/win32-x64": { 650 | "version": "0.25.1", 651 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", 652 | "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", 653 | "cpu": [ 654 | "x64" 655 | ], 656 | "dev": true, 657 | "license": "MIT", 658 | "optional": true, 659 | "os": [ 660 | "win32" 661 | ], 662 | "engines": { 663 | "node": ">=18" 664 | } 665 | }, 666 | "node_modules/@fastify/busboy": { 667 | "version": "2.1.1", 668 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 669 | "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 670 | "engines": { 671 | "node": ">=14" 672 | } 673 | }, 674 | "node_modules/@github/dependency-submission-toolkit": { 675 | "resolved": "", 676 | "link": true 677 | }, 678 | "node_modules/@github/npm-dependency-submission-example": { 679 | "resolved": "example", 680 | "link": true 681 | }, 682 | "node_modules/@isaacs/cliui": { 683 | "version": "8.0.2", 684 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 685 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 686 | "dev": true, 687 | "dependencies": { 688 | "string-width": "^5.1.2", 689 | "string-width-cjs": "npm:string-width@^4.2.0", 690 | "strip-ansi": "^7.0.1", 691 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 692 | "wrap-ansi": "^8.1.0", 693 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 694 | }, 695 | "engines": { 696 | "node": ">=12" 697 | } 698 | }, 699 | "node_modules/@jridgewell/gen-mapping": { 700 | "version": "0.3.5", 701 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", 702 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", 703 | "dev": true, 704 | "dependencies": { 705 | "@jridgewell/set-array": "^1.2.1", 706 | "@jridgewell/sourcemap-codec": "^1.4.10", 707 | "@jridgewell/trace-mapping": "^0.3.24" 708 | }, 709 | "engines": { 710 | "node": ">=6.0.0" 711 | } 712 | }, 713 | "node_modules/@jridgewell/resolve-uri": { 714 | "version": "3.1.2", 715 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 716 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 717 | "dev": true, 718 | "engines": { 719 | "node": ">=6.0.0" 720 | } 721 | }, 722 | "node_modules/@jridgewell/set-array": { 723 | "version": "1.2.1", 724 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 725 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 726 | "dev": true, 727 | "engines": { 728 | "node": ">=6.0.0" 729 | } 730 | }, 731 | "node_modules/@jridgewell/sourcemap-codec": { 732 | "version": "1.5.0", 733 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 734 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 735 | "dev": true, 736 | "license": "MIT" 737 | }, 738 | "node_modules/@jridgewell/trace-mapping": { 739 | "version": "0.3.25", 740 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 741 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 742 | "dev": true, 743 | "dependencies": { 744 | "@jridgewell/resolve-uri": "^3.1.0", 745 | "@jridgewell/sourcemap-codec": "^1.4.14" 746 | } 747 | }, 748 | "node_modules/@octokit/auth-token": { 749 | "version": "4.0.0", 750 | "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", 751 | "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", 752 | "engines": { 753 | "node": ">= 18" 754 | } 755 | }, 756 | "node_modules/@octokit/core": { 757 | "version": "5.2.0", 758 | "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", 759 | "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", 760 | "dependencies": { 761 | "@octokit/auth-token": "^4.0.0", 762 | "@octokit/graphql": "^7.1.0", 763 | "@octokit/request": "^8.3.1", 764 | "@octokit/request-error": "^5.1.0", 765 | "@octokit/types": "^13.0.0", 766 | "before-after-hook": "^2.2.0", 767 | "universal-user-agent": "^6.0.0" 768 | }, 769 | "engines": { 770 | "node": ">= 18" 771 | } 772 | }, 773 | "node_modules/@octokit/core/node_modules/@octokit/request-error": { 774 | "version": "5.1.1", 775 | "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", 776 | "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", 777 | "license": "MIT", 778 | "dependencies": { 779 | "@octokit/types": "^13.1.0", 780 | "deprecation": "^2.0.0", 781 | "once": "^1.4.0" 782 | }, 783 | "engines": { 784 | "node": ">= 18" 785 | } 786 | }, 787 | "node_modules/@octokit/endpoint": { 788 | "version": "9.0.6", 789 | "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", 790 | "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", 791 | "dependencies": { 792 | "@octokit/types": "^13.1.0", 793 | "universal-user-agent": "^6.0.0" 794 | }, 795 | "engines": { 796 | "node": ">= 18" 797 | } 798 | }, 799 | "node_modules/@octokit/graphql": { 800 | "version": "7.1.0", 801 | "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", 802 | "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", 803 | "dependencies": { 804 | "@octokit/request": "^8.3.0", 805 | "@octokit/types": "^13.0.0", 806 | "universal-user-agent": "^6.0.0" 807 | }, 808 | "engines": { 809 | "node": ">= 18" 810 | } 811 | }, 812 | "node_modules/@octokit/openapi-types": { 813 | "version": "23.0.1", 814 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", 815 | "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==" 816 | }, 817 | "node_modules/@octokit/plugin-paginate-rest": { 818 | "version": "9.2.2", 819 | "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", 820 | "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", 821 | "dependencies": { 822 | "@octokit/types": "^12.6.0" 823 | }, 824 | "engines": { 825 | "node": ">= 18" 826 | }, 827 | "peerDependencies": { 828 | "@octokit/core": "5" 829 | } 830 | }, 831 | "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { 832 | "version": "20.0.0", 833 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", 834 | "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==" 835 | }, 836 | "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { 837 | "version": "12.6.0", 838 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", 839 | "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", 840 | "dependencies": { 841 | "@octokit/openapi-types": "^20.0.0" 842 | } 843 | }, 844 | "node_modules/@octokit/plugin-rest-endpoint-methods": { 845 | "version": "10.4.1", 846 | "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", 847 | "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", 848 | "dependencies": { 849 | "@octokit/types": "^12.6.0" 850 | }, 851 | "engines": { 852 | "node": ">= 18" 853 | }, 854 | "peerDependencies": { 855 | "@octokit/core": "5" 856 | } 857 | }, 858 | "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { 859 | "version": "20.0.0", 860 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", 861 | "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==" 862 | }, 863 | "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { 864 | "version": "12.6.0", 865 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", 866 | "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", 867 | "dependencies": { 868 | "@octokit/openapi-types": "^20.0.0" 869 | } 870 | }, 871 | "node_modules/@octokit/request": { 872 | "version": "8.4.1", 873 | "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", 874 | "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", 875 | "dependencies": { 876 | "@octokit/endpoint": "^9.0.6", 877 | "@octokit/request-error": "^5.1.1", 878 | "@octokit/types": "^13.1.0", 879 | "universal-user-agent": "^6.0.0" 880 | }, 881 | "engines": { 882 | "node": ">= 18" 883 | } 884 | }, 885 | "node_modules/@octokit/request-error": { 886 | "version": "6.1.7", 887 | "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", 888 | "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", 889 | "dependencies": { 890 | "@octokit/types": "^13.6.2" 891 | }, 892 | "engines": { 893 | "node": ">= 18" 894 | } 895 | }, 896 | "node_modules/@octokit/request/node_modules/@octokit/request-error": { 897 | "version": "5.1.1", 898 | "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", 899 | "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", 900 | "dependencies": { 901 | "@octokit/types": "^13.1.0", 902 | "deprecation": "^2.0.0", 903 | "once": "^1.4.0" 904 | }, 905 | "engines": { 906 | "node": ">= 18" 907 | } 908 | }, 909 | "node_modules/@octokit/types": { 910 | "version": "13.8.0", 911 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", 912 | "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", 913 | "dependencies": { 914 | "@octokit/openapi-types": "^23.0.1" 915 | } 916 | }, 917 | "node_modules/@octokit/webhooks-types": { 918 | "version": "7.5.0", 919 | "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.5.0.tgz", 920 | "integrity": "sha512-oFypF1oD0z1x4qi+Ff4ienJ/iZ3GBXoht+0B+x8gMIWiNhRJZADYO+2KOh03ZGOX8WF6iJELZWw+giHieBO7rg==" 921 | }, 922 | "node_modules/@pkgjs/parseargs": { 923 | "version": "0.11.0", 924 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 925 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 926 | "dev": true, 927 | "optional": true, 928 | "engines": { 929 | "node": ">=14" 930 | } 931 | }, 932 | "node_modules/@rollup/rollup-android-arm-eabi": { 933 | "version": "4.34.9", 934 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.9.tgz", 935 | "integrity": "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==", 936 | "cpu": [ 937 | "arm" 938 | ], 939 | "dev": true, 940 | "license": "MIT", 941 | "optional": true, 942 | "os": [ 943 | "android" 944 | ] 945 | }, 946 | "node_modules/@rollup/rollup-android-arm64": { 947 | "version": "4.34.9", 948 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.9.tgz", 949 | "integrity": "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==", 950 | "cpu": [ 951 | "arm64" 952 | ], 953 | "dev": true, 954 | "license": "MIT", 955 | "optional": true, 956 | "os": [ 957 | "android" 958 | ] 959 | }, 960 | "node_modules/@rollup/rollup-darwin-arm64": { 961 | "version": "4.34.9", 962 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz", 963 | "integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==", 964 | "cpu": [ 965 | "arm64" 966 | ], 967 | "dev": true, 968 | "license": "MIT", 969 | "optional": true, 970 | "os": [ 971 | "darwin" 972 | ] 973 | }, 974 | "node_modules/@rollup/rollup-darwin-x64": { 975 | "version": "4.34.9", 976 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz", 977 | "integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==", 978 | "cpu": [ 979 | "x64" 980 | ], 981 | "dev": true, 982 | "license": "MIT", 983 | "optional": true, 984 | "os": [ 985 | "darwin" 986 | ] 987 | }, 988 | "node_modules/@rollup/rollup-freebsd-arm64": { 989 | "version": "4.34.9", 990 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.9.tgz", 991 | "integrity": "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==", 992 | "cpu": [ 993 | "arm64" 994 | ], 995 | "dev": true, 996 | "license": "MIT", 997 | "optional": true, 998 | "os": [ 999 | "freebsd" 1000 | ] 1001 | }, 1002 | "node_modules/@rollup/rollup-freebsd-x64": { 1003 | "version": "4.34.9", 1004 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.9.tgz", 1005 | "integrity": "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==", 1006 | "cpu": [ 1007 | "x64" 1008 | ], 1009 | "dev": true, 1010 | "license": "MIT", 1011 | "optional": true, 1012 | "os": [ 1013 | "freebsd" 1014 | ] 1015 | }, 1016 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 1017 | "version": "4.34.9", 1018 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.9.tgz", 1019 | "integrity": "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==", 1020 | "cpu": [ 1021 | "arm" 1022 | ], 1023 | "dev": true, 1024 | "license": "MIT", 1025 | "optional": true, 1026 | "os": [ 1027 | "linux" 1028 | ] 1029 | }, 1030 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 1031 | "version": "4.34.9", 1032 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.9.tgz", 1033 | "integrity": "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==", 1034 | "cpu": [ 1035 | "arm" 1036 | ], 1037 | "dev": true, 1038 | "license": "MIT", 1039 | "optional": true, 1040 | "os": [ 1041 | "linux" 1042 | ] 1043 | }, 1044 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 1045 | "version": "4.34.9", 1046 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz", 1047 | "integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==", 1048 | "cpu": [ 1049 | "arm64" 1050 | ], 1051 | "dev": true, 1052 | "license": "MIT", 1053 | "optional": true, 1054 | "os": [ 1055 | "linux" 1056 | ] 1057 | }, 1058 | "node_modules/@rollup/rollup-linux-arm64-musl": { 1059 | "version": "4.34.9", 1060 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz", 1061 | "integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==", 1062 | "cpu": [ 1063 | "arm64" 1064 | ], 1065 | "dev": true, 1066 | "license": "MIT", 1067 | "optional": true, 1068 | "os": [ 1069 | "linux" 1070 | ] 1071 | }, 1072 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 1073 | "version": "4.34.9", 1074 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.9.tgz", 1075 | "integrity": "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==", 1076 | "cpu": [ 1077 | "loong64" 1078 | ], 1079 | "dev": true, 1080 | "license": "MIT", 1081 | "optional": true, 1082 | "os": [ 1083 | "linux" 1084 | ] 1085 | }, 1086 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 1087 | "version": "4.34.9", 1088 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.9.tgz", 1089 | "integrity": "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==", 1090 | "cpu": [ 1091 | "ppc64" 1092 | ], 1093 | "dev": true, 1094 | "license": "MIT", 1095 | "optional": true, 1096 | "os": [ 1097 | "linux" 1098 | ] 1099 | }, 1100 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 1101 | "version": "4.34.9", 1102 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.9.tgz", 1103 | "integrity": "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==", 1104 | "cpu": [ 1105 | "riscv64" 1106 | ], 1107 | "dev": true, 1108 | "license": "MIT", 1109 | "optional": true, 1110 | "os": [ 1111 | "linux" 1112 | ] 1113 | }, 1114 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 1115 | "version": "4.34.9", 1116 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.9.tgz", 1117 | "integrity": "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==", 1118 | "cpu": [ 1119 | "s390x" 1120 | ], 1121 | "dev": true, 1122 | "license": "MIT", 1123 | "optional": true, 1124 | "os": [ 1125 | "linux" 1126 | ] 1127 | }, 1128 | "node_modules/@rollup/rollup-linux-x64-gnu": { 1129 | "version": "4.34.9", 1130 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz", 1131 | "integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==", 1132 | "cpu": [ 1133 | "x64" 1134 | ], 1135 | "dev": true, 1136 | "license": "MIT", 1137 | "optional": true, 1138 | "os": [ 1139 | "linux" 1140 | ] 1141 | }, 1142 | "node_modules/@rollup/rollup-linux-x64-musl": { 1143 | "version": "4.34.9", 1144 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz", 1145 | "integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==", 1146 | "cpu": [ 1147 | "x64" 1148 | ], 1149 | "dev": true, 1150 | "license": "MIT", 1151 | "optional": true, 1152 | "os": [ 1153 | "linux" 1154 | ] 1155 | }, 1156 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 1157 | "version": "4.34.9", 1158 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz", 1159 | "integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==", 1160 | "cpu": [ 1161 | "arm64" 1162 | ], 1163 | "dev": true, 1164 | "license": "MIT", 1165 | "optional": true, 1166 | "os": [ 1167 | "win32" 1168 | ] 1169 | }, 1170 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 1171 | "version": "4.34.9", 1172 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.9.tgz", 1173 | "integrity": "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==", 1174 | "cpu": [ 1175 | "ia32" 1176 | ], 1177 | "dev": true, 1178 | "license": "MIT", 1179 | "optional": true, 1180 | "os": [ 1181 | "win32" 1182 | ] 1183 | }, 1184 | "node_modules/@rollup/rollup-win32-x64-msvc": { 1185 | "version": "4.34.9", 1186 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz", 1187 | "integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==", 1188 | "cpu": [ 1189 | "x64" 1190 | ], 1191 | "dev": true, 1192 | "license": "MIT", 1193 | "optional": true, 1194 | "os": [ 1195 | "win32" 1196 | ] 1197 | }, 1198 | "node_modules/@tsconfig/strictest": { 1199 | "version": "2.0.5", 1200 | "resolved": "https://registry.npmjs.org/@tsconfig/strictest/-/strictest-2.0.5.tgz", 1201 | "integrity": "sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg==", 1202 | "dev": true 1203 | }, 1204 | "node_modules/@types/estree": { 1205 | "version": "1.0.6", 1206 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 1207 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 1208 | "dev": true, 1209 | "license": "MIT" 1210 | }, 1211 | "node_modules/@types/node": { 1212 | "version": "20.12.7", 1213 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", 1214 | "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", 1215 | "dev": true, 1216 | "dependencies": { 1217 | "undici-types": "~5.26.4" 1218 | } 1219 | }, 1220 | "node_modules/@vercel/ncc": { 1221 | "version": "0.38.1", 1222 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", 1223 | "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", 1224 | "dev": true, 1225 | "bin": { 1226 | "ncc": "dist/ncc/cli.js" 1227 | } 1228 | }, 1229 | "node_modules/@vitest/expect": { 1230 | "version": "3.1.2", 1231 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", 1232 | "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", 1233 | "dev": true, 1234 | "dependencies": { 1235 | "@vitest/spy": "3.1.2", 1236 | "@vitest/utils": "3.1.2", 1237 | "chai": "^5.2.0", 1238 | "tinyrainbow": "^2.0.0" 1239 | }, 1240 | "funding": { 1241 | "url": "https://opencollective.com/vitest" 1242 | } 1243 | }, 1244 | "node_modules/@vitest/mocker": { 1245 | "version": "3.1.2", 1246 | "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", 1247 | "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", 1248 | "dev": true, 1249 | "dependencies": { 1250 | "@vitest/spy": "3.1.2", 1251 | "estree-walker": "^3.0.3", 1252 | "magic-string": "^0.30.17" 1253 | }, 1254 | "funding": { 1255 | "url": "https://opencollective.com/vitest" 1256 | }, 1257 | "peerDependencies": { 1258 | "msw": "^2.4.9", 1259 | "vite": "^5.0.0 || ^6.0.0" 1260 | }, 1261 | "peerDependenciesMeta": { 1262 | "msw": { 1263 | "optional": true 1264 | }, 1265 | "vite": { 1266 | "optional": true 1267 | } 1268 | } 1269 | }, 1270 | "node_modules/@vitest/pretty-format": { 1271 | "version": "3.1.2", 1272 | "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", 1273 | "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", 1274 | "dev": true, 1275 | "dependencies": { 1276 | "tinyrainbow": "^2.0.0" 1277 | }, 1278 | "funding": { 1279 | "url": "https://opencollective.com/vitest" 1280 | } 1281 | }, 1282 | "node_modules/@vitest/runner": { 1283 | "version": "3.1.2", 1284 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", 1285 | "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", 1286 | "dev": true, 1287 | "dependencies": { 1288 | "@vitest/utils": "3.1.2", 1289 | "pathe": "^2.0.3" 1290 | }, 1291 | "funding": { 1292 | "url": "https://opencollective.com/vitest" 1293 | } 1294 | }, 1295 | "node_modules/@vitest/snapshot": { 1296 | "version": "3.1.2", 1297 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", 1298 | "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", 1299 | "dev": true, 1300 | "dependencies": { 1301 | "@vitest/pretty-format": "3.1.2", 1302 | "magic-string": "^0.30.17", 1303 | "pathe": "^2.0.3" 1304 | }, 1305 | "funding": { 1306 | "url": "https://opencollective.com/vitest" 1307 | } 1308 | }, 1309 | "node_modules/@vitest/spy": { 1310 | "version": "3.1.2", 1311 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", 1312 | "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", 1313 | "dev": true, 1314 | "dependencies": { 1315 | "tinyspy": "^3.0.2" 1316 | }, 1317 | "funding": { 1318 | "url": "https://opencollective.com/vitest" 1319 | } 1320 | }, 1321 | "node_modules/@vitest/utils": { 1322 | "version": "3.1.2", 1323 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", 1324 | "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", 1325 | "dev": true, 1326 | "dependencies": { 1327 | "@vitest/pretty-format": "3.1.2", 1328 | "loupe": "^3.1.3", 1329 | "tinyrainbow": "^2.0.0" 1330 | }, 1331 | "funding": { 1332 | "url": "https://opencollective.com/vitest" 1333 | } 1334 | }, 1335 | "node_modules/ansi-regex": { 1336 | "version": "6.0.1", 1337 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 1338 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 1339 | "dev": true, 1340 | "engines": { 1341 | "node": ">=12" 1342 | }, 1343 | "funding": { 1344 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 1345 | } 1346 | }, 1347 | "node_modules/any-promise": { 1348 | "version": "1.3.0", 1349 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 1350 | "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", 1351 | "dev": true 1352 | }, 1353 | "node_modules/assertion-error": { 1354 | "version": "2.0.1", 1355 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 1356 | "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 1357 | "dev": true, 1358 | "engines": { 1359 | "node": ">=12" 1360 | } 1361 | }, 1362 | "node_modules/balanced-match": { 1363 | "version": "1.0.2", 1364 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1365 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1366 | "dev": true 1367 | }, 1368 | "node_modules/before-after-hook": { 1369 | "version": "2.2.3", 1370 | "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", 1371 | "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" 1372 | }, 1373 | "node_modules/brace-expansion": { 1374 | "version": "2.0.1", 1375 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 1376 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 1377 | "dev": true, 1378 | "dependencies": { 1379 | "balanced-match": "^1.0.0" 1380 | } 1381 | }, 1382 | "node_modules/bundle-require": { 1383 | "version": "5.1.0", 1384 | "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", 1385 | "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", 1386 | "dev": true, 1387 | "license": "MIT", 1388 | "dependencies": { 1389 | "load-tsconfig": "^0.2.3" 1390 | }, 1391 | "engines": { 1392 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1393 | }, 1394 | "peerDependencies": { 1395 | "esbuild": ">=0.18" 1396 | } 1397 | }, 1398 | "node_modules/cac": { 1399 | "version": "6.7.14", 1400 | "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1401 | "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1402 | "dev": true, 1403 | "engines": { 1404 | "node": ">=8" 1405 | } 1406 | }, 1407 | "node_modules/chai": { 1408 | "version": "5.2.0", 1409 | "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", 1410 | "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", 1411 | "dev": true, 1412 | "dependencies": { 1413 | "assertion-error": "^2.0.1", 1414 | "check-error": "^2.1.1", 1415 | "deep-eql": "^5.0.1", 1416 | "loupe": "^3.1.0", 1417 | "pathval": "^2.0.0" 1418 | }, 1419 | "engines": { 1420 | "node": ">=12" 1421 | } 1422 | }, 1423 | "node_modules/check-error": { 1424 | "version": "2.1.1", 1425 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1426 | "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1427 | "dev": true, 1428 | "engines": { 1429 | "node": ">= 16" 1430 | } 1431 | }, 1432 | "node_modules/chokidar": { 1433 | "version": "4.0.3", 1434 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", 1435 | "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", 1436 | "dev": true, 1437 | "license": "MIT", 1438 | "dependencies": { 1439 | "readdirp": "^4.0.1" 1440 | }, 1441 | "engines": { 1442 | "node": ">= 14.16.0" 1443 | }, 1444 | "funding": { 1445 | "url": "https://paulmillr.com/funding/" 1446 | } 1447 | }, 1448 | "node_modules/color-convert": { 1449 | "version": "2.0.1", 1450 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1451 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1452 | "dev": true, 1453 | "dependencies": { 1454 | "color-name": "~1.1.4" 1455 | }, 1456 | "engines": { 1457 | "node": ">=7.0.0" 1458 | } 1459 | }, 1460 | "node_modules/color-name": { 1461 | "version": "1.1.4", 1462 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1463 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1464 | "dev": true 1465 | }, 1466 | "node_modules/commander": { 1467 | "version": "4.1.1", 1468 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 1469 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 1470 | "dev": true, 1471 | "engines": { 1472 | "node": ">= 6" 1473 | } 1474 | }, 1475 | "node_modules/consola": { 1476 | "version": "3.4.0", 1477 | "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.0.tgz", 1478 | "integrity": "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==", 1479 | "dev": true, 1480 | "license": "MIT", 1481 | "engines": { 1482 | "node": "^14.18.0 || >=16.10.0" 1483 | } 1484 | }, 1485 | "node_modules/cross-spawn": { 1486 | "version": "7.0.3", 1487 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 1488 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 1489 | "dev": true, 1490 | "dependencies": { 1491 | "path-key": "^3.1.0", 1492 | "shebang-command": "^2.0.0", 1493 | "which": "^2.0.1" 1494 | }, 1495 | "engines": { 1496 | "node": ">= 8" 1497 | } 1498 | }, 1499 | "node_modules/debug": { 1500 | "version": "4.4.0", 1501 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1502 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1503 | "dev": true, 1504 | "license": "MIT", 1505 | "dependencies": { 1506 | "ms": "^2.1.3" 1507 | }, 1508 | "engines": { 1509 | "node": ">=6.0" 1510 | }, 1511 | "peerDependenciesMeta": { 1512 | "supports-color": { 1513 | "optional": true 1514 | } 1515 | } 1516 | }, 1517 | "node_modules/deep-eql": { 1518 | "version": "5.0.2", 1519 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1520 | "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1521 | "dev": true, 1522 | "engines": { 1523 | "node": ">=6" 1524 | } 1525 | }, 1526 | "node_modules/deprecation": { 1527 | "version": "2.3.1", 1528 | "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", 1529 | "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" 1530 | }, 1531 | "node_modules/eastasianwidth": { 1532 | "version": "0.2.0", 1533 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 1534 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 1535 | "dev": true 1536 | }, 1537 | "node_modules/emoji-regex": { 1538 | "version": "9.2.2", 1539 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 1540 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 1541 | "dev": true 1542 | }, 1543 | "node_modules/es-module-lexer": { 1544 | "version": "1.6.0", 1545 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", 1546 | "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", 1547 | "dev": true 1548 | }, 1549 | "node_modules/esbuild": { 1550 | "version": "0.25.1", 1551 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", 1552 | "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", 1553 | "dev": true, 1554 | "hasInstallScript": true, 1555 | "license": "MIT", 1556 | "bin": { 1557 | "esbuild": "bin/esbuild" 1558 | }, 1559 | "engines": { 1560 | "node": ">=18" 1561 | }, 1562 | "optionalDependencies": { 1563 | "@esbuild/aix-ppc64": "0.25.1", 1564 | "@esbuild/android-arm": "0.25.1", 1565 | "@esbuild/android-arm64": "0.25.1", 1566 | "@esbuild/android-x64": "0.25.1", 1567 | "@esbuild/darwin-arm64": "0.25.1", 1568 | "@esbuild/darwin-x64": "0.25.1", 1569 | "@esbuild/freebsd-arm64": "0.25.1", 1570 | "@esbuild/freebsd-x64": "0.25.1", 1571 | "@esbuild/linux-arm": "0.25.1", 1572 | "@esbuild/linux-arm64": "0.25.1", 1573 | "@esbuild/linux-ia32": "0.25.1", 1574 | "@esbuild/linux-loong64": "0.25.1", 1575 | "@esbuild/linux-mips64el": "0.25.1", 1576 | "@esbuild/linux-ppc64": "0.25.1", 1577 | "@esbuild/linux-riscv64": "0.25.1", 1578 | "@esbuild/linux-s390x": "0.25.1", 1579 | "@esbuild/linux-x64": "0.25.1", 1580 | "@esbuild/netbsd-arm64": "0.25.1", 1581 | "@esbuild/netbsd-x64": "0.25.1", 1582 | "@esbuild/openbsd-arm64": "0.25.1", 1583 | "@esbuild/openbsd-x64": "0.25.1", 1584 | "@esbuild/sunos-x64": "0.25.1", 1585 | "@esbuild/win32-arm64": "0.25.1", 1586 | "@esbuild/win32-ia32": "0.25.1", 1587 | "@esbuild/win32-x64": "0.25.1" 1588 | } 1589 | }, 1590 | "node_modules/estree-walker": { 1591 | "version": "3.0.3", 1592 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1593 | "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1594 | "dev": true, 1595 | "dependencies": { 1596 | "@types/estree": "^1.0.0" 1597 | } 1598 | }, 1599 | "node_modules/expect-type": { 1600 | "version": "1.2.1", 1601 | "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", 1602 | "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", 1603 | "dev": true, 1604 | "engines": { 1605 | "node": ">=12.0.0" 1606 | } 1607 | }, 1608 | "node_modules/fdir": { 1609 | "version": "6.4.4", 1610 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", 1611 | "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", 1612 | "dev": true, 1613 | "peerDependencies": { 1614 | "picomatch": "^3 || ^4" 1615 | }, 1616 | "peerDependenciesMeta": { 1617 | "picomatch": { 1618 | "optional": true 1619 | } 1620 | } 1621 | }, 1622 | "node_modules/foreground-child": { 1623 | "version": "3.1.1", 1624 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 1625 | "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 1626 | "dev": true, 1627 | "dependencies": { 1628 | "cross-spawn": "^7.0.0", 1629 | "signal-exit": "^4.0.1" 1630 | }, 1631 | "engines": { 1632 | "node": ">=14" 1633 | }, 1634 | "funding": { 1635 | "url": "https://github.com/sponsors/isaacs" 1636 | } 1637 | }, 1638 | "node_modules/foreground-child/node_modules/signal-exit": { 1639 | "version": "4.1.0", 1640 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 1641 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 1642 | "dev": true, 1643 | "engines": { 1644 | "node": ">=14" 1645 | }, 1646 | "funding": { 1647 | "url": "https://github.com/sponsors/isaacs" 1648 | } 1649 | }, 1650 | "node_modules/fsevents": { 1651 | "version": "2.3.3", 1652 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1653 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1654 | "dev": true, 1655 | "hasInstallScript": true, 1656 | "optional": true, 1657 | "os": [ 1658 | "darwin" 1659 | ], 1660 | "engines": { 1661 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1662 | } 1663 | }, 1664 | "node_modules/glob": { 1665 | "version": "10.3.12", 1666 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", 1667 | "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", 1668 | "dev": true, 1669 | "dependencies": { 1670 | "foreground-child": "^3.1.0", 1671 | "jackspeak": "^2.3.6", 1672 | "minimatch": "^9.0.1", 1673 | "minipass": "^7.0.4", 1674 | "path-scurry": "^1.10.2" 1675 | }, 1676 | "bin": { 1677 | "glob": "dist/esm/bin.mjs" 1678 | }, 1679 | "engines": { 1680 | "node": ">=16 || 14 >=14.17" 1681 | }, 1682 | "funding": { 1683 | "url": "https://github.com/sponsors/isaacs" 1684 | } 1685 | }, 1686 | "node_modules/is-fullwidth-code-point": { 1687 | "version": "3.0.0", 1688 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1689 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1690 | "dev": true, 1691 | "engines": { 1692 | "node": ">=8" 1693 | } 1694 | }, 1695 | "node_modules/isexe": { 1696 | "version": "2.0.0", 1697 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1698 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1699 | "dev": true 1700 | }, 1701 | "node_modules/jackspeak": { 1702 | "version": "2.3.6", 1703 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", 1704 | "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", 1705 | "dev": true, 1706 | "dependencies": { 1707 | "@isaacs/cliui": "^8.0.2" 1708 | }, 1709 | "engines": { 1710 | "node": ">=14" 1711 | }, 1712 | "funding": { 1713 | "url": "https://github.com/sponsors/isaacs" 1714 | }, 1715 | "optionalDependencies": { 1716 | "@pkgjs/parseargs": "^0.11.0" 1717 | } 1718 | }, 1719 | "node_modules/joycon": { 1720 | "version": "3.1.1", 1721 | "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", 1722 | "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", 1723 | "dev": true, 1724 | "engines": { 1725 | "node": ">=10" 1726 | } 1727 | }, 1728 | "node_modules/lilconfig": { 1729 | "version": "3.1.3", 1730 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", 1731 | "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", 1732 | "dev": true, 1733 | "license": "MIT", 1734 | "engines": { 1735 | "node": ">=14" 1736 | }, 1737 | "funding": { 1738 | "url": "https://github.com/sponsors/antonk52" 1739 | } 1740 | }, 1741 | "node_modules/lines-and-columns": { 1742 | "version": "1.2.4", 1743 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 1744 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", 1745 | "dev": true 1746 | }, 1747 | "node_modules/load-tsconfig": { 1748 | "version": "0.2.5", 1749 | "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", 1750 | "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", 1751 | "dev": true, 1752 | "license": "MIT", 1753 | "engines": { 1754 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1755 | } 1756 | }, 1757 | "node_modules/lodash.sortby": { 1758 | "version": "4.7.0", 1759 | "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", 1760 | "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", 1761 | "dev": true 1762 | }, 1763 | "node_modules/loupe": { 1764 | "version": "3.1.3", 1765 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", 1766 | "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", 1767 | "dev": true 1768 | }, 1769 | "node_modules/lru-cache": { 1770 | "version": "10.2.0", 1771 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", 1772 | "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", 1773 | "dev": true, 1774 | "engines": { 1775 | "node": "14 || >=16.14" 1776 | } 1777 | }, 1778 | "node_modules/magic-string": { 1779 | "version": "0.30.17", 1780 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1781 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1782 | "dev": true, 1783 | "dependencies": { 1784 | "@jridgewell/sourcemap-codec": "^1.5.0" 1785 | } 1786 | }, 1787 | "node_modules/minimatch": { 1788 | "version": "9.0.4", 1789 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", 1790 | "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", 1791 | "dev": true, 1792 | "dependencies": { 1793 | "brace-expansion": "^2.0.1" 1794 | }, 1795 | "engines": { 1796 | "node": ">=16 || 14 >=14.17" 1797 | }, 1798 | "funding": { 1799 | "url": "https://github.com/sponsors/isaacs" 1800 | } 1801 | }, 1802 | "node_modules/minipass": { 1803 | "version": "7.0.4", 1804 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", 1805 | "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", 1806 | "dev": true, 1807 | "engines": { 1808 | "node": ">=16 || 14 >=14.17" 1809 | } 1810 | }, 1811 | "node_modules/ms": { 1812 | "version": "2.1.3", 1813 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1814 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1815 | "dev": true, 1816 | "license": "MIT" 1817 | }, 1818 | "node_modules/mz": { 1819 | "version": "2.7.0", 1820 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", 1821 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", 1822 | "dev": true, 1823 | "dependencies": { 1824 | "any-promise": "^1.0.0", 1825 | "object-assign": "^4.0.1", 1826 | "thenify-all": "^1.0.0" 1827 | } 1828 | }, 1829 | "node_modules/nanoid": { 1830 | "version": "3.3.11", 1831 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1832 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1833 | "dev": true, 1834 | "funding": [ 1835 | { 1836 | "type": "github", 1837 | "url": "https://github.com/sponsors/ai" 1838 | } 1839 | ], 1840 | "bin": { 1841 | "nanoid": "bin/nanoid.cjs" 1842 | }, 1843 | "engines": { 1844 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1845 | } 1846 | }, 1847 | "node_modules/object-assign": { 1848 | "version": "4.1.1", 1849 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1850 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1851 | "dev": true, 1852 | "engines": { 1853 | "node": ">=0.10.0" 1854 | } 1855 | }, 1856 | "node_modules/once": { 1857 | "version": "1.4.0", 1858 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1859 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1860 | "dependencies": { 1861 | "wrappy": "1" 1862 | } 1863 | }, 1864 | "node_modules/packageurl-js": { 1865 | "version": "1.2.1", 1866 | "resolved": "https://registry.npmjs.org/packageurl-js/-/packageurl-js-1.2.1.tgz", 1867 | "integrity": "sha512-cZ6/MzuXaoFd16/k0WnwtI298UCaDHe/XlSh85SeOKbGZ1hq0xvNbx3ILyCMyk7uFQxl6scF3Aucj6/EO9NwcA==" 1868 | }, 1869 | "node_modules/path-key": { 1870 | "version": "3.1.1", 1871 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1872 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1873 | "dev": true, 1874 | "engines": { 1875 | "node": ">=8" 1876 | } 1877 | }, 1878 | "node_modules/path-scurry": { 1879 | "version": "1.10.2", 1880 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", 1881 | "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", 1882 | "dev": true, 1883 | "dependencies": { 1884 | "lru-cache": "^10.2.0", 1885 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 1886 | }, 1887 | "engines": { 1888 | "node": ">=16 || 14 >=14.17" 1889 | }, 1890 | "funding": { 1891 | "url": "https://github.com/sponsors/isaacs" 1892 | } 1893 | }, 1894 | "node_modules/pathe": { 1895 | "version": "2.0.3", 1896 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1897 | "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1898 | "dev": true 1899 | }, 1900 | "node_modules/pathval": { 1901 | "version": "2.0.0", 1902 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", 1903 | "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", 1904 | "dev": true, 1905 | "engines": { 1906 | "node": ">= 14.16" 1907 | } 1908 | }, 1909 | "node_modules/picocolors": { 1910 | "version": "1.1.1", 1911 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1912 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1913 | "dev": true, 1914 | "license": "ISC" 1915 | }, 1916 | "node_modules/picomatch": { 1917 | "version": "4.0.2", 1918 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", 1919 | "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", 1920 | "dev": true, 1921 | "engines": { 1922 | "node": ">=12" 1923 | }, 1924 | "funding": { 1925 | "url": "https://github.com/sponsors/jonschlinkert" 1926 | } 1927 | }, 1928 | "node_modules/pirates": { 1929 | "version": "4.0.6", 1930 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", 1931 | "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", 1932 | "dev": true, 1933 | "engines": { 1934 | "node": ">= 6" 1935 | } 1936 | }, 1937 | "node_modules/postcss": { 1938 | "version": "8.5.3", 1939 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", 1940 | "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 1941 | "dev": true, 1942 | "funding": [ 1943 | { 1944 | "type": "opencollective", 1945 | "url": "https://opencollective.com/postcss/" 1946 | }, 1947 | { 1948 | "type": "tidelift", 1949 | "url": "https://tidelift.com/funding/github/npm/postcss" 1950 | }, 1951 | { 1952 | "type": "github", 1953 | "url": "https://github.com/sponsors/ai" 1954 | } 1955 | ], 1956 | "dependencies": { 1957 | "nanoid": "^3.3.8", 1958 | "picocolors": "^1.1.1", 1959 | "source-map-js": "^1.2.1" 1960 | }, 1961 | "engines": { 1962 | "node": "^10 || ^12 || >=14" 1963 | } 1964 | }, 1965 | "node_modules/postcss-load-config": { 1966 | "version": "6.0.1", 1967 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", 1968 | "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", 1969 | "dev": true, 1970 | "funding": [ 1971 | { 1972 | "type": "opencollective", 1973 | "url": "https://opencollective.com/postcss/" 1974 | }, 1975 | { 1976 | "type": "github", 1977 | "url": "https://github.com/sponsors/ai" 1978 | } 1979 | ], 1980 | "license": "MIT", 1981 | "dependencies": { 1982 | "lilconfig": "^3.1.1" 1983 | }, 1984 | "engines": { 1985 | "node": ">= 18" 1986 | }, 1987 | "peerDependencies": { 1988 | "jiti": ">=1.21.0", 1989 | "postcss": ">=8.0.9", 1990 | "tsx": "^4.8.1", 1991 | "yaml": "^2.4.2" 1992 | }, 1993 | "peerDependenciesMeta": { 1994 | "jiti": { 1995 | "optional": true 1996 | }, 1997 | "postcss": { 1998 | "optional": true 1999 | }, 2000 | "tsx": { 2001 | "optional": true 2002 | }, 2003 | "yaml": { 2004 | "optional": true 2005 | } 2006 | } 2007 | }, 2008 | "node_modules/punycode": { 2009 | "version": "2.3.1", 2010 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 2011 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 2012 | "dev": true, 2013 | "engines": { 2014 | "node": ">=6" 2015 | } 2016 | }, 2017 | "node_modules/readdirp": { 2018 | "version": "4.1.2", 2019 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", 2020 | "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", 2021 | "dev": true, 2022 | "license": "MIT", 2023 | "engines": { 2024 | "node": ">= 14.18.0" 2025 | }, 2026 | "funding": { 2027 | "type": "individual", 2028 | "url": "https://paulmillr.com/funding/" 2029 | } 2030 | }, 2031 | "node_modules/resolve-from": { 2032 | "version": "5.0.0", 2033 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 2034 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 2035 | "dev": true, 2036 | "engines": { 2037 | "node": ">=8" 2038 | } 2039 | }, 2040 | "node_modules/rollup": { 2041 | "version": "4.34.9", 2042 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz", 2043 | "integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==", 2044 | "dev": true, 2045 | "license": "MIT", 2046 | "dependencies": { 2047 | "@types/estree": "1.0.6" 2048 | }, 2049 | "bin": { 2050 | "rollup": "dist/bin/rollup" 2051 | }, 2052 | "engines": { 2053 | "node": ">=18.0.0", 2054 | "npm": ">=8.0.0" 2055 | }, 2056 | "optionalDependencies": { 2057 | "@rollup/rollup-android-arm-eabi": "4.34.9", 2058 | "@rollup/rollup-android-arm64": "4.34.9", 2059 | "@rollup/rollup-darwin-arm64": "4.34.9", 2060 | "@rollup/rollup-darwin-x64": "4.34.9", 2061 | "@rollup/rollup-freebsd-arm64": "4.34.9", 2062 | "@rollup/rollup-freebsd-x64": "4.34.9", 2063 | "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", 2064 | "@rollup/rollup-linux-arm-musleabihf": "4.34.9", 2065 | "@rollup/rollup-linux-arm64-gnu": "4.34.9", 2066 | "@rollup/rollup-linux-arm64-musl": "4.34.9", 2067 | "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", 2068 | "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", 2069 | "@rollup/rollup-linux-riscv64-gnu": "4.34.9", 2070 | "@rollup/rollup-linux-s390x-gnu": "4.34.9", 2071 | "@rollup/rollup-linux-x64-gnu": "4.34.9", 2072 | "@rollup/rollup-linux-x64-musl": "4.34.9", 2073 | "@rollup/rollup-win32-arm64-msvc": "4.34.9", 2074 | "@rollup/rollup-win32-ia32-msvc": "4.34.9", 2075 | "@rollup/rollup-win32-x64-msvc": "4.34.9", 2076 | "fsevents": "~2.3.2" 2077 | } 2078 | }, 2079 | "node_modules/shebang-command": { 2080 | "version": "2.0.0", 2081 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2082 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2083 | "dev": true, 2084 | "dependencies": { 2085 | "shebang-regex": "^3.0.0" 2086 | }, 2087 | "engines": { 2088 | "node": ">=8" 2089 | } 2090 | }, 2091 | "node_modules/shebang-regex": { 2092 | "version": "3.0.0", 2093 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2094 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2095 | "dev": true, 2096 | "engines": { 2097 | "node": ">=8" 2098 | } 2099 | }, 2100 | "node_modules/siginfo": { 2101 | "version": "2.0.0", 2102 | "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 2103 | "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 2104 | "dev": true, 2105 | "license": "ISC" 2106 | }, 2107 | "node_modules/source-map": { 2108 | "version": "0.8.0-beta.0", 2109 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", 2110 | "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", 2111 | "dev": true, 2112 | "dependencies": { 2113 | "whatwg-url": "^7.0.0" 2114 | }, 2115 | "engines": { 2116 | "node": ">= 8" 2117 | } 2118 | }, 2119 | "node_modules/source-map-js": { 2120 | "version": "1.2.1", 2121 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 2122 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 2123 | "dev": true, 2124 | "engines": { 2125 | "node": ">=0.10.0" 2126 | } 2127 | }, 2128 | "node_modules/stackback": { 2129 | "version": "0.0.2", 2130 | "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 2131 | "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 2132 | "dev": true, 2133 | "license": "MIT" 2134 | }, 2135 | "node_modules/std-env": { 2136 | "version": "3.9.0", 2137 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", 2138 | "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", 2139 | "dev": true 2140 | }, 2141 | "node_modules/string-width": { 2142 | "version": "5.1.2", 2143 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 2144 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 2145 | "dev": true, 2146 | "dependencies": { 2147 | "eastasianwidth": "^0.2.0", 2148 | "emoji-regex": "^9.2.2", 2149 | "strip-ansi": "^7.0.1" 2150 | }, 2151 | "engines": { 2152 | "node": ">=12" 2153 | }, 2154 | "funding": { 2155 | "url": "https://github.com/sponsors/sindresorhus" 2156 | } 2157 | }, 2158 | "node_modules/string-width-cjs": { 2159 | "name": "string-width", 2160 | "version": "4.2.3", 2161 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2162 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2163 | "dev": true, 2164 | "dependencies": { 2165 | "emoji-regex": "^8.0.0", 2166 | "is-fullwidth-code-point": "^3.0.0", 2167 | "strip-ansi": "^6.0.1" 2168 | }, 2169 | "engines": { 2170 | "node": ">=8" 2171 | } 2172 | }, 2173 | "node_modules/string-width-cjs/node_modules/ansi-regex": { 2174 | "version": "5.0.1", 2175 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2176 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2177 | "dev": true, 2178 | "engines": { 2179 | "node": ">=8" 2180 | } 2181 | }, 2182 | "node_modules/string-width-cjs/node_modules/emoji-regex": { 2183 | "version": "8.0.0", 2184 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2185 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2186 | "dev": true 2187 | }, 2188 | "node_modules/string-width-cjs/node_modules/strip-ansi": { 2189 | "version": "6.0.1", 2190 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2191 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2192 | "dev": true, 2193 | "dependencies": { 2194 | "ansi-regex": "^5.0.1" 2195 | }, 2196 | "engines": { 2197 | "node": ">=8" 2198 | } 2199 | }, 2200 | "node_modules/strip-ansi": { 2201 | "version": "7.1.0", 2202 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 2203 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 2204 | "dev": true, 2205 | "dependencies": { 2206 | "ansi-regex": "^6.0.1" 2207 | }, 2208 | "engines": { 2209 | "node": ">=12" 2210 | }, 2211 | "funding": { 2212 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2213 | } 2214 | }, 2215 | "node_modules/strip-ansi-cjs": { 2216 | "name": "strip-ansi", 2217 | "version": "6.0.1", 2218 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2219 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2220 | "dev": true, 2221 | "dependencies": { 2222 | "ansi-regex": "^5.0.1" 2223 | }, 2224 | "engines": { 2225 | "node": ">=8" 2226 | } 2227 | }, 2228 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 2229 | "version": "5.0.1", 2230 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2231 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2232 | "dev": true, 2233 | "engines": { 2234 | "node": ">=8" 2235 | } 2236 | }, 2237 | "node_modules/sucrase": { 2238 | "version": "3.35.0", 2239 | "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", 2240 | "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", 2241 | "dev": true, 2242 | "dependencies": { 2243 | "@jridgewell/gen-mapping": "^0.3.2", 2244 | "commander": "^4.0.0", 2245 | "glob": "^10.3.10", 2246 | "lines-and-columns": "^1.1.6", 2247 | "mz": "^2.7.0", 2248 | "pirates": "^4.0.1", 2249 | "ts-interface-checker": "^0.1.9" 2250 | }, 2251 | "bin": { 2252 | "sucrase": "bin/sucrase", 2253 | "sucrase-node": "bin/sucrase-node" 2254 | }, 2255 | "engines": { 2256 | "node": ">=16 || 14 >=14.17" 2257 | } 2258 | }, 2259 | "node_modules/thenify": { 2260 | "version": "3.3.1", 2261 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", 2262 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", 2263 | "dev": true, 2264 | "dependencies": { 2265 | "any-promise": "^1.0.0" 2266 | } 2267 | }, 2268 | "node_modules/thenify-all": { 2269 | "version": "1.6.0", 2270 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 2271 | "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", 2272 | "dev": true, 2273 | "dependencies": { 2274 | "thenify": ">= 3.1.0 < 4" 2275 | }, 2276 | "engines": { 2277 | "node": ">=0.8" 2278 | } 2279 | }, 2280 | "node_modules/tinybench": { 2281 | "version": "2.9.0", 2282 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 2283 | "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 2284 | "dev": true, 2285 | "license": "MIT" 2286 | }, 2287 | "node_modules/tinyexec": { 2288 | "version": "0.3.2", 2289 | "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 2290 | "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 2291 | "dev": true, 2292 | "license": "MIT" 2293 | }, 2294 | "node_modules/tinyglobby": { 2295 | "version": "0.2.13", 2296 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", 2297 | "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", 2298 | "dev": true, 2299 | "dependencies": { 2300 | "fdir": "^6.4.4", 2301 | "picomatch": "^4.0.2" 2302 | }, 2303 | "engines": { 2304 | "node": ">=12.0.0" 2305 | }, 2306 | "funding": { 2307 | "url": "https://github.com/sponsors/SuperchupuDev" 2308 | } 2309 | }, 2310 | "node_modules/tinyrainbow": { 2311 | "version": "2.0.0", 2312 | "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 2313 | "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 2314 | "dev": true, 2315 | "engines": { 2316 | "node": ">=14.0.0" 2317 | } 2318 | }, 2319 | "node_modules/tinyspy": { 2320 | "version": "3.0.2", 2321 | "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 2322 | "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 2323 | "dev": true, 2324 | "engines": { 2325 | "node": ">=14.0.0" 2326 | } 2327 | }, 2328 | "node_modules/tr46": { 2329 | "version": "1.0.1", 2330 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", 2331 | "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", 2332 | "dev": true, 2333 | "dependencies": { 2334 | "punycode": "^2.1.0" 2335 | } 2336 | }, 2337 | "node_modules/tree-kill": { 2338 | "version": "1.2.2", 2339 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", 2340 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", 2341 | "dev": true, 2342 | "bin": { 2343 | "tree-kill": "cli.js" 2344 | } 2345 | }, 2346 | "node_modules/ts-interface-checker": { 2347 | "version": "0.1.13", 2348 | "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", 2349 | "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", 2350 | "dev": true 2351 | }, 2352 | "node_modules/tsup": { 2353 | "version": "8.4.0", 2354 | "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.4.0.tgz", 2355 | "integrity": "sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==", 2356 | "dev": true, 2357 | "license": "MIT", 2358 | "dependencies": { 2359 | "bundle-require": "^5.1.0", 2360 | "cac": "^6.7.14", 2361 | "chokidar": "^4.0.3", 2362 | "consola": "^3.4.0", 2363 | "debug": "^4.4.0", 2364 | "esbuild": "^0.25.0", 2365 | "joycon": "^3.1.1", 2366 | "picocolors": "^1.1.1", 2367 | "postcss-load-config": "^6.0.1", 2368 | "resolve-from": "^5.0.0", 2369 | "rollup": "^4.34.8", 2370 | "source-map": "0.8.0-beta.0", 2371 | "sucrase": "^3.35.0", 2372 | "tinyexec": "^0.3.2", 2373 | "tinyglobby": "^0.2.11", 2374 | "tree-kill": "^1.2.2" 2375 | }, 2376 | "bin": { 2377 | "tsup": "dist/cli-default.js", 2378 | "tsup-node": "dist/cli-node.js" 2379 | }, 2380 | "engines": { 2381 | "node": ">=18" 2382 | }, 2383 | "peerDependencies": { 2384 | "@microsoft/api-extractor": "^7.36.0", 2385 | "@swc/core": "^1", 2386 | "postcss": "^8.4.12", 2387 | "typescript": ">=4.5.0" 2388 | }, 2389 | "peerDependenciesMeta": { 2390 | "@microsoft/api-extractor": { 2391 | "optional": true 2392 | }, 2393 | "@swc/core": { 2394 | "optional": true 2395 | }, 2396 | "postcss": { 2397 | "optional": true 2398 | }, 2399 | "typescript": { 2400 | "optional": true 2401 | } 2402 | } 2403 | }, 2404 | "node_modules/tunnel": { 2405 | "version": "0.0.6", 2406 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 2407 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 2408 | "engines": { 2409 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 2410 | } 2411 | }, 2412 | "node_modules/typescript": { 2413 | "version": "5.4.5", 2414 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", 2415 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", 2416 | "dev": true, 2417 | "bin": { 2418 | "tsc": "bin/tsc", 2419 | "tsserver": "bin/tsserver" 2420 | }, 2421 | "engines": { 2422 | "node": ">=14.17" 2423 | } 2424 | }, 2425 | "node_modules/undici": { 2426 | "version": "5.28.5", 2427 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", 2428 | "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", 2429 | "license": "MIT", 2430 | "dependencies": { 2431 | "@fastify/busboy": "^2.0.0" 2432 | }, 2433 | "engines": { 2434 | "node": ">=14.0" 2435 | } 2436 | }, 2437 | "node_modules/undici-types": { 2438 | "version": "5.26.5", 2439 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 2440 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 2441 | "dev": true 2442 | }, 2443 | "node_modules/universal-user-agent": { 2444 | "version": "6.0.1", 2445 | "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", 2446 | "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" 2447 | }, 2448 | "node_modules/uuid": { 2449 | "version": "8.3.2", 2450 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 2451 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 2452 | "bin": { 2453 | "uuid": "dist/bin/uuid" 2454 | } 2455 | }, 2456 | "node_modules/vite": { 2457 | "version": "6.3.2", 2458 | "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.2.tgz", 2459 | "integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==", 2460 | "dev": true, 2461 | "dependencies": { 2462 | "esbuild": "^0.25.0", 2463 | "fdir": "^6.4.3", 2464 | "picomatch": "^4.0.2", 2465 | "postcss": "^8.5.3", 2466 | "rollup": "^4.34.9", 2467 | "tinyglobby": "^0.2.12" 2468 | }, 2469 | "bin": { 2470 | "vite": "bin/vite.js" 2471 | }, 2472 | "engines": { 2473 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2474 | }, 2475 | "funding": { 2476 | "url": "https://github.com/vitejs/vite?sponsor=1" 2477 | }, 2478 | "optionalDependencies": { 2479 | "fsevents": "~2.3.3" 2480 | }, 2481 | "peerDependencies": { 2482 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2483 | "jiti": ">=1.21.0", 2484 | "less": "*", 2485 | "lightningcss": "^1.21.0", 2486 | "sass": "*", 2487 | "sass-embedded": "*", 2488 | "stylus": "*", 2489 | "sugarss": "*", 2490 | "terser": "^5.16.0", 2491 | "tsx": "^4.8.1", 2492 | "yaml": "^2.4.2" 2493 | }, 2494 | "peerDependenciesMeta": { 2495 | "@types/node": { 2496 | "optional": true 2497 | }, 2498 | "jiti": { 2499 | "optional": true 2500 | }, 2501 | "less": { 2502 | "optional": true 2503 | }, 2504 | "lightningcss": { 2505 | "optional": true 2506 | }, 2507 | "sass": { 2508 | "optional": true 2509 | }, 2510 | "sass-embedded": { 2511 | "optional": true 2512 | }, 2513 | "stylus": { 2514 | "optional": true 2515 | }, 2516 | "sugarss": { 2517 | "optional": true 2518 | }, 2519 | "terser": { 2520 | "optional": true 2521 | }, 2522 | "tsx": { 2523 | "optional": true 2524 | }, 2525 | "yaml": { 2526 | "optional": true 2527 | } 2528 | } 2529 | }, 2530 | "node_modules/vite-node": { 2531 | "version": "3.1.2", 2532 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", 2533 | "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", 2534 | "dev": true, 2535 | "dependencies": { 2536 | "cac": "^6.7.14", 2537 | "debug": "^4.4.0", 2538 | "es-module-lexer": "^1.6.0", 2539 | "pathe": "^2.0.3", 2540 | "vite": "^5.0.0 || ^6.0.0" 2541 | }, 2542 | "bin": { 2543 | "vite-node": "vite-node.mjs" 2544 | }, 2545 | "engines": { 2546 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2547 | }, 2548 | "funding": { 2549 | "url": "https://opencollective.com/vitest" 2550 | } 2551 | }, 2552 | "node_modules/vitest": { 2553 | "version": "3.1.2", 2554 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", 2555 | "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", 2556 | "dev": true, 2557 | "dependencies": { 2558 | "@vitest/expect": "3.1.2", 2559 | "@vitest/mocker": "3.1.2", 2560 | "@vitest/pretty-format": "^3.1.2", 2561 | "@vitest/runner": "3.1.2", 2562 | "@vitest/snapshot": "3.1.2", 2563 | "@vitest/spy": "3.1.2", 2564 | "@vitest/utils": "3.1.2", 2565 | "chai": "^5.2.0", 2566 | "debug": "^4.4.0", 2567 | "expect-type": "^1.2.1", 2568 | "magic-string": "^0.30.17", 2569 | "pathe": "^2.0.3", 2570 | "std-env": "^3.9.0", 2571 | "tinybench": "^2.9.0", 2572 | "tinyexec": "^0.3.2", 2573 | "tinyglobby": "^0.2.13", 2574 | "tinypool": "^1.0.2", 2575 | "tinyrainbow": "^2.0.0", 2576 | "vite": "^5.0.0 || ^6.0.0", 2577 | "vite-node": "3.1.2", 2578 | "why-is-node-running": "^2.3.0" 2579 | }, 2580 | "bin": { 2581 | "vitest": "vitest.mjs" 2582 | }, 2583 | "engines": { 2584 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2585 | }, 2586 | "funding": { 2587 | "url": "https://opencollective.com/vitest" 2588 | }, 2589 | "peerDependencies": { 2590 | "@edge-runtime/vm": "*", 2591 | "@types/debug": "^4.1.12", 2592 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2593 | "@vitest/browser": "3.1.2", 2594 | "@vitest/ui": "3.1.2", 2595 | "happy-dom": "*", 2596 | "jsdom": "*" 2597 | }, 2598 | "peerDependenciesMeta": { 2599 | "@edge-runtime/vm": { 2600 | "optional": true 2601 | }, 2602 | "@types/debug": { 2603 | "optional": true 2604 | }, 2605 | "@types/node": { 2606 | "optional": true 2607 | }, 2608 | "@vitest/browser": { 2609 | "optional": true 2610 | }, 2611 | "@vitest/ui": { 2612 | "optional": true 2613 | }, 2614 | "happy-dom": { 2615 | "optional": true 2616 | }, 2617 | "jsdom": { 2618 | "optional": true 2619 | } 2620 | } 2621 | }, 2622 | "node_modules/vitest/node_modules/tinypool": { 2623 | "version": "1.0.2", 2624 | "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", 2625 | "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", 2626 | "dev": true, 2627 | "license": "MIT", 2628 | "engines": { 2629 | "node": "^18.0.0 || >=20.0.0" 2630 | } 2631 | }, 2632 | "node_modules/webidl-conversions": { 2633 | "version": "4.0.2", 2634 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", 2635 | "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", 2636 | "dev": true 2637 | }, 2638 | "node_modules/whatwg-url": { 2639 | "version": "7.1.0", 2640 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", 2641 | "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", 2642 | "dev": true, 2643 | "dependencies": { 2644 | "lodash.sortby": "^4.7.0", 2645 | "tr46": "^1.0.1", 2646 | "webidl-conversions": "^4.0.2" 2647 | } 2648 | }, 2649 | "node_modules/which": { 2650 | "version": "2.0.2", 2651 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2652 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2653 | "dev": true, 2654 | "dependencies": { 2655 | "isexe": "^2.0.0" 2656 | }, 2657 | "bin": { 2658 | "node-which": "bin/node-which" 2659 | }, 2660 | "engines": { 2661 | "node": ">= 8" 2662 | } 2663 | }, 2664 | "node_modules/why-is-node-running": { 2665 | "version": "2.3.0", 2666 | "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2667 | "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2668 | "dev": true, 2669 | "license": "MIT", 2670 | "dependencies": { 2671 | "siginfo": "^2.0.0", 2672 | "stackback": "0.0.2" 2673 | }, 2674 | "bin": { 2675 | "why-is-node-running": "cli.js" 2676 | }, 2677 | "engines": { 2678 | "node": ">=8" 2679 | } 2680 | }, 2681 | "node_modules/wrap-ansi": { 2682 | "version": "8.1.0", 2683 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 2684 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 2685 | "dev": true, 2686 | "dependencies": { 2687 | "ansi-styles": "^6.1.0", 2688 | "string-width": "^5.0.1", 2689 | "strip-ansi": "^7.0.1" 2690 | }, 2691 | "engines": { 2692 | "node": ">=12" 2693 | }, 2694 | "funding": { 2695 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2696 | } 2697 | }, 2698 | "node_modules/wrap-ansi-cjs": { 2699 | "name": "wrap-ansi", 2700 | "version": "7.0.0", 2701 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2702 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2703 | "dev": true, 2704 | "dependencies": { 2705 | "ansi-styles": "^4.0.0", 2706 | "string-width": "^4.1.0", 2707 | "strip-ansi": "^6.0.0" 2708 | }, 2709 | "engines": { 2710 | "node": ">=10" 2711 | }, 2712 | "funding": { 2713 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2714 | } 2715 | }, 2716 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 2717 | "version": "5.0.1", 2718 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2719 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2720 | "dev": true, 2721 | "engines": { 2722 | "node": ">=8" 2723 | } 2724 | }, 2725 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 2726 | "version": "4.3.0", 2727 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2728 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2729 | "dev": true, 2730 | "dependencies": { 2731 | "color-convert": "^2.0.1" 2732 | }, 2733 | "engines": { 2734 | "node": ">=8" 2735 | }, 2736 | "funding": { 2737 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2738 | } 2739 | }, 2740 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 2741 | "version": "8.0.0", 2742 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2743 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2744 | "dev": true 2745 | }, 2746 | "node_modules/wrap-ansi-cjs/node_modules/string-width": { 2747 | "version": "4.2.3", 2748 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2749 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2750 | "dev": true, 2751 | "dependencies": { 2752 | "emoji-regex": "^8.0.0", 2753 | "is-fullwidth-code-point": "^3.0.0", 2754 | "strip-ansi": "^6.0.1" 2755 | }, 2756 | "engines": { 2757 | "node": ">=8" 2758 | } 2759 | }, 2760 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 2761 | "version": "6.0.1", 2762 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2763 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2764 | "dev": true, 2765 | "dependencies": { 2766 | "ansi-regex": "^5.0.1" 2767 | }, 2768 | "engines": { 2769 | "node": ">=8" 2770 | } 2771 | }, 2772 | "node_modules/wrap-ansi/node_modules/ansi-styles": { 2773 | "version": "6.2.1", 2774 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 2775 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 2776 | "dev": true, 2777 | "engines": { 2778 | "node": ">=12" 2779 | }, 2780 | "funding": { 2781 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2782 | } 2783 | }, 2784 | "node_modules/wrappy": { 2785 | "version": "1.0.2", 2786 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2787 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 2788 | } 2789 | } 2790 | } 2791 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@github/dependency-submission-toolkit", 3 | "version": "2.0.5", 4 | "description": "A TypeScript library for creating dependency snapshots.", 5 | "homepage": "https://github.com/github/dependency-submission-toolkit", 6 | "bugs": { 7 | "url": "https://github.com/github/dependency-submission-toolkit/issues" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/github/dependency-submission-toolkit.git" 12 | }, 13 | "license": "MIT", 14 | "type": "module", 15 | "exports": { 16 | ".": { 17 | "types": "./dist/index.d.cts", 18 | "require": "./dist/index.cjs", 19 | "import": "./dist/index.js" 20 | } 21 | }, 22 | "main": "./dist/index.cjs", 23 | "module": "./dist/index.js", 24 | "types": "./dist/index.d.ts", 25 | "files": ["dist"], 26 | "workspaces": ["example"], 27 | "scripts": { 28 | "all": "npm run type-check && npm run build && npm run ci && npm run test", 29 | "build": "tsup", 30 | "ci": "biome ci .", 31 | "format": "biome format --write .", 32 | "lint": "biome lint --apply .", 33 | "prepare": "npm run build", 34 | "test": "vitest run src", 35 | "test:watch": "vitest watch src", 36 | "type-check": "tsc" 37 | }, 38 | "dependencies": { 39 | "@actions/core": "^1.10.1", 40 | "@actions/github": "^6.0.0", 41 | "@octokit/request-error": "^6.1.1", 42 | "@octokit/webhooks-types": "^7.5.0", 43 | "packageurl-js": "^1.2.1" 44 | }, 45 | "devDependencies": { 46 | "@biomejs/biome": "^1.7.0", 47 | "@tsconfig/strictest": "^2.0.5", 48 | "@types/node": "^20.12.7", 49 | "tsup": "^8.4.0", 50 | "typescript": "^5.4.5", 51 | "vitest": "^3.0.8" 52 | }, 53 | "overrides": { 54 | "esbuild": ">=0.25.0", 55 | "@octokit/request-error@5.1.0": "5.1.1" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './manifest.js' 2 | export * from './package-cache.js' 3 | export * from './package.js' 4 | export * from './snapshot.js' 5 | -------------------------------------------------------------------------------- /src/manifest.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest' 2 | 3 | import { Manifest } from './manifest.js' 4 | import { PackageCache } from './package-cache.js' 5 | 6 | const cache = new PackageCache() 7 | cache 8 | .package('pkg:npm/%40github/dependency-submission-toolkit@0.1.2') 9 | .dependsOn(cache.package('pkg:npm/%40actions/core@1.6.0')) 10 | 11 | function roundTripJSON(obj: unknown): object { 12 | return JSON.parse(JSON.stringify(obj)) 13 | } 14 | 15 | describe('Manifest', () => { 16 | it('renders expected JSON', () => { 17 | const manifest = new Manifest('test', './some/test') 18 | manifest.addDirectDependency( 19 | cache.package('pkg:npm/%40github/dependency-submission-toolkit@0.1.2') 20 | ) 21 | manifest.addIndirectDependency( 22 | cache.package('pkg:npm/%40actions/core@1.6.0') 23 | ) 24 | expect(roundTripJSON(manifest)).toEqual({ 25 | file: { 26 | source_location: './some/test' 27 | }, 28 | name: 'test', 29 | resolved: { 30 | 'pkg:npm/%40actions/core@1.6.0': { 31 | dependencies: [], 32 | package_url: 'pkg:npm/%40actions/core@1.6.0', 33 | relationship: 'indirect' 34 | }, 35 | 'pkg:npm/%40github/dependency-submission-toolkit@0.1.2': { 36 | dependencies: ['pkg:npm/%40actions/core@1.6.0'], 37 | package_url: 'pkg:npm/%40github/dependency-submission-toolkit@0.1.2', 38 | relationship: 'direct' 39 | } 40 | } 41 | }) 42 | }) 43 | }) 44 | -------------------------------------------------------------------------------- /src/manifest.ts: -------------------------------------------------------------------------------- 1 | import type { Package } from './package.js' 2 | 3 | /** 4 | * FileInfo specifies where the manifest or build-target are specified in the repository. 5 | */ 6 | type FileInfo = { 7 | source_location?: string 8 | } 9 | 10 | /** 11 | * DependencyRelationship is a notation of whether a dependency is requested 12 | * directly by this manifest, or is a dependency of another dependency. 13 | */ 14 | export type DependencyRelationship = 'direct' | 'indirect' 15 | 16 | /** 17 | * DependencyScope is a notation of whether the dependency is required for the 18 | * primary build artifact (runtime), or is only used for development. Future 19 | * versions of this specification may allow for more granular scopes, like 20 | * `runtime:server`, `runtime:shipped`, `development:test`, 21 | * `development:benchmark`, and so on. 22 | */ 23 | export type DependencyScope = 'runtime' | 'development' 24 | 25 | /** 26 | * Dependency. 27 | */ 28 | class Dependency { 29 | /** 30 | * @type {Package} 31 | */ 32 | depPackage: Package 33 | /** 34 | * @type {DependencyRelationship} 35 | */ 36 | relationship?: DependencyRelationship 37 | /** 38 | * @type {DependencyScope} 39 | */ 40 | scope?: DependencyScope 41 | 42 | /** 43 | * constructor. 44 | * 45 | * @param {Package} depPackage 46 | * @param {DependencyRelationship} relationship 47 | * @param {DependencyScope} scope 48 | */ 49 | constructor( 50 | depPackage: Package, 51 | relationship?: DependencyRelationship, 52 | scope?: DependencyScope 53 | ) { 54 | this.depPackage = depPackage 55 | if (relationship !== undefined) { 56 | this.relationship = relationship 57 | } 58 | if (scope !== undefined) { 59 | this.scope = scope 60 | } 61 | } 62 | 63 | /** 64 | * toJSON is a custom JSON-serializer. It will be called when JSON.stringify() 65 | * is called with this class or any object containing this class. 66 | * 67 | * @returns {object} with keys package_url, relationship, scope, and 68 | * dependency, per the Snapshot format 69 | */ 70 | toJSON(): object { 71 | return { 72 | package_url: this.depPackage.packageURL.toString(), 73 | relationship: this.relationship, 74 | scope: this.scope, 75 | dependencies: this.depPackage.packageDependencyIDs 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * Manifest defines the dependencies and the relationships of those dependencies. 82 | */ 83 | export class Manifest { 84 | resolved: Record 85 | name: string 86 | file?: FileInfo 87 | 88 | constructor(name: string, filePath?: string) { 89 | this.resolved = {} 90 | this.name = name 91 | if (filePath) { 92 | this.file = { source_location: filePath } 93 | } 94 | } 95 | 96 | /** 97 | * addIndirectDependency adds a package as an indirect dependency to the 98 | * manifest. Direct dependencies take precedence over indirect dependencies 99 | * if a package is added as both. 100 | * 101 | * @param {Package} pkg 102 | * @param {DependencyScope} scope 103 | */ 104 | addDirectDependency(pkg: Package, scope?: DependencyScope) { 105 | // will overwrite any previous indirect assignments 106 | this.resolved[pkg.packageID()] = new Dependency(pkg, 'direct', scope) 107 | } 108 | 109 | /** 110 | * addIndirectDependency adds a package as an indirect dependency to the 111 | * manifest. NOTE: if a dependency has been previously added as a direct 112 | * dependency, no change will happen (direct dependencies take precedence). 113 | * 114 | * @param {Package} pkg 115 | * @param {DependencyScope} scope dependency scope of the package 116 | */ 117 | addIndirectDependency(pkg: Package, scope?: DependencyScope) { 118 | // nullish assignment to keep any previous assignments, including direct assignments 119 | this.resolved[pkg.packageID()] ??= new Dependency(pkg, 'indirect', scope) 120 | } 121 | 122 | hasDependency(pkg: Package): boolean { 123 | return this.lookupDependency(pkg) !== undefined 124 | } 125 | 126 | lookupDependency(pkg: Package): Dependency | undefined { 127 | return this.resolved[pkg.packageID()] 128 | } 129 | 130 | countDependencies(): number { 131 | return Object.keys(this.resolved).length 132 | } 133 | 134 | /** 135 | * filterDependencies. Given a predicate function (a function returning a 136 | * boolean for an input), return the packages that match the dependency 137 | * relationship. Used for getting filtered lists of direct/indirect packages, 138 | * runtime/development packages, etc. 139 | * 140 | * @param {Function} predicate 141 | * @returns {Array} 142 | */ 143 | filterDependencies(predicate: (dep: Dependency) => boolean): Array { 144 | return Object.values(this.resolved).reduce>((acc, dep) => { 145 | if (predicate(dep)) { 146 | acc.push(dep.depPackage) 147 | } 148 | return acc 149 | }, []) 150 | } 151 | 152 | /** 153 | * directDependencies returns list of packages that are specified as direct dependencies 154 | */ 155 | directDependencies(): Array { 156 | return this.filterDependencies((dep) => dep.relationship === 'direct') 157 | } 158 | 159 | /** 160 | * indirectDependencies returns list of packages that are specified as indirect dependencies 161 | */ 162 | indirectDependencies(): Array { 163 | return this.filterDependencies((dep) => dep.relationship === 'indirect') 164 | } 165 | } 166 | 167 | /** 168 | * The dependencies used in a code artifact or "build target" are more 169 | * accurately determined by the build process or commands used to generate the 170 | * build target, rather than static processing of package files. BuildTarget is 171 | * a specialized case of Manifest intended to assist in capturing this 172 | * association of build target and dependencies. 173 | * 174 | * @extends {Manifest} 175 | */ 176 | export class BuildTarget extends Manifest { 177 | /** 178 | * addBuildDependency will add a package as a direct runtime dependency and all of 179 | * the package's transitive dependencies as indirect dependencies 180 | * 181 | * @param {Package} pkg package used to build the build target 182 | */ 183 | addBuildDependency(pkg: Package) { 184 | this.addDirectDependency(pkg, 'runtime') 185 | for (const transDep of pkg.dependencies) { 186 | this.addIndirectDependency(transDep, 'runtime') 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/package-cache.test.ts: -------------------------------------------------------------------------------- 1 | import { PackageURL } from 'packageurl-js' 2 | import { describe, expect, it } from 'vitest' 3 | 4 | import { PackageCache } from './package-cache.js' 5 | import { Package } from './package.js' 6 | 7 | const purl = 'pkg:npm/%40github/dependency-submission-toolkit@0.1.2' 8 | 9 | describe('PackageCache', () => { 10 | describe('with no packages', () => { 11 | const cache = new PackageCache() 12 | it('adds and remove Package', () => { 13 | const dep = new Package(purl) 14 | cache.addPackage(dep) 15 | expect(cache.countPackages()).toBe(1) 16 | cache.removePackage(dep) 17 | expect(cache.countPackages()).toBe(0) 18 | }) 19 | it('constructs a package with .package using PackageURL', () => { 20 | const packageURL = new PackageURL( 21 | 'npm', 22 | 'github', 23 | 'dependency-submission-toolkit', 24 | '0.1.2', 25 | null, 26 | null 27 | ) 28 | const dep = cache.package(packageURL) 29 | expect(dep).toBeInstanceOf(Package) 30 | expect(cache.countPackages()).toBe(1) 31 | 32 | // purposely using reference equality with 'toBe' 33 | expect(cache.package(packageURL)).toBe(dep) 34 | }) 35 | it('constructs a package with .package using string', () => { 36 | const cache = new PackageCache() 37 | const dep = cache.package(purl) 38 | expect(dep).toBeInstanceOf(Package) 39 | expect(cache.countPackages()).toBe(1) 40 | 41 | // purposely using reference equality with 'toBe' 42 | expect(cache.package(purl)).toBe(dep) 43 | }) 44 | it('.packagesMatching returns packages that match matcher', () => { 45 | const cache = new PackageCache() 46 | cache.package( 47 | new PackageURL( 48 | 'npm', 49 | '@github', 50 | 'dependency-submission-toolkit', 51 | '0.1.2', 52 | null, 53 | null 54 | ) 55 | ) 56 | 57 | cache.package( 58 | new PackageURL( 59 | 'npm', 60 | '@github', 61 | 'dependency-submission-toolkit', 62 | '0.2.0', 63 | null, 64 | null 65 | ) 66 | ) 67 | 68 | expect(cache.packagesMatching({ namespace: '@github' })).toHaveLength(2) 69 | expect(cache.packagesMatching({ namespace: '@gubhib' })).toHaveLength(0) 70 | 71 | expect( 72 | cache.packagesMatching({ 73 | namespace: '@github', 74 | name: 'dependency-submission-toolkit' 75 | }) 76 | ).toHaveLength(2) 77 | 78 | expect( 79 | cache.packagesMatching({ 80 | namespace: '@github', 81 | name: 'dependency-submission-toolkit', 82 | version: '0.1.2' 83 | }) 84 | ).toHaveLength(1) 85 | }) 86 | }) 87 | }) 88 | -------------------------------------------------------------------------------- /src/package-cache.ts: -------------------------------------------------------------------------------- 1 | import { PackageURL } from 'packageurl-js' 2 | 3 | import { Package } from './package.js' 4 | 5 | /** 6 | * Use PackageCache to define packages and the relationships between packages. You may 7 | * think of PackageCache as the universe of possible packages to be used in Manifests 8 | * and BuildTargets. PackageCache is not serialized to the Dependency Submission API. 9 | */ 10 | export class PackageCache { 11 | private database: Record 12 | 13 | constructor() { 14 | this.database = {} 15 | } 16 | 17 | /** 18 | * 'cache.package()' will be the most commonly used method of PackageCache. 19 | * package(identifier) will create and add a new Package to the PackageCache if no 20 | * Packaging with a matching identifier exists in PackageCache, or return an existing 21 | * Package if a match is found. The mutation in this case is expected; do not 22 | * use package(identifier) to determine if a package is already added. 23 | * Instead, use hasPackage or lookupPackage. 24 | * 25 | * 26 | * @param {PackageURL | string} identifier PackageURL or string matching the Package URL format (https://github.com/package-url/purl-spec) 27 | * @returns {Package} 28 | */ 29 | package(identifier: PackageURL | string): Package { 30 | const existingDep = this.lookupPackage(identifier) 31 | if (existingDep) { 32 | return existingDep 33 | } 34 | 35 | const dep = new Package(identifier) 36 | this.addPackage(dep) 37 | return dep 38 | } 39 | 40 | /** 41 | * Provided a "matcher" object with any of the string fields 'namespace', 42 | * 'name', or 'version', returns all packages matching fields specified by 43 | * the matcher stored by the PackageCache 44 | * 45 | * @param {Object} matcher 46 | * @returns {boolean} 47 | */ 48 | packagesMatching(matcher: { 49 | namespace?: string 50 | name?: string 51 | version?: string 52 | }): Array { 53 | return Object.values(this.database).filter((pkg) => pkg.matching(matcher)) 54 | } 55 | 56 | /** 57 | * addPackage adds a package, even if it already exists in the cache. 58 | * 59 | * @param {Package} pkg 60 | */ 61 | addPackage(pkg: Package) { 62 | this.database[pkg.packageURL.toString()] = pkg 63 | } 64 | 65 | /** 66 | * removePackage a removes a package from the cache 67 | * 68 | * @param {Package} pkg 69 | */ 70 | removePackage(pkg: Package) { 71 | delete this.database[pkg.packageURL.toString()] 72 | } 73 | 74 | /** 75 | * lookupPackage looks up and returns a package with a matching identifier, 76 | * if one exists. 77 | * 78 | * @param {PackageURL | string} identifier 79 | * @returns {Package | undefined} 80 | */ 81 | lookupPackage(identifier: PackageURL | string): Package | undefined { 82 | if (typeof identifier === 'string') { 83 | const purl = PackageURL.fromString(identifier) 84 | return this.database[purl.toString()] 85 | } 86 | return this.database[identifier.toString()] 87 | } 88 | 89 | /** 90 | * hasPackage returns true if a package with a matching identifier exists. 91 | * 92 | * @param {PackageURL | string} identifier 93 | * @returns {boolean} 94 | */ 95 | hasPackage(identifier: PackageURL | string): boolean { 96 | return this.lookupPackage(identifier) !== undefined 97 | } 98 | 99 | /** 100 | * countPackages returns the total number of packages tracked in the cache 101 | * 102 | * @returns {number} 103 | */ 104 | countPackages(): number { 105 | return Object.values(this.database).length 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/package.test.ts: -------------------------------------------------------------------------------- 1 | import { PackageURL } from 'packageurl-js' 2 | import { describe, expect, it } from 'vitest' 3 | 4 | import { Package } from './package.js' 5 | 6 | describe('Package', () => { 7 | it('constructs a from Package URL-formatted string ', () => { 8 | const purl = 'pkg:npm/%40github/dependency-submission-toolkit@0.1.2' 9 | const pkg = new Package(purl) 10 | 11 | expect(pkg.namespace()).toBe('@github') 12 | expect(pkg.name()).toBe('dependency-submission-toolkit') 13 | expect(pkg.version()).toBe('0.1.2') 14 | }) 15 | it('constructs a package with from PackageURL object', () => { 16 | const pkg = new Package( 17 | new PackageURL( 18 | 'npm', 19 | '@github', 20 | 'dependency-submission-toolkit', 21 | '0.1.2', 22 | null, 23 | null 24 | ) 25 | ) 26 | 27 | expect(pkg.namespace()).toBe('@github') 28 | expect(pkg.name()).toBe('dependency-submission-toolkit') 29 | expect(pkg.version()).toBe('0.1.2') 30 | }) 31 | it('.matching will match a package with matching aspects', () => { 32 | const pkg = new Package( 33 | new PackageURL( 34 | 'npm', 35 | '@github', 36 | 'dependency-submission-toolkit', 37 | '0.1.2', 38 | null, 39 | null 40 | ) 41 | ) 42 | 43 | expect(pkg.matching({ namespace: '@github' })).toBeTruthy() 44 | expect(pkg.matching({ namespace: 'buhtig@' })).toBeFalsy() 45 | 46 | expect(pkg.matching({ name: 'dependency-submission-toolkit' })).toBeTruthy() 47 | expect(pkg.matching({ name: 'foo-bar-baz' })).toBeFalsy() 48 | 49 | expect(pkg.matching({ version: '0.1.2' })).toBeTruthy() 50 | expect(pkg.matching({ version: '0.1.2' })).toBeTruthy() 51 | 52 | expect( 53 | pkg.matching({ 54 | namespace: '@github', 55 | name: 'dependency-submission-toolkit', 56 | version: '0.1.2' 57 | }) 58 | ).toBeTruthy() 59 | expect( 60 | pkg.matching({ 61 | namespace: 'buhtig@', 62 | name: 'dependency-submission-toolkit', 63 | version: '0.1.2' 64 | }) 65 | ).toBeFalsy() 66 | expect( 67 | pkg.matching({ 68 | namespace: '@github', 69 | name: 'foo-bar-baz', 70 | version: '0.1.2' 71 | }) 72 | ).toBeFalsy() 73 | expect( 74 | pkg.matching({ 75 | namespace: '@github', 76 | name: 'dependency-submission-toolkit', 77 | version: '1.2.3' 78 | }) 79 | ).toBeFalsy() 80 | }) 81 | }) 82 | -------------------------------------------------------------------------------- /src/package.ts: -------------------------------------------------------------------------------- 1 | import { PackageURL } from 'packageurl-js' 2 | 3 | /** 4 | * Package is module that can be depended upon in manifest or build target. A 5 | * package is what you would download from a registry like NPM. 6 | * We consider all packages that are defined in the [Package URL spec](https://github.com/package-url/purl-spec/blob/1eae1e95d81fddf8ae7f06b4dfc7b5b5be0cc3e2/PURL-TYPES.rst) as being valid package types. 7 | */ 8 | export class Package { 9 | /** 10 | * @type {PackageURL} 11 | */ 12 | packageURL: PackageURL 13 | /** 14 | * @type {Array} 15 | */ 16 | dependencies: Array 17 | 18 | /** 19 | * A Package can be constructed with a PackageURL or a string conforming to 20 | * the Package URL format (https://github.com/package-url/purl-spec) 21 | * 22 | * @param {PackageURL | string} pkg 23 | */ 24 | constructor(pkg: PackageURL | string) { 25 | if (typeof pkg === 'string') { 26 | this.packageURL = PackageURL.fromString(pkg) 27 | } else { 28 | this.packageURL = pkg 29 | } 30 | this.dependencies = [] 31 | } 32 | 33 | /** 34 | * Associate a package child dependency with this package 35 | * 36 | * @param {Package} pkg 37 | * @returns {Package} 38 | */ 39 | dependsOn(pkg: Package): Package { 40 | this.dependencies.push(pkg) 41 | return this 42 | } 43 | 44 | /** 45 | * Add multiple packages as dependencies. 46 | * 47 | * @param {Array} pkgs 48 | * @returns {Package} 49 | */ 50 | dependsOnPackages(pkgs: Array): Package { 51 | for (const pkg of pkgs) { 52 | this.dependsOn(pkg) 53 | } 54 | return this 55 | } 56 | 57 | /** 58 | * packageDependencyIDs provides the list of package IDs of package dependencies 59 | */ 60 | get packageDependencyIDs() { 61 | return this.dependencies.map((dep) => dep.packageID()) 62 | } 63 | 64 | /** 65 | * packageID generates the unique package ID (currently, the Package URL) 66 | * 67 | * @returns {string} 68 | */ 69 | packageID(): string { 70 | return this.packageURL.toString() 71 | } 72 | 73 | /** 74 | * namespace of the package 75 | * 76 | * @returns {string} 77 | */ 78 | namespace(): string | null { 79 | return this.packageURL.namespace ?? null 80 | } 81 | 82 | /** 83 | * name of the package 84 | * 85 | * @returns {string} 86 | */ 87 | name(): string { 88 | return this.packageURL.name 89 | } 90 | 91 | /** 92 | * version of the package 93 | * 94 | * @returns {string} 95 | */ 96 | version(): string { 97 | return this.packageURL.version || '' 98 | } 99 | 100 | /** 101 | * Provided a "matcher" object with any of the string fields 'namespace', 102 | * 'name', or 'version', returns true if the Package has values matching the 103 | * matcher. 104 | * 105 | * @param {Object} matcher 106 | * @returns {boolean} 107 | */ 108 | matching(matcher: { 109 | namespace?: string 110 | name?: string 111 | version?: string 112 | }): boolean { 113 | // prettier-ignore 114 | return ( 115 | (matcher.namespace === undefined || 116 | this.packageURL.namespace === matcher.namespace) && 117 | (matcher.name === undefined || this.packageURL.name === matcher.name) && 118 | (matcher.version === undefined || 119 | this.packageURL.version === matcher.version) 120 | ) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/snapshot.test.ts: -------------------------------------------------------------------------------- 1 | import { context } from '@actions/github' 2 | import { describe, expect, it } from 'vitest' 3 | 4 | import { Manifest } from './manifest.js' 5 | import { PackageCache } from './package-cache.js' 6 | import { Snapshot, shaFromContext } from './snapshot.js' 7 | 8 | function roundTripJSON(obj: unknown): object { 9 | return JSON.parse(JSON.stringify(obj)) 10 | } 11 | 12 | const cache = new PackageCache() 13 | cache 14 | .package('pkg:npm/%40github/dependency-submission-toolkit@0.1.2') 15 | .dependsOn(cache.package('pkg:npm/%40actions/core@1.6.0')) 16 | 17 | const manifest = new Manifest('test', './some/test') 18 | manifest.addDirectDependency( 19 | cache.package('pkg:npm/%40github/dependency-submission-toolkit@0.1.2') 20 | ) 21 | manifest.addIndirectDependency(cache.package('pkg:npm/%40actions/core@1.6.0')) 22 | 23 | // add bogus git data to the context 24 | context.sha = '1000000000000000000000000000000000000000' 25 | context.ref = 'foo/bar/baz' 26 | context.eventName = 'push' 27 | 28 | describe('Snapshot', () => { 29 | it('renders expected JSON', () => { 30 | const snapshot = new Snapshot( 31 | exampleDetector, 32 | context, 33 | exampleJob, 34 | exampleDate 35 | ) 36 | snapshot.addManifest(manifest) 37 | expect(roundTripJSON(snapshot)).toEqual({ 38 | detector: { 39 | name: 'test detector', 40 | url: 'https://github.com/github/dependency-submission-toolkit', 41 | version: '0.0.1' 42 | }, 43 | version: 0, 44 | job: { 45 | id: '42', 46 | correlator: 'test' 47 | }, 48 | ref: 'foo/bar/baz', 49 | scanned: '2022-06-04T05:07:06.457Z', 50 | sha: '1000000000000000000000000000000000000000', 51 | manifests: { 52 | test: { 53 | resolved: { 54 | 'pkg:npm/%40github/dependency-submission-toolkit@0.1.2': { 55 | package_url: 56 | 'pkg:npm/%40github/dependency-submission-toolkit@0.1.2', 57 | relationship: 'direct', 58 | dependencies: ['pkg:npm/%40actions/core@1.6.0'] 59 | }, 60 | 'pkg:npm/%40actions/core@1.6.0': { 61 | package_url: 'pkg:npm/%40actions/core@1.6.0', 62 | relationship: 'indirect', 63 | dependencies: [] 64 | } 65 | }, 66 | name: 'test', 67 | file: { 68 | source_location: './some/test' 69 | } 70 | } 71 | } 72 | }) 73 | }) 74 | 75 | it('gets the correct sha from the context when given a pull request', () => { 76 | const prContext = context 77 | const expectedSha = 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2' 78 | prContext.eventName = 'pull_request' 79 | prContext.payload.pull_request = { 80 | number: 1, 81 | head: { 82 | sha: expectedSha 83 | } 84 | } 85 | 86 | const snapshot = new Snapshot( 87 | exampleDetector, 88 | prContext, 89 | exampleJob, 90 | exampleDate 91 | ) 92 | 93 | expect(snapshot.sha).toEqual(expectedSha) 94 | }) 95 | }) 96 | 97 | describe('shaFromContext', () => { 98 | it('gets the right sha from the context when given a pull_request event', () => { 99 | const expectedSha = '1234567890123456789012345678901234567890' 100 | const prContext = context 101 | prContext.eventName = 'pull_request' 102 | prContext.payload.pull_request = { 103 | number: 1, 104 | head: { 105 | sha: expectedSha 106 | } 107 | } 108 | expect(shaFromContext(prContext)).toEqual(expectedSha) 109 | }) 110 | 111 | it('gets the right sha from the context when given a pull_request_review event', () => { 112 | const expectedSha = 'abcdef1234567890123456789012345678901234' 113 | const prReviewContext = context 114 | prReviewContext.eventName = 'pull_request_review' 115 | prReviewContext.payload.pull_request = { 116 | number: 1, 117 | head: { 118 | sha: expectedSha 119 | } 120 | } 121 | expect(shaFromContext(prReviewContext)).toEqual(expectedSha) 122 | }) 123 | 124 | it('uses the primary sha from the context when given a push event', () => { 125 | const expectedSha = 'def1234567890123456789012345678901234567' 126 | const pushContext = context 127 | pushContext.eventName = 'push' 128 | pushContext.sha = expectedSha 129 | expect(shaFromContext(pushContext)).toEqual(expectedSha) 130 | }) 131 | }) 132 | 133 | const exampleDetector = { 134 | name: 'test detector', 135 | url: 'https://github.com/github/dependency-submission-toolkit', 136 | version: '0.0.1' 137 | } 138 | 139 | const exampleJob = { 140 | id: '42', 141 | correlator: 'test' 142 | } 143 | 144 | const exampleDate = new Date('2022-06-04T05:07:06.457Z') 145 | -------------------------------------------------------------------------------- /src/snapshot.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import * as github from '@actions/github' 3 | import type { Context } from '@actions/github/lib/context.js' 4 | import { RequestError } from '@octokit/request-error' 5 | import type { PullRequestEvent } from '@octokit/webhooks-types' 6 | 7 | import type { Manifest } from './manifest.js' 8 | 9 | /* 10 | Core functionality for creating a snapshot of a project's dependencies. 11 | */ 12 | 13 | /** 14 | * When multiple snapshots are submitted, Job provides the means for Snapshots to 15 | * be distinguished. Correlator must be unique between different Snapshots 16 | */ 17 | export type Job = { 18 | correlator: string 19 | id: string 20 | html_url?: string 21 | } 22 | 23 | /** 24 | * jobFromContext creates a job from a @actions/github Context 25 | * 26 | * @param {Context} context 27 | * @returns {Job} 28 | */ 29 | export function jobFromContext(context: Context): Job { 30 | return { 31 | correlator: context.job, 32 | id: context.runId.toString() 33 | } 34 | } 35 | 36 | /** 37 | * shaFromContext returns the sha of the commit that triggered the action, or the head sha of the PR. 38 | * 39 | * See https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request for more details 40 | * about why this function is necessary, but the short reason is that GITHUB_SHA is _not_ necessarily the head sha 41 | * of the PR when the event is pull_request (or some other related event types). 42 | * 43 | * @param {Context} context 44 | * @returns {string} 45 | */ 46 | export function shaFromContext(context: Context): string { 47 | const pullRequestEvents = [ 48 | 'pull_request', 49 | 'pull_request_comment', 50 | 'pull_request_review', 51 | 'pull_request_review_comment' 52 | // Note that pull_request_target is omitted here. 53 | // That event runs in the context of the base commit of the PR, 54 | // so the snapshot should not be associated with the head commit. 55 | ] 56 | if (pullRequestEvents.includes(context.eventName)) { 57 | const pr = (context.payload as PullRequestEvent).pull_request 58 | return pr.head.sha 59 | } 60 | return context.sha 61 | } 62 | 63 | /** 64 | * Detector provides metadata details about the detector used to generate the snapshot 65 | */ 66 | export type Detector = { 67 | name: string 68 | url: string 69 | version: string 70 | } 71 | 72 | /** 73 | * Manifests. 74 | */ 75 | type Manifests = Record 76 | 77 | /** 78 | * ISO8601Date. 79 | */ 80 | type ISO8601Date = string 81 | 82 | /** 83 | * Snapshot is the top-level container for Dependency Submission 84 | */ 85 | export class Snapshot { 86 | /** 87 | * @type {Manifests} 88 | */ 89 | manifests: Manifests 90 | /** 91 | * @type {number} 92 | */ 93 | version: number 94 | /** 95 | * @type {Job} 96 | */ 97 | job: Job 98 | /** 99 | * @type {string} sha of the Git commit 100 | */ 101 | sha: string 102 | /** 103 | * @type {string} ref of the Git commit; example: "refs/heads/main" 104 | */ 105 | ref: string 106 | /** 107 | * @type {ISO8601Date} 108 | */ 109 | scanned: ISO8601Date 110 | /** 111 | * @type {Detector} 112 | */ 113 | detector: Detector 114 | 115 | /** 116 | * All constructor parameters of a Snapshot are optional, but can be specified for specific overrides 117 | * 118 | * @param {Detector} detector 119 | * @param {Context} context 120 | * @param {Job} job 121 | * @param {Date} date 122 | * @param {number} version 123 | */ 124 | constructor( 125 | detector: Detector, 126 | context: Context = github.context, 127 | job?: Job, 128 | date: Date = new Date(), 129 | version = 0 130 | ) { 131 | this.detector = detector 132 | this.version = version 133 | this.job = job || jobFromContext(context) 134 | this.sha = shaFromContext(context) 135 | this.ref = context.ref 136 | this.scanned = date.toISOString() 137 | this.manifests = {} 138 | } 139 | 140 | /** 141 | * addManifest adds a manifest to the snapshot. At least one manifest must be added. 142 | * 143 | * @param {Manifest} manifest 144 | */ 145 | addManifest(manifest: Manifest) { 146 | this.manifests[manifest.name] = manifest 147 | } 148 | 149 | /** 150 | * prettyJSON formats an intended version of the Snapshot (useful for debugging) 151 | * 152 | * @returns {string} 153 | */ 154 | prettyJSON(): string { 155 | return JSON.stringify(this, undefined, 4) 156 | } 157 | } 158 | 159 | /** 160 | * submitSnapshot submits a snapshot to the Dependency Submission API 161 | * 162 | * @param {Snapshot} snapshot 163 | * @param {Context} context 164 | */ 165 | export async function submitSnapshot( 166 | snapshot: Snapshot, 167 | context: Context = github.context 168 | ) { 169 | core.setOutput('snapshot', JSON.stringify(snapshot)) 170 | core.notice('Submitting snapshot...') 171 | core.notice(snapshot.prettyJSON()) 172 | 173 | const repo = context.repo 174 | const githubToken = core.getInput('token') || (await core.getIDToken()) 175 | const octokit = github.getOctokit(githubToken) 176 | 177 | try { 178 | const response = await octokit.request( 179 | 'POST /repos/{owner}/{repo}/dependency-graph/snapshots', 180 | { 181 | headers: { 182 | accept: 'application/vnd.github.foo-bar-preview+json' 183 | }, 184 | owner: repo.owner, 185 | repo: repo.repo, 186 | ...snapshot 187 | } 188 | ) 189 | const result = response.data.result 190 | if (result === 'SUCCESS' || result === 'ACCEPTED') { 191 | core.notice( 192 | `Snapshot successfully created at ${response.data.created_at.toString()}` + 193 | ` with id ${response.data.id}` 194 | ) 195 | } else { 196 | core.error( 197 | `Snapshot creation failed with result: "${result}: ${response.data.message}"` 198 | ) 199 | } 200 | } catch (error) { 201 | if (error instanceof RequestError) { 202 | core.error( 203 | `HTTP Status ${error.status} for request ${error.request.method} ${error.request.url}` 204 | ) 205 | if (error.response) { 206 | core.error( 207 | `Response body:\n${JSON.stringify(error.response.data, undefined, 2)}` 208 | ) 209 | } 210 | } 211 | if (error instanceof Error) { 212 | core.error(error.message) 213 | if (error.stack) core.error(error.stack) 214 | } 215 | throw new Error(`Failed to submit snapshot: ${error}`) 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "isolatedModules": true, 4 | "module": "NodeNext", 5 | "moduleDetection": "force", 6 | "moduleResolution": "NodeNext", 7 | "noEmit": true 8 | }, 9 | "exclude": ["dist", "example", "node_modules"], 10 | "extends": "@tsconfig/strictest/tsconfig.json" 11 | } 12 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | clean: true, 6 | dts: true, 7 | format: ['esm', 'cjs'], 8 | minify: true, 9 | sourcemap: true, 10 | splitting: true, 11 | target: 'node20', 12 | treeshake: true 13 | }) 14 | --------------------------------------------------------------------------------