From 00bb3aae6011c9a48d5801c70076685607e03724 Mon Sep 17 00:00:00 2001 From: Akash Date: Wed, 12 Feb 2025 22:06:52 +0530 Subject: [PATCH 01/29] feat: initialize keploy-github-app-beta with Docker support and essential files Signed-off-by: Akash --- keploy-github-app-beta/.dockerignore | 12 + keploy-github-app-beta/.gitignore | 7 + keploy-github-app-beta/CODE_OF_CONDUCT.md | 73 + keploy-github-app-beta/CONTRIBUTING.md | 39 + keploy-github-app-beta/Dockerfile | 8 + keploy-github-app-beta/LICENSE | 15 + keploy-github-app-beta/README.md | 33 + keploy-github-app-beta/app.yml | 137 + keploy-github-app-beta/index.js | 56 + keploy-github-app-beta/package-lock.json | 3448 +++++++++++++++++ keploy-github-app-beta/package.json | 29 + .../test/fixtures/mock-cert.pem | 27 + .../test/fixtures/pull_request.opened.json | 17 + keploy-github-app-beta/test/index.test.js | 112 + 14 files changed, 4013 insertions(+) create mode 100644 keploy-github-app-beta/.dockerignore create mode 100644 keploy-github-app-beta/.gitignore create mode 100644 keploy-github-app-beta/CODE_OF_CONDUCT.md create mode 100644 keploy-github-app-beta/CONTRIBUTING.md create mode 100644 keploy-github-app-beta/Dockerfile create mode 100644 keploy-github-app-beta/LICENSE create mode 100644 keploy-github-app-beta/README.md create mode 100644 keploy-github-app-beta/app.yml create mode 100644 keploy-github-app-beta/index.js create mode 100644 keploy-github-app-beta/package-lock.json create mode 100644 keploy-github-app-beta/package.json create mode 100644 keploy-github-app-beta/test/fixtures/mock-cert.pem create mode 100644 keploy-github-app-beta/test/fixtures/pull_request.opened.json create mode 100644 keploy-github-app-beta/test/index.test.js diff --git a/keploy-github-app-beta/.dockerignore b/keploy-github-app-beta/.dockerignore new file mode 100644 index 0000000..c961acb --- /dev/null +++ b/keploy-github-app-beta/.dockerignore @@ -0,0 +1,12 @@ +**/node_modules/ +**/.git +**/README.md +**/LICENSE +**/.vscode +**/npm-debug.log +**/coverage +**/.env +**/.editorconfig +**/dist +**/*.pem +Dockerfile diff --git a/keploy-github-app-beta/.gitignore b/keploy-github-app-beta/.gitignore new file mode 100644 index 0000000..b3d906d --- /dev/null +++ b/keploy-github-app-beta/.gitignore @@ -0,0 +1,7 @@ +node_modules +npm-debug.log +*.pem +!mock-cert.pem +.env +coverage +lib diff --git a/keploy-github-app-beta/CODE_OF_CONDUCT.md b/keploy-github-app-beta/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..203ff8f --- /dev/null +++ b/keploy-github-app-beta/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at . All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/keploy-github-app-beta/CONTRIBUTING.md b/keploy-github-app-beta/CONTRIBUTING.md new file mode 100644 index 0000000..f6ebb81 --- /dev/null +++ b/keploy-github-app-beta/CONTRIBUTING.md @@ -0,0 +1,39 @@ +## Contributing + +[fork]: /fork +[pr]: /compare +[code-of-conduct]: CODE_OF_CONDUCT.md + +Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. + +Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. + +## Issues and PRs + +If you have suggestions for how this project could be improved, or want to report a bug, open an issue! We'd love all and any contributions. If you have questions, too, we'd love to hear them. + +We'd also love PRs. If you're thinking of a large PR, we advise opening up an issue first to talk about it, though! Look at the links below if you're not sure how to open a PR. + +## Submitting a pull request + +1. [Fork][fork] and clone the repository. +1. Configure and install the dependencies: `npm install`. +1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so there's no need to lint separately. +1. Create a new branch: `git checkout -b my-branch-name`. +1. Make your change, add tests, and make sure the tests still pass. +1. Push to your fork and [submit a pull request][pr]. +1. Pat your self on the back and wait for your pull request to be reviewed and merged. + +Here are a few things you can do that will increase the likelihood of your pull request being accepted: + +- Write and update tests. +- Keep your changes 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. +- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). + +Work in Progress pull requests are also welcome to get feedback early on, or if there is something blocked you. + +## Resources + +- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) +- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) +- [GitHub Help](https://help.github.com) diff --git a/keploy-github-app-beta/Dockerfile b/keploy-github-app-beta/Dockerfile new file mode 100644 index 0000000..bb1a3aa --- /dev/null +++ b/keploy-github-app-beta/Dockerfile @@ -0,0 +1,8 @@ +FROM node:20-slim +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production +RUN npm cache clean --force +ENV NODE_ENV="production" +COPY . . +CMD [ "npm", "start" ] diff --git a/keploy-github-app-beta/LICENSE b/keploy-github-app-beta/LICENSE new file mode 100644 index 0000000..409bb75 --- /dev/null +++ b/keploy-github-app-beta/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2025, Sky Singh + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/keploy-github-app-beta/README.md b/keploy-github-app-beta/README.md new file mode 100644 index 0000000..7de2f89 --- /dev/null +++ b/keploy-github-app-beta/README.md @@ -0,0 +1,33 @@ +# keploy-github-app-beta + +> A GitHub App built with [Probot](https://github.com/probot/probot) that Keploy app beta version + +## Setup + +```sh +# Install dependencies +npm install + +# Run the bot +npm start +``` + +## Docker + +```sh +# 1. Build container +docker build -t keploy-github-app-beta . + +# 2. Start container +docker run -e APP_ID= -e PRIVATE_KEY= keploy-github-app-beta +``` + +## Contributing + +If you have suggestions for how keploy-github-app-beta could be improved, or want to report a bug, open an issue! We'd love all and any contributions. + +For more, check out the [Contributing Guide](CONTRIBUTING.md). + +## License + +[ISC](LICENSE) © 2025 Sky Singh diff --git a/keploy-github-app-beta/app.yml b/keploy-github-app-beta/app.yml new file mode 100644 index 0000000..e5418ba --- /dev/null +++ b/keploy-github-app-beta/app.yml @@ -0,0 +1,137 @@ +# This is a GitHub App Manifest. These settings will be used by default when +# initially configuring your GitHub App. +# +# NOTE: changing this file will not update your GitHub App settings. +# You must visit github.com/settings/apps/your-app-name to edit them. +# +# Read more about configuring your GitHub App: +# https://probot.github.io/docs/development/#configuring-a-github-app +# +# Read more about GitHub App Manifests: +# https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/ + +# The list of events the GitHub App subscribes to. +# Uncomment the event names below to enable them. +default_events: + # - check_run + # - check_suite + # - commit_comment + # - create + # - delete + - deployment + # - deployment_status + # - fork + # - gollum + # - issue_comment + # - issues + # - label + # - milestone + # - member + # - membership + # - org_block + # - organization + # - page_build + # - project + # - project_card + # - project_column + # - public + - pull_request +# - pull_request_review +# - pull_request_review_comment +# - push +# - release +# - repository +# - repository_import +# - status +# - team +# - team_add +# - watch + +# The set of permissions needed by the GitHub App. The format of the object uses +# the permission name for the key (for example, issues) and the access type for +# the value (for example, write). +# Valid values are `read`, `write`, and `none` +default_permissions: + # Repository creation, deletion, settings, teams, and collaborators. + # https://developer.github.com/v3/apps/permissions/#permission-on-administration + # administration: read + + # Checks on code. + # https://developer.github.com/v3/apps/permissions/#permission-on-checks + # checks: read + + # Repository contents, commits, branches, downloads, releases, and merges. + # https://developer.github.com/v3/apps/permissions/#permission-on-contents + # contents: read + + # Deployments and deployment statuses. + # https://developer.github.com/v3/apps/permissions/#permission-on-deployments + deployments: write + + # Issues and related comments, assignees, labels, and milestones. + # https://developer.github.com/v3/apps/permissions/#permission-on-issues + # issues: write + + # Search repositories, list collaborators, and access repository '. + # https://developer.github.com/v3/apps/permissions/#metadata-permissions + metadata: read + + # Retrieve Pages statuses, configuration, and builds, as well as create new builds. + # https://developer.github.com/v3/apps/permissions/#permission-on-pages + # pages: read + + # Pull requests and related comments, assignees, labels, milestones, and merges. + # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests + pull_requests: read + + # Manage the post-receive hooks for a repository. + # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks + # repository_hooks: read + + # Manage repository projects, columns, and cards. + # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects + # repository_projects: read + + # Retrieve security vulnerability alerts. + # https://developer.github.com/v4/object/repositoryvulnerabilityalert/ + # vulnerability_alerts: read + + # Commit statuses. + # https://developer.github.com/v3/apps/permissions/#permission-on-statuses + # statuses: read + + # Organization members and teams. + # https://developer.github.com/v3/apps/permissions/#permission-on-members + # members: read + + # View and manage users blocked by the organization. + # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking + # organization_user_blocking: read + + # Manage organization projects, columns, and cards. + # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects + # organization_projects: read + + # Manage team discussions and related comments. + # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions + # team_discussions: read + + # Manage the post-receive hooks for an organization. + # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks + # organization_hooks: read + + # Get notified of, and update, content references. + # https://developer.github.com/v3/apps/permissions/ + # organization_administration: read +# The name of the GitHub App. Defaults to the name specified in package.json +# name: My Probot App + +# The homepage of your GitHub App. +# url: https://example.com/ + +# A description of the GitHub App. +# description: A description of my awesome app + +# Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app. +# Default: true +# public: false diff --git a/keploy-github-app-beta/index.js b/keploy-github-app-beta/index.js new file mode 100644 index 0000000..9c7d556 --- /dev/null +++ b/keploy-github-app-beta/index.js @@ -0,0 +1,56 @@ +// Deployments API example +// See: https://developer.github.com/v3/repos/deployments/ to learn more + +/** + * This is the main entrypoint to your Probot app + * @param {import('probot').Probot} app + */ +export default (app) => { + // Your code here + app.log.info("Yay, the app was loaded!"); + app.on( + ["pull_request.opened", "pull_request.synchronize"], + async (context) => { + // Creates a deployment on a pull request event + // Then sets the deployment status to success + // NOTE: this example doesn't actually integrate with a cloud + // provider to deploy your app, it just demos the basic API usage. + app.log.info(context.payload); + + // Probot API note: context.repo() => { username: 'hiimbex', repo: 'testing-things' } + const res = await context.octokit.repos.createDeployment( + context.repo({ + ref: context.payload.pull_request.head.ref, // The ref to deploy. This can be a branch, tag, or SHA. + task: "deploy", // Specifies a task to execute (e.g., deploy or deploy:migrations). + auto_merge: true, // Attempts to automatically merge the default branch into the requested ref, if it is behind the default branch. + required_contexts: [], // The status contexts to verify against commit status checks. If this parameter is omitted, then all unique contexts will be verified before a deployment is created. To bypass checking entirely pass an empty array. Defaults to all unique contexts. + payload: { + schema: "rocks!", + }, // JSON payload with extra information about the deployment. Default: "" + environment: "production", // Name for the target deployment environment (e.g., production, staging, qa) + description: "My Probot App's first deploy!", // Short description of the deployment + transient_environment: false, // Specifies if the given environment is specific to the deployment and will no longer exist at some point in the future. + production_environment: true, // Specifies if the given environment is one that end-users directly interact with. + }), + ); + + const deploymentId = res.data.id; + await context.octokit.repos.createDeploymentStatus( + context.repo({ + deployment_id: deploymentId, + state: "success", // The state of the status. Can be one of error, failure, inactive, pending, or success + log_url: "https://example.com", // The log URL to associate with this status. This URL should contain output to keep the user updated while the task is running or serve as historical information for what happened in the deployment. + description: "My Probot App set a deployment status!", // A short description of the status. + environment_url: "https://example.com", // Sets the URL for accessing your environment. + auto_inactive: true, // Adds a new inactive status to all prior non-transient, non-production environment deployments with the same repository and environment name as the created status's deployment. An inactive status is only added to deployments that had a success state. + }), + ); + }, + ); + + // For more information on building apps: + // https://probot.github.io/docs/ + + // To get your app running against GitHub, see: + // https://probot.github.io/docs/development/ +}; diff --git a/keploy-github-app-beta/package-lock.json b/keploy-github-app-beta/package-lock.json new file mode 100644 index 0000000..708ff82 --- /dev/null +++ b/keploy-github-app-beta/package-lock.json @@ -0,0 +1,3448 @@ +{ + "name": "keploy-github-app-beta", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "keploy-github-app-beta", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "probot": "^13.0.1" + }, + "devDependencies": { + "nock": "^14.0.0-beta.5", + "smee-client": "^2.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "license": "MIT" + }, + "node_modules/@mswjs/interceptors": { + "version": "0.37.6", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.6.tgz", + "integrity": "sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@octokit/auth-app": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.1.3.tgz", + "integrity": "sha512-dcaiteA6Y/beAlDLZOPNReN3FGHu+pARD6OHfh3T9f3EO09++ec+5wt3KtGGSSs2Mp5tI8fQwdMOEnrzBLfgUA==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-app": "^7.1.0", + "@octokit/auth-oauth-user": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "deprecation": "^2.3.1", + "lru-cache": "npm:@wolfy1339/lru-cache@^11.0.2-patch.1", + "universal-github-app-jwt": "^1.1.2", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-app/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/auth-app/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/auth-oauth-app": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-7.1.0.tgz", + "integrity": "sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^6.1.0", + "@octokit/auth-oauth-user": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "@types/btoa-lite": "^1.0.0", + "btoa-lite": "^1.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-app/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/auth-oauth-device": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-6.1.0.tgz", + "integrity": "sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-methods": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-device/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/auth-oauth-user": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-4.1.0.tgz", + "integrity": "sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-oauth-device": "^6.1.0", + "@octokit/oauth-methods": "^4.1.0", + "@octokit/request": "^8.3.1", + "@octokit/types": "^13.0.0", + "btoa-lite": "^1.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/auth-oauth-user/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/auth-unauthenticated": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz", + "integrity": "sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/endpoint/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/oauth-authorization-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz", + "integrity": "sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-4.1.0.tgz", + "integrity": "sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw==", + "license": "MIT", + "dependencies": { + "@octokit/oauth-authorization-url": "^6.0.2", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "btoa-lite": "^1.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/oauth-methods/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/oauth-methods/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-enterprise-compatibility": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-compatibility/-/plugin-enterprise-compatibility-4.1.0.tgz", + "integrity": "sha512-a8QehVu9Iy4k+m2XgG2rrF4m9vhlRIaefOMr0yJzgQCt4KpiTj5mZVrzSwagyOovkJdD0yDolQazBQZqPWTFSQ==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", + "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz", + "integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.2.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^5.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", + "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^23.0.1" + } + }, + "node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/webhooks": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-12.3.1.tgz", + "integrity": "sha512-BVwtWE3rRXB9IugmQTfKspqjNa8q+ab73ddkV9k1Zok3XbuOxJUi4lTYk5zBZDhfWb/Y2H+RO9Iggm25gsqeow==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/webhooks-methods": "^4.1.0", + "@octokit/webhooks-types": "7.6.1", + "aggregate-error": "^3.1.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-methods": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-4.1.0.tgz", + "integrity": "sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/webhooks-types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.6.1.tgz", + "integrity": "sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==", + "license": "MIT" + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.1.tgz", + "integrity": "sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", + "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.1.tgz", + "integrity": "sha512-SgHEKXoVxOjc20ZYusPG3Fh+RLIZTSa4x8QtD3NfgAUDyqdFFS9W1F2ZVbZkqDCdyMcQG02Ok4duUGLHJXHgbA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.1", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.0.tgz", + "integrity": "sha512-04VHHV1KIN/c1wLWwzmLI02d/welgscBJ4BuDqrHaxd+ZIdlVXK9UYQsYf3JwSeF52z/4YoSzr8bfdVBSWoMAg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.0.tgz", + "integrity": "sha512-Q57JGpH6T4dkYHo9tKXONgLtxzsh1ZEW5M9A/OwKrZFyEpLqWgjhcZ3hIuVvDlhb426iDF1f9FPToV/mi5rpeA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.36" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.0.tgz", + "integrity": "sha512-88+qCHZC02up8PwKHk0UQKLLqGGURzS3hFQBZC7PnGwReuoKjHXS1o29H58S+QkXJpkTr2GACbx8j6mUoGjNPA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.0.tgz", + "integrity": "sha512-XFWVx6k0XlU8lu6cBlCa29ONtVt6ADEjmxtyAyeF2+rifk8uBJbk1La0yIVfI0DoKURGbaEDTNelaXG9l/lNNQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.44.1.tgz", + "integrity": "sha512-RoVeMGKcNttNfXMSl6W4fsYoCAYP1vi6ZAWIGhBY+o7R9Y0afA7f9JJL0j8LHbyb0P0QhSYk+6O56OwI2k4iRQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.0.tgz", + "integrity": "sha512-JGwmHhBkRT2G/BYNV1aGI+bBjJu4fJUD/5/Jat0EWZa2ftrLV3YE8z84Fiij/wK32oMZ88eS8DI4ecLGZhpqsQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.0.tgz", + "integrity": "sha512-at8GceTtNxD1NfFKGAuwtqM41ot/TpcLh+YsGe4dhf7gvv1HW/ZWdq6nfRtS6UjIvZJOokViqLPJ3GVtZItAnQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.0.tgz", + "integrity": "sha512-Cc8SMf+nLqp0fi8oAnooNEfwZWFnzMiBHCGmDFYqmgjPylyLmi83b+NiTns/rKGwlErpW0AGPt0sMpkbNlzn8w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.45.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.1.tgz", + "integrity": "sha512-VH6mU3YqAKTePPfUPwfq4/xr049774qWtfTuJqVHoVspCLiT3bW+fCQ1toZxt6cxRPYASoYaBsMA3CWo8B8rcw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.1.tgz", + "integrity": "sha512-ThLmzAQDs7b/tdKI3BV2+yawuF09jF111OFsovqT1Qj3D8vjwKBwhi/rDE5xethwn4tSXtZcJ9hBsVAlWFQZ7g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.1", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.0.tgz", + "integrity": "sha512-4HqP9IBC8e7pW9p90P3q4ox0XlbLGme65YTrA3UTLvqvo4Z6b0puqZQP203YFu8m9rE/luLfaG7/xrwwqMUpJw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.0.tgz", + "integrity": "sha512-LB+3xiNzc034zHfCtgs4ITWhq6Xvdo8bsq7amR058jZlf2aXXDrN9SV4si4z2ya9QX4tz6r4eZJwDkXOp14/AQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.0.tgz", + "integrity": "sha512-SlT0+bLA0Lg3VthGje+bSZatlGHw/vwgQywx0R/5u9QC59FddTQSPJeWNw29M6f8ScORMeUOOTwihlQAn4GkJQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.0.tgz", + "integrity": "sha512-HFdvqf2+w8sWOuwtEXayGzdZ2vWpCKEQv5F7+2DSA74Te/Cv4rvb2E5So5/lh+ok4/RAIPuvCbCb/SHQFzMmbw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.0.tgz", + "integrity": "sha512-Tn7emHAlvYDFik3vGU0mdwvWJDwtITtkJ+5eT2cUquct6nIs+H8M47sqMJkCpyPe5QIBJoTOHxmc6mj9lz6zDw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.51.0.tgz", + "integrity": "sha512-cMKASxCX4aFxesoj3WK8uoQ0YUrRvnfxaO72QWI2xLu5ZtgX/QvdGBlU3Ehdond5eb74c2s1cqRQUIptBnKz1g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.0.tgz", + "integrity": "sha512-mtVv6UeaaSaWTeZtLo4cx4P5/ING2obSqfWGItIFSunQBrYROfhuVe7wdIrFUs2RH1tn2YYpAJyMaRe/bnTTIQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.0.tgz", + "integrity": "sha512-tWWyymgwYcTwZ4t8/rLDfPYbOTF3oYB8SxnYMtIQ1zEf5uDm90Ku3i6U/vhaMyfHNlIHvDhvJh+qx5Nc4Z3Acg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.0.tgz", + "integrity": "sha512-qLslv/EPuLj0IXFvcE3b0EqhWI8LKmrgRPIa4gUd8DllbBpqJAvLNJSv3cC6vWwovpbSI3bagNO/3Q2SuXv2xA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.44.0.tgz", + "integrity": "sha512-t16pQ7A4WYu1yyQJZhRKIfUNvl5PAaF2pEteLvgJb/BWdd1oNuU1rOYt4S825kMy+0q4ngiX281Ss9qiwHfxFQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.50.0.tgz", + "integrity": "sha512-TtLxDdYZmBhFswm8UIsrDjh/HFBeDXd4BLmE8h2MxirNHewLJ0VS9UUddKKEverb5Sm2qFVjqRjcU+8Iw4FJ3w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", + "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.0.tgz", + "integrity": "sha512-aTUWbzbFMFeRODn3720TZO0tsh/49T8H3h8vVnVKJ+yE36AeW38Uj/8zykQ/9nO8Vrtjr5yKuX3uMiG/W8FKNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.0.tgz", + "integrity": "sha512-9zhjDpUDOtD+coeADnYEJQ0IeLVCj7w/hqzIutdp5NqS1VqTAanaEfsEcSypyvYv5DX3YOsTUoF+nr2wDXPETA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.0.tgz", + "integrity": "sha512-vm+V255NGw9gaSsPD6CP0oGo8L55BffBc8KnxqsMuc6XiAD1L8SFNzsW0RHhxJFqy9CJaJh+YiJ5EHXuZ5rZBw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.30.0.tgz", + "integrity": "sha512-4VlGgo32k2EQ2wcCY3vEU28A0O13aOtHz3Xt2/2U5FAh9EfhD6t6DqL5Z6yAnRCntbTFDU4YfbpyzSlHNWycPw==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, + "node_modules/@prisma/instrumentation": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-5.22.0.tgz", + "integrity": "sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.8", + "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0", + "@opentelemetry/sdk-trace-base": "^1.22" + } + }, + "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/api-logs": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", + "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@probot/get-private-key": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@probot/get-private-key/-/get-private-key-1.1.2.tgz", + "integrity": "sha512-yVgyCdTyooGX6+czDLkJahEcwgBWZsKH9xbjvjDNVFjY3QtiI/tHRiB3zjgJCQMZehXxv2CFHZQSpWRXdr6CeQ==", + "license": "ISC" + }, + "node_modules/@probot/octokit-plugin-config": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@probot/octokit-plugin-config/-/octokit-plugin-config-2.0.1.tgz", + "integrity": "sha512-aWQYzPY2xiKscTVTKveghtbglqZ+W4eBLIdK1C/cNiFIofy3AxKogWgEZj29PjIe5ZRYx0sRHAPc/pkcXyOmTQ==", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@probot/pino": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@probot/pino/-/pino-3.0.0.tgz", + "integrity": "sha512-2pLi8gIzDI5NEbu24SOBXqflTc3o95StJE6+jiw3R3n4i3B5hCJjlzCB2j3OETeohtCTuDSc//GuGPyDfZehWg==", + "license": "MIT", + "dependencies": { + "@sentry/node": "^8.0.0", + "pino-pretty": "^13.0.0", + "pump": "^3.0.0", + "split2": "^4.0.0" + }, + "bin": { + "pino-probot": "bin/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/core": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", + "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", + "license": "MIT", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/node": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.55.0.tgz", + "integrity": "sha512-h10LJLDTRAzYgay60Oy7moMookqqSZSviCWkkmHZyaDn+4WURnPp5SKhhfrzPRQcXKrweiOwDSHBgn1tweDssg==", + "license": "MIT", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/instrumentation-amqplib": "^0.46.0", + "@opentelemetry/instrumentation-connect": "0.43.0", + "@opentelemetry/instrumentation-dataloader": "0.16.0", + "@opentelemetry/instrumentation-express": "0.47.0", + "@opentelemetry/instrumentation-fastify": "0.44.1", + "@opentelemetry/instrumentation-fs": "0.19.0", + "@opentelemetry/instrumentation-generic-pool": "0.43.0", + "@opentelemetry/instrumentation-graphql": "0.47.0", + "@opentelemetry/instrumentation-hapi": "0.45.1", + "@opentelemetry/instrumentation-http": "0.57.1", + "@opentelemetry/instrumentation-ioredis": "0.47.0", + "@opentelemetry/instrumentation-kafkajs": "0.7.0", + "@opentelemetry/instrumentation-knex": "0.44.0", + "@opentelemetry/instrumentation-koa": "0.47.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.44.0", + "@opentelemetry/instrumentation-mongodb": "0.51.0", + "@opentelemetry/instrumentation-mongoose": "0.46.0", + "@opentelemetry/instrumentation-mysql": "0.45.0", + "@opentelemetry/instrumentation-mysql2": "0.45.0", + "@opentelemetry/instrumentation-nestjs-core": "0.44.0", + "@opentelemetry/instrumentation-pg": "0.50.0", + "@opentelemetry/instrumentation-redis-4": "0.46.0", + "@opentelemetry/instrumentation-tedious": "0.18.0", + "@opentelemetry/instrumentation-undici": "0.10.0", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.28.0", + "@prisma/instrumentation": "5.22.0", + "@sentry/core": "8.55.0", + "@sentry/opentelemetry": "8.55.0", + "import-in-the-middle": "^1.11.2" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/opentelemetry": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.55.0.tgz", + "integrity": "sha512-UvatdmSr3Xf+4PLBzJNLZ2JjG1yAPWGe/VrJlJAqyTJ2gKeTzgXJJw8rp4pbvNZO8NaTGEYhhO+scLUj0UtLAQ==", + "license": "MIT", + "dependencies": { + "@sentry/core": "8.55.0" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.28.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/btoa-lite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz", + "integrity": "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==", + "license": "MIT" + }, + "node_modules/@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.8.tgz", + "integrity": "sha512-7fx54m60nLFUVYlxAB1xpe9CBWX2vSrk50Y6ogRJ1v5xxtba7qXTg5BgYDN5dq+yuQQ9HaVlHJyAAt1/mxryFg==", + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "license": "Apache-2.0" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT" + }, + "node_modules/btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", + "license": "MIT" + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "license": "ISC" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-in-the-middle": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.0.tgz", + "integrity": "sha512-YG86SYDtrL/Yu8JgfWb7kjQ0myLeT1whw6fs/ZHFkXFcbk9zJU9lOCsSJHpvaPumU11nN3US7NW6x1YTk+HrUA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ioredis": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.5.0.tgz", + "integrity": "sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "name": "@wolfy1339/lru-cache", + "version": "11.0.2-patch.1", + "resolved": "https://registry.npmjs.org/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz", + "integrity": "sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==", + "license": "ISC", + "engines": { + "node": "18 >=18.20 || 20 || >=22" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nock": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.1.tgz", + "integrity": "sha512-IJN4O9pturuRdn60NjQ7YkFt6Rwei7ZKaOwb1tvUIIqTgeD0SDDAX3vrqZD4wcXczeEy/AsUXxpGpP/yHqV7xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mswjs/interceptors": "^0.37.3", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">=18.20.0 <20 || >=20.12.1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/octokit-auth-probot": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/octokit-auth-probot/-/octokit-auth-probot-2.0.1.tgz", + "integrity": "sha512-HzOJ4EPC5OJN6oZEoKTMYtqUQ2ZSKHmDWbLHfFB7JYpho9Zb+aJmDfRShd5a/eGvmIzbZ0NRIWjmnvspDp8JAQ==", + "license": "ISC", + "dependencies": { + "@octokit/auth-app": "^6.1.3", + "@octokit/auth-token": "^4.0.0", + "@octokit/auth-unauthenticated": "^5.0.1", + "@octokit/types": "^12.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.1.tgz", + "integrity": "sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pino": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", + "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-http": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-10.4.0.tgz", + "integrity": "sha512-vjQsKBE+VN1LVchjbfLE7B6nBeGASZNRNKsR68VS0DolTm5R3zo+47JX1wjm0O96dcbvA7vnqt8YqOWlG5nN0w==", + "license": "MIT", + "dependencies": { + "get-caller-file": "^2.0.5", + "pino": "^9.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, + "node_modules/pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/probot": { + "version": "13.4.3", + "resolved": "https://registry.npmjs.org/probot/-/probot-13.4.3.tgz", + "integrity": "sha512-Vr14ET5JwXQcXDsztLFIGzQHzU2Wl7ZWg8B6dhvBRRd1wFwnBGfJISm7NqZRpM1vQCn6QDNSRKGo6RYnloWz/A==", + "license": "ISC", + "dependencies": { + "@octokit/core": "^5.0.2", + "@octokit/plugin-enterprise-compatibility": "^4.0.1", + "@octokit/plugin-paginate-rest": "^9.1.4", + "@octokit/plugin-rest-endpoint-methods": "^10.1.5", + "@octokit/plugin-retry": "^6.0.1", + "@octokit/plugin-throttling": "^8.1.3", + "@octokit/request": "^8.1.6", + "@octokit/types": "^12.3.0", + "@octokit/webhooks": "^12.0.10", + "@probot/get-private-key": "^1.1.2", + "@probot/octokit-plugin-config": "^2.0.1", + "@probot/pino": "^3.0.0", + "@types/express": "^4.17.21", + "bottleneck": "^2.19.5", + "commander": "^12.0.0", + "deepmerge": "^4.3.1", + "dotenv": "^16.3.1", + "express": "^4.21.0", + "ioredis": "^5.3.2", + "js-yaml": "^4.1.0", + "lru-cache": "npm:@wolfy1339/lru-cache@^11.0.2-patch.1", + "octokit-auth-probot": "^2.0.1", + "pino": "^9.0.0", + "pino-http": "^10.0.0", + "pkg-conf": "^3.1.0", + "update-dotenv": "^1.1.1" + }, + "bin": { + "probot": "bin/probot.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.1.tgz", + "integrity": "sha512-fgZEz/t3FDrU9o7EhI+iNNq1pNNpJImOvX72HUd6RoFiw8MaKd8/gR5tLuc8A0G0e55LMbP6ImjnmXY6zrTmjw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/smee-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/smee-client/-/smee-client-2.0.4.tgz", + "integrity": "sha512-RxXCs0mfaxpI8JF4SeTM51XtRiprzW5g20HVt4aTQ36EB+RaN0aj0m/4EbXLGdfPlqahQ09d3UnJYmALN2CbYw==", + "dev": true, + "license": "ISC", + "dependencies": { + "commander": "^12.0.0", + "eventsource": "^2.0.2", + "validator": "^13.11.0" + }, + "bin": { + "smee": "bin/smee.js" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" + }, + "node_modules/universal-github-app-jwt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.2.0.tgz", + "integrity": "sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g==", + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "^9.0.0", + "jsonwebtoken": "^9.0.2" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "license": "ISC" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-dotenv": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-dotenv/-/update-dotenv-1.1.1.tgz", + "integrity": "sha512-3cIC18In/t0X/yH793c00qqxcKD8jVCgNOPif/fGQkFpYMGecM9YAc+kaAKXuZsM2dE9I9wFI7KvAuNX22SGMQ==", + "license": "ISC", + "peerDependencies": { + "dotenv": "*" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + } + } +} diff --git a/keploy-github-app-beta/package.json b/keploy-github-app-beta/package.json new file mode 100644 index 0000000..6b5a4b0 --- /dev/null +++ b/keploy-github-app-beta/package.json @@ -0,0 +1,29 @@ +{ + "name": "keploy-github-app-beta", + "version": "1.0.0", + "private": true, + "description": "Keploy app beta version", + "author": "Sky Singh", + "license": "ISC", + "homepage": "https://github.com//", + "keywords": [ + "probot", + "github", + "probot-app" + ], + "scripts": { + "start": "probot run ./index.js", + "test": "node --test" + }, + "dependencies": { + "probot": "^13.0.1" + }, + "devDependencies": { + "nock": "^14.0.0-beta.5", + "smee-client": "^2.0.0" + }, + "engines": { + "node": ">= 18" + }, + "type": "module" +} diff --git a/keploy-github-app-beta/test/fixtures/mock-cert.pem b/keploy-github-app-beta/test/fixtures/mock-cert.pem new file mode 100644 index 0000000..f2f271c --- /dev/null +++ b/keploy-github-app-beta/test/fixtures/mock-cert.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAli7V49NdZe+XYC1pLaHM0te8kiDmZBJ1u2HJHN8GdbROB6NO +VpC3xK7NxQn6xpvZ9ux20NvcDvGle+DOptZztBH+np6h2jZQ1/kD1yG1eQvVH4th +/9oqHuIjmIfO8lIe4Hyd5Fw5xHkGqVETTGR+0c7kdZIlHmkOregUGtMYZRUi4YG+ +q0w+uFemiHpGKXbeCIAvkq7aIkisEzvPWfSyYdA6WJHpxFk7tD7D8VkzABLVRHCq +AuyqPG39BhGZcGLXx5rGK56kDBJkyTR1t3DkHpwX+JKNG5UYNwOG4LcQj1fteeta +TdkYUMjIyWbanlMYyC+dq7B5fe7el99jXQ1gXwIDAQABAoIBADKfiPOpzKLOtzzx +MbHzB0LO+75aHq7+1faayJrVxqyoYWELuB1P3NIMhknzyjdmU3t7S7WtVqkm5Twz +lBUC1q+NHUHEgRQ4GNokExpSP4SU63sdlaQTmv0cBxmkNarS6ZuMBgDy4XoLvaYX +MSUf/uukDLhg0ehFS3BteVFtdJyllhDdTenF1Nb1rAeN4egt8XLsE5NQDr1szFEG +xH5lb+8EDtzgsGpeIddWR64xP0lDIKSZWst/toYKWiwjaY9uZCfAhvYQ1RsO7L/t +sERmpYgh+rAZUh/Lr98EI8BPSPhzFcSHmtqzzejvC5zrZPHcUimz0CGA3YBiLoJX +V1OrxmECgYEAxkd8gpmVP+LEWB3lqpSvJaXcGkbzcDb9m0OPzHUAJDZtiIIf0UmO +nvL68/mzbCHSj+yFjZeG1rsrAVrOzrfDCuXjAv+JkEtEx0DIevU1u60lGnevOeky +r8Be7pmymFB9/gzQAd5ezIlTv/COgoO986a3h1yfhzrrzbqSiivw308CgYEAwecI +aZZwqH3GifR+0+Z1B48cezA5tC8LZt5yObGzUfxKTWy30d7lxe9N59t0KUVt/QL5 +qVkd7mqGzsUMyxUN2U2HVnFTWfUFMhkn/OnCnayhILs8UlCTD2Xxoy1KbQH/9FIr +xf0pbMNJLXeGfyRt/8H+BzSZKBw9opJBWE4gqfECgYBp9FdvvryHuBkt8UQCRJPX +rWsRy6pY47nf11mnazpZH5Cmqspv3zvMapF6AIxFk0leyYiQolFWvAv+HFV5F6+t +Si1mM8GCDwbA5zh6pEBDewHhw+UqMBh63HSeUhmi1RiOwrAA36CO8i+D2Pt+eQHv +ir52IiPJcs4BUNrv5Q1BdwKBgBHgVNw3LGe8QMOTMOYkRwHNZdjNl2RPOgPf2jQL +d/bFBayhq0jD/fcDmvEXQFxVtFAxKAc+2g2S8J67d/R5Gm/AQAvuIrsWZcY6n38n +pfOXaLt1x5fnKcevpFlg4Y2vM4O416RHNLx8PJDehh3Oo/2CSwMrDDuwbtZAGZok +icphAoGBAI74Tisfn+aeCZMrO8KxaWS5r2CD1KVzddEMRKlJvSKTY+dOCtJ+XKj1 +OsZdcDvDC5GtgcywHsYeOWHldgDWY1S8Z/PUo4eK9qBXYBXp3JEZQ1dqzFdz+Txi +rBn2WsFLsxV9j2/ugm0PqWVBcU2bPUCwvaRu3SOms2teaLwGCkhr +-----END RSA PRIVATE KEY----- diff --git a/keploy-github-app-beta/test/fixtures/pull_request.opened.json b/keploy-github-app-beta/test/fixtures/pull_request.opened.json new file mode 100644 index 0000000..79e9fd9 --- /dev/null +++ b/keploy-github-app-beta/test/fixtures/pull_request.opened.json @@ -0,0 +1,17 @@ +{ + "action": "opened", + "pull_request": { + "head": { + "ref": "hiimbex-patch-1" + } + }, + "repository": { + "name": "testing-things", + "owner": { + "login": "hiimbex" + } + }, + "installation": { + "id": 2 + } +} diff --git a/keploy-github-app-beta/test/index.test.js b/keploy-github-app-beta/test/index.test.js new file mode 100644 index 0000000..9e7a25f --- /dev/null +++ b/keploy-github-app-beta/test/index.test.js @@ -0,0 +1,112 @@ +import nock from "nock"; +// Requiring our app implementation +import myProbotApp from "../index.js"; +import { Probot, ProbotOctokit } from "probot"; +// Requiring our fixtures +//import payload from "./fixtures/pull_request.opened" with { type: "json" }; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; +import { describe, beforeEach, afterEach, test } from "node:test"; +import assert from "node:assert"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +const payload = JSON.parse( + fs.readFileSync( + path.join(__dirname, "fixtures/pull_request.opened.json"), + "utf-8", + ), +); + +const deployment = { + ref: "hiimbex-patch-1", + task: "deploy", + auto_merge: true, + required_contexts: [], + payload: { + schema: "rocks!", + }, + environment: "production", + description: "My Probot App's first deploy!", + transient_environment: false, + production_environment: true, +}; + +const deploymentStatus = { + state: "success", + log_url: "https://example.com", + description: "My Probot App set a deployment status!", + environment_url: "https://example.com", + auto_inactive: true, +}; + +const privateKey = fs.readFileSync( + path.join(__dirname, "fixtures/mock-cert.pem"), + "utf-8", +); + +describe("My Probot app", () => { + let probot; + + beforeEach(() => { + nock.disableNetConnect(); + probot = new Probot({ + appId: 123, + privateKey, + // disable request throttling and retries for testing + Octokit: ProbotOctokit.defaults({ + retry: { enabled: false }, + throttle: { enabled: false }, + }), + }); + // Load our app into probot + probot.load(myProbotApp); + }); + + test("creates a deployment and a deployment status", async () => { + const mock = nock("https://api.github.com") + // Test that we correctly return a test token + .post("/app/installations/2/access_tokens") + .reply(200, { + token: "test", + permissions: { + deployments: "write", + pull_requests: "read", + }, + }) + + // Test that a deployment is created + .post("/repos/hiimbex/testing-things/deployments", (body) => { + assert.deepStrictEqual(body, deployment); + return true; + }) + .reply(200, { id: 123 }) + + // Test that a deployment status is created + .post( + "/repos/hiimbex/testing-things/deployments/123/statuses", + (body) => { + assert.deepStrictEqual(body, deploymentStatus); + return true; + }, + ) + .reply(200); + + // Receive a webhook event + await probot.receive({ name: "pull_request", payload }); + + assert.deepStrictEqual(mock.pendingMocks(), []); + }); + + afterEach(() => { + nock.cleanAll(); + nock.enableNetConnect(); + }); +}); + +// For more information about testing with Jest see: +// https://facebook.github.io/jest/ + +// For more information about testing with Nock see: +// https://github.com/nock/nock From f8f5aa8f50c435f628ea61f7b470d33eb7d46564 Mon Sep 17 00:00:00 2001 From: Akash Date: Wed, 12 Feb 2025 22:21:47 +0530 Subject: [PATCH 02/29] feat: add check for /keploy folder existence in pull request events Signed-off-by: Akash Signed-off-by: Sky Singh --- keploy-github-app-beta/index.js | 36 ++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/keploy-github-app-beta/index.js b/keploy-github-app-beta/index.js index 9c7d556..cee58c4 100644 --- a/keploy-github-app-beta/index.js +++ b/keploy-github-app-beta/index.js @@ -11,12 +11,46 @@ export default (app) => { app.on( ["pull_request.opened", "pull_request.synchronize"], async (context) => { + try { + // Get repository and PR details + const { owner, repo } = context.repo(); + const { ref } = context.payload.pull_request.head; + + // Try to get the contents of /keploy directory + try { + await context.octokit.repos.getContent({ + owner, + repo, + path: 'keploy', + ref: ref + }); + app.log.info('/keploy folder exists'); + + // Continue with your deployment logic here + // ... rest of your deployment code ... + + } catch (error) { + if (error.status === 404) { + app.log.warn('/keploy folder not found'); + // You might want to create a check run or comment on the PR + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: '⚠️ Warning: The `/keploy` folder is missing in this PR.' + }); + return; + } + throw error; + } + + } catch (error) { + app.log.error('Error checking /keploy folder:', error); + } // Creates a deployment on a pull request event // Then sets the deployment status to success // NOTE: this example doesn't actually integrate with a cloud // provider to deploy your app, it just demos the basic API usage. app.log.info(context.payload); - // Probot API note: context.repo() => { username: 'hiimbex', repo: 'testing-things' } const res = await context.octokit.repos.createDeployment( context.repo({ From 2865040387eb73e2806fd87a5fde266065f2735c Mon Sep 17 00:00:00 2001 From: Akash Date: Wed, 12 Feb 2025 23:51:57 +0530 Subject: [PATCH 03/29] feat: added Keploy Github App Signed-off-by: Sky Singh --- .github/workflows/keploy.yml | 20 + keploy-github-app-beta/.dockerignore | 12 - keploy-github-app-beta/.gitignore | 5 + keploy-github-app-beta/CODE_OF_CONDUCT.md | 73 - keploy-github-app-beta/CONTRIBUTING.md | 39 - keploy-github-app-beta/Dockerfile | 8 - keploy-github-app-beta/LICENSE | 15 - keploy-github-app-beta/README.md | 33 - keploy-github-app-beta/app.yml | 137 - keploy-github-app-beta/diffparser.ts | 114 + keploy-github-app-beta/index.js | 90 - keploy-github-app-beta/index.ts | 55 + keploy-github-app-beta/keploy.ts | 21 + .../keploy/test-set-0/tests/test-1.yaml | 48 + keploy-github-app-beta/lint.ts | 21 + keploy-github-app-beta/llm.ts | 262 ++ keploy-github-app-beta/package-lock.json | 2522 ++++++++++++++++- keploy-github-app-beta/package.json | 18 +- keploy-github-app-beta/pr.ts | 256 ++ keploy-github-app-beta/rules.md | 6 + keploy-github-app-beta/rules.ts | 35 + keploy-github-app-beta/security.ts | 27 + keploy-github-app-beta/src/addLabel.ts | 63 + keploy-github-app-beta/src/cli.ts | 70 + keploy-github-app-beta/src/config/models.ts | 75 + .../src/config/userConfig.ts | 29 + keploy-github-app-beta/test.ts | 3 + .../test/fixtures/mock-cert.pem | 27 - .../test/fixtures/pull_request.opened.json | 17 - keploy-github-app-beta/test/index.test.js | 112 - keploy-github-app-beta/tsconfig.json | 111 + keploy-github-app-beta/utils.ts | 22 + 32 files changed, 3661 insertions(+), 685 deletions(-) create mode 100644 .github/workflows/keploy.yml delete mode 100644 keploy-github-app-beta/.dockerignore delete mode 100644 keploy-github-app-beta/CODE_OF_CONDUCT.md delete mode 100644 keploy-github-app-beta/CONTRIBUTING.md delete mode 100644 keploy-github-app-beta/Dockerfile delete mode 100644 keploy-github-app-beta/LICENSE delete mode 100644 keploy-github-app-beta/README.md delete mode 100644 keploy-github-app-beta/app.yml create mode 100644 keploy-github-app-beta/diffparser.ts delete mode 100644 keploy-github-app-beta/index.js create mode 100644 keploy-github-app-beta/index.ts create mode 100644 keploy-github-app-beta/keploy.ts create mode 100644 keploy-github-app-beta/keploy/test-set-0/tests/test-1.yaml create mode 100644 keploy-github-app-beta/lint.ts create mode 100644 keploy-github-app-beta/llm.ts create mode 100644 keploy-github-app-beta/pr.ts create mode 100644 keploy-github-app-beta/rules.md create mode 100644 keploy-github-app-beta/rules.ts create mode 100644 keploy-github-app-beta/security.ts create mode 100644 keploy-github-app-beta/src/addLabel.ts create mode 100644 keploy-github-app-beta/src/cli.ts create mode 100644 keploy-github-app-beta/src/config/models.ts create mode 100644 keploy-github-app-beta/src/config/userConfig.ts create mode 100644 keploy-github-app-beta/test.ts delete mode 100644 keploy-github-app-beta/test/fixtures/mock-cert.pem delete mode 100644 keploy-github-app-beta/test/fixtures/pull_request.opened.json delete mode 100644 keploy-github-app-beta/test/index.test.js create mode 100644 keploy-github-app-beta/tsconfig.json create mode 100644 keploy-github-app-beta/utils.ts diff --git a/.github/workflows/keploy.yml b/.github/workflows/keploy.yml new file mode 100644 index 0000000..7570bd5 --- /dev/null +++ b/.github/workflows/keploy.yml @@ -0,0 +1,20 @@ +name: Run test-cases + +on: + pull_request: + types: [opened, synchronize] + +jobs: + my_job: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Keploy Report + uses: keploy/testgpt@main + with: + working-directory: ${{ github.workspace }} + delay: 10 + command: node src/app.js + keploy-path: . \ No newline at end of file diff --git a/keploy-github-app-beta/.dockerignore b/keploy-github-app-beta/.dockerignore deleted file mode 100644 index c961acb..0000000 --- a/keploy-github-app-beta/.dockerignore +++ /dev/null @@ -1,12 +0,0 @@ -**/node_modules/ -**/.git -**/README.md -**/LICENSE -**/.vscode -**/npm-debug.log -**/coverage -**/.env -**/.editorconfig -**/dist -**/*.pem -Dockerfile diff --git a/keploy-github-app-beta/.gitignore b/keploy-github-app-beta/.gitignore index b3d906d..6cadb8a 100644 --- a/keploy-github-app-beta/.gitignore +++ b/keploy-github-app-beta/.gitignore @@ -5,3 +5,8 @@ npm-debug.log .env coverage lib +scripts/* +/dist + +myenv/ + diff --git a/keploy-github-app-beta/CODE_OF_CONDUCT.md b/keploy-github-app-beta/CODE_OF_CONDUCT.md deleted file mode 100644 index 203ff8f..0000000 --- a/keploy-github-app-beta/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,73 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, race, -religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or - advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at . All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org diff --git a/keploy-github-app-beta/CONTRIBUTING.md b/keploy-github-app-beta/CONTRIBUTING.md deleted file mode 100644 index f6ebb81..0000000 --- a/keploy-github-app-beta/CONTRIBUTING.md +++ /dev/null @@ -1,39 +0,0 @@ -## Contributing - -[fork]: /fork -[pr]: /compare -[code-of-conduct]: CODE_OF_CONDUCT.md - -Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. - -Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. - -## Issues and PRs - -If you have suggestions for how this project could be improved, or want to report a bug, open an issue! We'd love all and any contributions. If you have questions, too, we'd love to hear them. - -We'd also love PRs. If you're thinking of a large PR, we advise opening up an issue first to talk about it, though! Look at the links below if you're not sure how to open a PR. - -## Submitting a pull request - -1. [Fork][fork] and clone the repository. -1. Configure and install the dependencies: `npm install`. -1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so there's no need to lint separately. -1. Create a new branch: `git checkout -b my-branch-name`. -1. Make your change, add tests, and make sure the tests still pass. -1. Push to your fork and [submit a pull request][pr]. -1. Pat your self on the back and wait for your pull request to be reviewed and merged. - -Here are a few things you can do that will increase the likelihood of your pull request being accepted: - -- Write and update tests. -- Keep your changes 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. -- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). - -Work in Progress pull requests are also welcome to get feedback early on, or if there is something blocked you. - -## Resources - -- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) -- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) -- [GitHub Help](https://help.github.com) diff --git a/keploy-github-app-beta/Dockerfile b/keploy-github-app-beta/Dockerfile deleted file mode 100644 index bb1a3aa..0000000 --- a/keploy-github-app-beta/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM node:20-slim -WORKDIR /usr/src/app -COPY package.json package-lock.json ./ -RUN npm ci --production -RUN npm cache clean --force -ENV NODE_ENV="production" -COPY . . -CMD [ "npm", "start" ] diff --git a/keploy-github-app-beta/LICENSE b/keploy-github-app-beta/LICENSE deleted file mode 100644 index 409bb75..0000000 --- a/keploy-github-app-beta/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -ISC License - -Copyright (c) 2025, Sky Singh - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/keploy-github-app-beta/README.md b/keploy-github-app-beta/README.md deleted file mode 100644 index 7de2f89..0000000 --- a/keploy-github-app-beta/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# keploy-github-app-beta - -> A GitHub App built with [Probot](https://github.com/probot/probot) that Keploy app beta version - -## Setup - -```sh -# Install dependencies -npm install - -# Run the bot -npm start -``` - -## Docker - -```sh -# 1. Build container -docker build -t keploy-github-app-beta . - -# 2. Start container -docker run -e APP_ID= -e PRIVATE_KEY= keploy-github-app-beta -``` - -## Contributing - -If you have suggestions for how keploy-github-app-beta could be improved, or want to report a bug, open an issue! We'd love all and any contributions. - -For more, check out the [Contributing Guide](CONTRIBUTING.md). - -## License - -[ISC](LICENSE) © 2025 Sky Singh diff --git a/keploy-github-app-beta/app.yml b/keploy-github-app-beta/app.yml deleted file mode 100644 index e5418ba..0000000 --- a/keploy-github-app-beta/app.yml +++ /dev/null @@ -1,137 +0,0 @@ -# This is a GitHub App Manifest. These settings will be used by default when -# initially configuring your GitHub App. -# -# NOTE: changing this file will not update your GitHub App settings. -# You must visit github.com/settings/apps/your-app-name to edit them. -# -# Read more about configuring your GitHub App: -# https://probot.github.io/docs/development/#configuring-a-github-app -# -# Read more about GitHub App Manifests: -# https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/ - -# The list of events the GitHub App subscribes to. -# Uncomment the event names below to enable them. -default_events: - # - check_run - # - check_suite - # - commit_comment - # - create - # - delete - - deployment - # - deployment_status - # - fork - # - gollum - # - issue_comment - # - issues - # - label - # - milestone - # - member - # - membership - # - org_block - # - organization - # - page_build - # - project - # - project_card - # - project_column - # - public - - pull_request -# - pull_request_review -# - pull_request_review_comment -# - push -# - release -# - repository -# - repository_import -# - status -# - team -# - team_add -# - watch - -# The set of permissions needed by the GitHub App. The format of the object uses -# the permission name for the key (for example, issues) and the access type for -# the value (for example, write). -# Valid values are `read`, `write`, and `none` -default_permissions: - # Repository creation, deletion, settings, teams, and collaborators. - # https://developer.github.com/v3/apps/permissions/#permission-on-administration - # administration: read - - # Checks on code. - # https://developer.github.com/v3/apps/permissions/#permission-on-checks - # checks: read - - # Repository contents, commits, branches, downloads, releases, and merges. - # https://developer.github.com/v3/apps/permissions/#permission-on-contents - # contents: read - - # Deployments and deployment statuses. - # https://developer.github.com/v3/apps/permissions/#permission-on-deployments - deployments: write - - # Issues and related comments, assignees, labels, and milestones. - # https://developer.github.com/v3/apps/permissions/#permission-on-issues - # issues: write - - # Search repositories, list collaborators, and access repository '. - # https://developer.github.com/v3/apps/permissions/#metadata-permissions - metadata: read - - # Retrieve Pages statuses, configuration, and builds, as well as create new builds. - # https://developer.github.com/v3/apps/permissions/#permission-on-pages - # pages: read - - # Pull requests and related comments, assignees, labels, milestones, and merges. - # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests - pull_requests: read - - # Manage the post-receive hooks for a repository. - # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks - # repository_hooks: read - - # Manage repository projects, columns, and cards. - # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects - # repository_projects: read - - # Retrieve security vulnerability alerts. - # https://developer.github.com/v4/object/repositoryvulnerabilityalert/ - # vulnerability_alerts: read - - # Commit statuses. - # https://developer.github.com/v3/apps/permissions/#permission-on-statuses - # statuses: read - - # Organization members and teams. - # https://developer.github.com/v3/apps/permissions/#permission-on-members - # members: read - - # View and manage users blocked by the organization. - # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking - # organization_user_blocking: read - - # Manage organization projects, columns, and cards. - # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects - # organization_projects: read - - # Manage team discussions and related comments. - # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions - # team_discussions: read - - # Manage the post-receive hooks for an organization. - # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks - # organization_hooks: read - - # Get notified of, and update, content references. - # https://developer.github.com/v3/apps/permissions/ - # organization_administration: read -# The name of the GitHub App. Defaults to the name specified in package.json -# name: My Probot App - -# The homepage of your GitHub App. -# url: https://example.com/ - -# A description of the GitHub App. -# description: A description of my awesome app - -# Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app. -# Default: true -# public: false diff --git a/keploy-github-app-beta/diffparser.ts b/keploy-github-app-beta/diffparser.ts new file mode 100644 index 0000000..3cf99a5 --- /dev/null +++ b/keploy-github-app-beta/diffparser.ts @@ -0,0 +1,114 @@ +// diffParser.ts +import parseDiff from 'parse-diff'; + + +async function parseGitDiffFromLLMOutput(llmOutput: any) { + const diffStart = llmOutput.indexOf('```diff'); + const diffEnd = llmOutput.indexOf('```', diffStart + 1); + return llmOutput.substring(diffStart, diffEnd); +} + + +export async function reviewPR(context: any, app: any, llmOutput: any) { +// export async function reviewPR(context: any, app: any) { + //trim the llmOutput to only include the diff + const ifLGTM = llmOutput.includes('LGTM'); + if (ifLGTM) { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'LGTM: LLM analysis is successful' + }); + return; + } + const gitDiff = await parseGitDiffFromLLMOutput(llmOutput); +// const gitDiff = `diff --git a/src/index.js b/src/index.js +// index abc1234..def5678 100644 +// --- a/src/index.js +// +++ b/src/index.js +// @@ -1,5 +1,5 @@ +// function add(a, b) { +// - return a - b; // Bug: Subtraction instead of addition +// + return a + b; // Fixed: Now correctly adds +// } + +// function subtract(a, b) { +// @@ -10,7 +10,7 @@ function subtract(a, b) { +// function multiply(a, b) { +// return a * b; +// } + +// -function divide(a, b) { +// - return a / b; +// +function divide(a, b) { +// + return b !== 0 ? a / b : NaN; // Added check for division by zero +// } +// diff --git a/tests/test.js b/tests/test.js +// index 1234567..890abcd 100644 +// --- a/tests/test.js +// +++ b/tests/test.js +// @@ -5,6 +5,6 @@ describe('Math operations', () => { +// expect(add(2, 3)).toBe(5); +// }); + +// - test('subtract should return the difference', () => { +// + test('subtract should return the correct difference', () => { +// expect(subtract(5, 3)).toBe(2); +// }); +// }); +// `; + // Create inline comments from the diff + await createInlineCommentsFromDiff(gitDiff, context, app); + + // Post the LLM analysis as a comment + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: llmOutput, + }); +} + + +export async function createInlineCommentsFromDiff(diff: string, context: any, app: any) { + const parsedFiles = parseDiff(diff); + const { pull_request, repository } = context.payload; + + for (const file of parsedFiles) { + if (file.to === '/dev/null') { + app.log.info(`Skipping deleted file: ${file.from}`); + continue; + } + + const filePath = file.to || file.from; + + for (const chunk of file.chunks) { + for (const change of chunk.changes) { + if (change.type !== 'add') continue; // Focus on additions for comments + + const line = change.ln; // Line number in the new file + const content = change.content.slice(1).trim(); + const body = `Suggested change:\n\`\`\`suggestion\n${content}\n\`\`\``; + + try { + await context.octokit.pulls.createReviewComment({ + owner: repository.owner.login, + repo: repository.name, + pull_number: pull_request.number, + commit_id: pull_request.head.sha, + path: filePath, + body, + line, + mediaType: { + previews: ['comfort-fade'], // Enable comfort-fade preview + }, + }); + app.log.info(`Created comment on ${filePath} line ${line}`); + } catch (error: any) { + app.log.error( + `Failed to create comment for ${filePath} line ${line}: ${error.message}` + ); + } + } + } + } +} \ No newline at end of file diff --git a/keploy-github-app-beta/index.js b/keploy-github-app-beta/index.js deleted file mode 100644 index cee58c4..0000000 --- a/keploy-github-app-beta/index.js +++ /dev/null @@ -1,90 +0,0 @@ -// Deployments API example -// See: https://developer.github.com/v3/repos/deployments/ to learn more - -/** - * This is the main entrypoint to your Probot app - * @param {import('probot').Probot} app - */ -export default (app) => { - // Your code here - app.log.info("Yay, the app was loaded!"); - app.on( - ["pull_request.opened", "pull_request.synchronize"], - async (context) => { - try { - // Get repository and PR details - const { owner, repo } = context.repo(); - const { ref } = context.payload.pull_request.head; - - // Try to get the contents of /keploy directory - try { - await context.octokit.repos.getContent({ - owner, - repo, - path: 'keploy', - ref: ref - }); - app.log.info('/keploy folder exists'); - - // Continue with your deployment logic here - // ... rest of your deployment code ... - - } catch (error) { - if (error.status === 404) { - app.log.warn('/keploy folder not found'); - // You might want to create a check run or comment on the PR - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: '⚠️ Warning: The `/keploy` folder is missing in this PR.' - }); - return; - } - throw error; - } - - } catch (error) { - app.log.error('Error checking /keploy folder:', error); - } - // Creates a deployment on a pull request event - // Then sets the deployment status to success - // NOTE: this example doesn't actually integrate with a cloud - // provider to deploy your app, it just demos the basic API usage. - app.log.info(context.payload); - // Probot API note: context.repo() => { username: 'hiimbex', repo: 'testing-things' } - const res = await context.octokit.repos.createDeployment( - context.repo({ - ref: context.payload.pull_request.head.ref, // The ref to deploy. This can be a branch, tag, or SHA. - task: "deploy", // Specifies a task to execute (e.g., deploy or deploy:migrations). - auto_merge: true, // Attempts to automatically merge the default branch into the requested ref, if it is behind the default branch. - required_contexts: [], // The status contexts to verify against commit status checks. If this parameter is omitted, then all unique contexts will be verified before a deployment is created. To bypass checking entirely pass an empty array. Defaults to all unique contexts. - payload: { - schema: "rocks!", - }, // JSON payload with extra information about the deployment. Default: "" - environment: "production", // Name for the target deployment environment (e.g., production, staging, qa) - description: "My Probot App's first deploy!", // Short description of the deployment - transient_environment: false, // Specifies if the given environment is specific to the deployment and will no longer exist at some point in the future. - production_environment: true, // Specifies if the given environment is one that end-users directly interact with. - }), - ); - - const deploymentId = res.data.id; - await context.octokit.repos.createDeploymentStatus( - context.repo({ - deployment_id: deploymentId, - state: "success", // The state of the status. Can be one of error, failure, inactive, pending, or success - log_url: "https://example.com", // The log URL to associate with this status. This URL should contain output to keep the user updated while the task is running or serve as historical information for what happened in the deployment. - description: "My Probot App set a deployment status!", // A short description of the status. - environment_url: "https://example.com", // Sets the URL for accessing your environment. - auto_inactive: true, // Adds a new inactive status to all prior non-transient, non-production environment deployments with the same repository and environment name as the created status's deployment. An inactive status is only added to deployments that had a success state. - }), - ); - }, - ); - - // For more information on building apps: - // https://probot.github.io/docs/ - - // To get your app running against GitHub, see: - // https://probot.github.io/docs/development/ -}; diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts new file mode 100644 index 0000000..24c5d44 --- /dev/null +++ b/keploy-github-app-beta/index.ts @@ -0,0 +1,55 @@ +// Deployments API example +// See: https://developer.github.com/v3/repos/deployments/ to learn more + +/** + * This is the main entrypoint to your Probot app + * @param {import('probot').Probot} app + */ +import { getAllPrDetails } from "./pr.js"; +import { handlePrAnalysis } from "./llm.js"; +import { handleKeployWorkflowTrigger } from "./keploy.js"; +import { handleError } from "./utils.js"; +import { handleSecurityWorkflowTrigger } from "./security.js"; +import { promptUserConfig } from './src/cli.js'; +import { reviewPR } from './diffparser.js'; +import { handleLintWorkflowTrigger } from "./lint.js"; + +let config: any; + +export default async (app: { + log: { info: (arg0: string, arg1?: string) => void }; + on: (arg0: string[], arg1: (context: any) => Promise) => void; +}) => { + try { + // Get user configuration through CLI + config = await promptUserConfig(); + // selectedModel = config.model; + app.log.info(`Initialized with API url: ${config.apiEndpoint} for use case: ${config.useCase} and model : ${config.selectedModel}`); + } catch (error) { + app.log.info("Failed to get user configuration"); + process.exit(1); + } + + app.log.info("Yay, the app was loaded!"); + + const handlePrEvent = async (context: any) => { + try { + const prData = await getAllPrDetails(context, app); + app.log.info(JSON.stringify(prData), "Full PR data collected"); + + const llmOutput = await handlePrAnalysis(context, prData , config.apiEndpoint , config.selectedModel, app); + // const stringllmOutput = await JSON.stringify(llmOutput); + // app.log.info(JSON.stringify(stringllmOutput), "LLM analysis complete"); + await reviewPR(context, app, llmOutput); + // await reviewPR(context, app); + + await handleKeployWorkflowTrigger(context); + await handleSecurityWorkflowTrigger(context); + await handleLintWorkflowTrigger(context); + } catch (error) { + await handleError(context, app, error); + } + }; + + app.on(["pull_request.opened", "pull_request.synchronize"], handlePrEvent); +}; diff --git a/keploy-github-app-beta/keploy.ts b/keploy-github-app-beta/keploy.ts new file mode 100644 index 0000000..0d2b513 --- /dev/null +++ b/keploy-github-app-beta/keploy.ts @@ -0,0 +1,21 @@ +export async function handleKeployWorkflowTrigger(context: { repo: () => { owner: any; repo: any; }; payload: { pull_request: { head: { ref: any; }; number: any; }; }; octokit: { repos: { getContent: (arg0: { owner: any; repo: any; path: string; ref: any; }) => any; }; actions: { createWorkflowDispatch: (arg0: { owner: any; repo: any; workflow_id: string; ref: any; }) => any; }; issues: { createComment: (arg0: any) => any; }; }; }) { + const { owner, repo } = context.repo(); + const { ref } = context.payload.pull_request.head; + + try { + await context.octokit.actions.createWorkflowDispatch({ + owner, repo, workflow_id: 'keploy.yaml', ref + }); + } catch (error : any) { + if (error.status === 404) { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: '⚠️ Failed to run Keploy Tests' + }); + return; + } + throw error; + } + } + \ No newline at end of file diff --git a/keploy-github-app-beta/keploy/test-set-0/tests/test-1.yaml b/keploy-github-app-beta/keploy/test-set-0/tests/test-1.yaml new file mode 100644 index 0000000..3670001 --- /dev/null +++ b/keploy-github-app-beta/keploy/test-set-0/tests/test-1.yaml @@ -0,0 +1,48 @@ +# Generated by Keploy (2.4.5) +version: api.keploy.io/v1beta1 +kind: Http +name: test-1 +spec: + metadata: {} + req: + method: POST + proto_major: 1 + proto_minor: 1 + url: http://localhost:8080/url + header: + Accept: '*/*' + Content-Length: "33" + Content-Type: application/json + Host: localhost:8080 + User-Agent: curl/7.81.0 + body: |- + { + "url": "https://google.com" + } + timestamp: 2025-02-22T23:12:25.837014092Z + resp: + status_code: 500 + header: + Content-Length: "929" + Content-Type: application/json; charset=utf-8 + Date: Sat, 22 Feb 2025 23:12:50 GMT + body: '{"error":{"Desc":{"Servers":[{"Addr":"localhost:27017","Arbiters":null,"AverageRTT":0,"AverageRTTSet":false,"Compression":null,"CanonicalAddr":"","ElectionID":"000000000000000000000000","HeartbeatInterval":0,"HelloOK":false,"Hosts":null,"LastError":{"ConnectionID":"","Wrapped":{"Code":0,"Message":"connection(localhost:27017[-63]) socket was unexpectedly closed: EOF","Labels":["NetworkError"],"Name":"","Wrapped":{"ConnectionID":"localhost:27017[-63]","Wrapped":{}},"TopologyVersion":null}},"LastUpdateTime":"0001-01-01T00:00:00Z","LastWriteTime":"0001-01-01T00:00:00Z","MaxBatchCount":0,"MaxDocumentSize":0,"MaxMessageSize":0,"Members":null,"Passives":null,"Passive":false,"Primary":"","ReadOnly":false,"ServiceID":null,"SessionTimeoutMinutes":0,"SetName":"","SetVersion":0,"Tags":null,"TopologyVersion":null,"Kind":0,"WireVersion":null}],"SetName":"","Kind":0,"SessionTimeoutMinutes":0,"CompatibilityErr":null},"Wrapped":{}}}' + status_message: Internal Server Error + proto_major: 0 + proto_minor: 0 + timestamp: 2025-02-22T23:12:52.683242659Z + objects: [] + assertions: + noise: + body.error.Desc.Servers.LastUpdateTime: [] + body.error.Desc.Servers.LastWriteTime: [] + header.Date: [] + created: 1740265972 +curl: |- + curl --request POST \ + --url http://localhost:8080/url \ + --header 'Host: localhost:8080' \ + --header 'User-Agent: curl/7.81.0' \ + --header 'Accept: */*' \ + --header 'Content-Type: application/json' \ + --data "{\n \"url\": \"https://google.com\"\n}" diff --git a/keploy-github-app-beta/lint.ts b/keploy-github-app-beta/lint.ts new file mode 100644 index 0000000..6bcc185 --- /dev/null +++ b/keploy-github-app-beta/lint.ts @@ -0,0 +1,21 @@ +export async function handleLintWorkflowTrigger(context: { repo: () => { owner: any; repo: any; }; payload: { pull_request: { head: { ref: any; }; number: any; }; }; octokit: { repos: { getContent: (arg0: { owner: any; repo: any; path: string; ref: any; }) => any; }; actions: { createWorkflowDispatch: (arg0: { owner: any; repo: any; workflow_id: string; ref: any; }) => any; }; issues: { createComment: (arg0: any) => any; }; }; }) { + const { owner, repo } = context.repo(); + const { ref } = context.payload.pull_request.head; + + try { + await context.octokit.actions.createWorkflowDispatch({ + owner, repo, workflow_id: 'lint.yaml', ref + }); + } catch (error : any) { + if (error.status === 404) { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'Lint workflow failed' + }); + return; + } + throw error; + } + } + \ No newline at end of file diff --git a/keploy-github-app-beta/llm.ts b/keploy-github-app-beta/llm.ts new file mode 100644 index 0000000..a24f93b --- /dev/null +++ b/keploy-github-app-beta/llm.ts @@ -0,0 +1,262 @@ +import axios from 'axios'; +import { getRulesForLLM } from './rules.js'; +import { loadConfig } from './src/config/userConfig.js'; +import { useCaseModels } from './src/config/models.js'; +import { determineLabelFromAnalysis, addLabelToPR } from './src/addLabel.js'; +// import { createInlineCommentsFromDiff } from './diffparser.js'; + + +export async function handlePrAnalysis( + context: { + octokit: { issues: { createComment: (arg0: any) => any; }; }; + repo: () => any; + payload: { pull_request: { number: any; }; }; + }, + prData: any, API : string, model: string , app: any +) { + // Load current configuration + const config = loadConfig(); + const useCase = config ? useCaseModels[config.useCase] : null; + + // Build the config info comment + const configInfo = `## Keploy Configuration +Use Case: ${config?.useCase || 'Not configured'} +API Endpoint: ${config?.apiEndpoint || 'Not configured'} + +### Suggested Models for ${useCase?.name || 'current use case'}: +${useCase?.suggestedModels.map(model => `- ${model.name}: ${model.link}`).join('\n') || 'No models configured'} +`; + // // Post config info + // await context.octokit.issues.createComment({ + // ...context.repo(), + // issue_number: context.payload.pull_request.number, + // body: configInfo, + // }); + + // Convert the code changes to a JSON string + const code_changes = JSON.stringify(prData.code_changes, null, 2); // Adding indentation for better readability + + // Build the issue context if available + const issueContext = prData.linked_issue ? ` + Linked Issue: + Number: #${prData.linked_issue.number} + Title: ${prData.linked_issue.title} + Description: ${prData.linked_issue.body} + State: ${prData.linked_issue.state} + Labels: ${prData.linked_issue.labels.join(', ')} + Assignees: ${prData.linked_issue.assignees.join(', ')} + + Issue Discussion: + ${prData.linked_issue.comments.map((c: any) => + `${c.author} (${c.created_at}): ${c.body}` + ).join('\n')} + ` : 'No linked issue found'; + + // Build the analysis comment + const analysis = `PR Analysis using ${API}: + Title: ${prData.metadata.title} + Author: ${prData.metadata.author} + Files Changed: ${prData.metadata.changed_files} + Status: ${prData.metadata.state} + Code Changes Summary: ${code_changes} + + ${issueContext} + + Summary: ${prData.metadata.body?.substring(0, 100)}...`; + + + // Post the comment to the PR + // await context.octokit.issues.createComment({ + // ...context.repo(), + // issue_number: context.payload.pull_request.number, + // body: analysis, + // }); + + // Get the rules for LLM + const rules = await getRulesForLLM(context); + + // If the rules are fetched successfully, post them as a comment + // await context.octokit.issues.createComment({ + // ...context.repo(), + // issue_number: context.payload.pull_request.number, + // body: rules.success ? rules.rules : rules.error, + // }); + + // call the LLM analysis function with selected model + const llmOutput = await analyzeLLM(prData, rules.rules , API , model, app); + + // Determine and add appropriate label + const labelToAdd = await determineLabelFromAnalysis(llmOutput); + await addLabelToPR(context, context.payload.pull_request.number, labelToAdd); + + return llmOutput; +} + +; +export async function analyzeLLM(prData: any, rules: any, API: string, model: string , app : any) { + const analysisContext = { + repository: { + name: prData.repository.name, + owner: prData.repository.owner, + readme: prData.repository.readme, + structure: prData.repository.structure + }, + pr: prData, + rules: rules, + issue_context: prData.linked_issue ? { + issue_number: prData.linked_issue.number, + issue_title: prData.linked_issue.title, + issue_description: prData.linked_issue.body, + issue_status: prData.linked_issue.state, + issue_labels: prData.linked_issue.labels, + issue_assignees: prData.linked_issue.assignees, + issue_discussion: prData.linked_issue.comments + } : null + }; + + const stringanalysisContext = JSON.stringify(analysisContext, null, 2); + + const prompt = ` + + Project Structure: + ${prData.repository.structure} + + README Content: + ${prData.repository.readme} + + PR Context: + ${stringanalysisContext} + + Given the above repository context and PR changes, please analyze the changes and: + 1. Verify if the changes align with the project's structure and purpose as described in the README + 2. Check if the changes follow the project's conventions visible in the folder structure + 3. Suggest improvements or identify potential issues + + Suggest the changes in the format of git diff. + + You must follow the following pattern for suggestions: + + Suggested change: + diff --git a/path/to/file b/path/to/file + index abc1234..def5678 100644 + --- a/path/to/file + +++ b/path/to/file + @@ -line,count +line,count @@ + actual diff content + + Here is some context about the PR made: ${stringanalysisContext}. + + + Please check the codebase diff for the following rules: + ${rules} + + ## GitHub PR Title + +\`$title\` + +## Description + +\`\`\` +$description +\`\`\` + +## Summary of changes + +\`\`\` +$short_summary +\`\`\` + +## IMPORTANT Instructions + +Input: New hunks annotated with line numbers and old hunks (replaced code). Hunks represent incomplete code fragments. +Additional Context: PR title, description, summaries and comment chains. +Task: Review new hunks for substantive issues using provided context and respond with comments if necessary. +Output: Review comments in markdown with exact line number ranges in new hunks. Start and end line numbers must be within the same hunk. For single-line comments, start=end line number. Must use example response format below. +Use fenced code blocks using the relevant language identifier where applicable. +Don't annotate code snippets with line numbers. Format and indent code correctly. +Do not use \`suggestion\` code blocks. +For fixes, use \`diff\` code blocks, marking changes with \`+\` or \`-\`. The line number range for comments with fix snippets must exactly match the range to replace in the new hunk. + +- Do NOT provide general feedback, summaries, explanations of changes, or praises + for making good additions. +- Focus solely on offering specific, objective insights based on the + given context and refrain from making broad comments about potential impacts on + the system or question intentions behind the changes. +- Do NOT write anything else in the output, just the review comments or LGTM!. +- DO NOT TAKE CONTEXT FROM PREVIOUS CONTEXT. ONLY USE THE CONTEXT PROVIDED IN THE CURRENT PROMPT. +- LIMIT YOUR RESPONSE TO ONLY LGTM OR THE DIFF, DO NOT GO ON YAPPING AND LIMIT YOUR REVIEW COMMENTS TO ONLY 20 WORDS AND THE DIFF +If there are no issues found on a line range, you MUST respond with the +text \`LGTM!\` for that line range in the review section. + +## Example + +### Example changes + +---new_hunk--- +\`\`\` + z = x / y + return z + +20: def add(x, y): +21: z = x + y +22: retrn z +23: +24: def multiply(x, y): +25: return x * y + +def subtract(x, y): + z = x - y +\`\`\` + +---old_hunk--- +\`\`\` + z = x / y + return z + +def add(x, y): + return x + y + +def subtract(x, y): + z = x - y +\`\`\` + +---comment_chains--- +\`\`\` +Please review this change. +\`\`\` + +---end_change_section--- + +### Example response + +22-22: +There's a syntax error in the add function. +\`\`\`diff +- retrn z ++ return z +\`\`\` +--- +24-25: +LGTM! + ` + + app.log.info('Analysis Context:', stringanalysisContext); + app.log.info(`Using Hugging Face API: ${API}`); + app.log.info(`Using LLM model: ${model}`); + app.log.info('Rules:', rules); + app.log.info('PR Data:', prData); + + + // Call the API with the analysis context + var response = await axios.post(API, { + model: model, + prompt + }); + + // const stringResp = await JSON.stringify(response.data, null, 2); + // app.log.info('API Response:',stringResp); + return response.data.response; + +} + + diff --git a/keploy-github-app-beta/package-lock.json b/keploy-github-app-beta/package-lock.json index 708ff82..de6da01 100644 --- a/keploy-github-app-beta/package-lock.json +++ b/keploy-github-app-beta/package-lock.json @@ -9,22 +9,620 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "axios": "^1.7.9", + "chalk": "^5.4.1", + "inquirer": "^12.4.2", + "parse-diff": "^0.11.1", "probot": "^13.0.1" }, "devDependencies": { - "nock": "^14.0.0-beta.5", - "smee-client": "^2.0.0" + "@types/node": "^22.13.5", + "eslint": "^9.21.0", + "nock": "^14.0.0- .5", + "smee-client": "^2.0.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.7.3" }, "engines": { "node": ">= 18" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", + "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.12.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.2.tgz", + "integrity": "sha512-PL9ixC5YsPXzXhAZFUPmkXGxfgjkdfZdPEPPmt4kFwQ4LBMDG9n/nHXYRGGZSKZJs+d1sGKWgS2GiPzVRKUdtQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/figures": "^1.0.10", + "@inquirer/type": "^3.0.4", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.6.tgz", + "integrity": "sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.7", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.7.tgz", + "integrity": "sha512-AA9CQhlrt6ZgiSy6qoAigiA1izOa751ugX6ioSjqgJ+/Gd+tEN/TORk5sUYNjXuHWfW0r1n/a6ak4u/NqHHrtA==", + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.10", + "@inquirer/type": "^3.0.4", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.7.tgz", + "integrity": "sha512-gktCSQtnSZHaBytkJKMKEuswSk2cDBuXX5rxGFv306mwHfBPjg5UAldw9zWGoEyvA9KpRDkeM4jfrx0rXn0GyA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.9.tgz", + "integrity": "sha512-Xxt6nhomWTAmuSX61kVgglLjMEFGa+7+F6UUtdEUeg7fg4r9vaFttUUKrtkViYYrQBA5Ia1tkOJj2koP9BuLig==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.10.tgz", + "integrity": "sha512-Ey6176gZmeqZuY/W/nZiUyvmb1/qInjcpiZjXWi6nON+nxJpD1bxtSoBxNliGISae32n6OwbY+TSXPZ1CfS4bw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.6.tgz", + "integrity": "sha512-1f5AIsZuVjPT4ecA8AwaxDFNHny/tSershP/cTvTDxLdiIGTeILNcKozB0LaYt6mojJLUbOYhpIxicaYf7UKIQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.9.tgz", + "integrity": "sha512-iN2xZvH3tyIYXLXBvlVh0npk1q/aVuKXZo5hj+K3W3D4ngAEq/DkLpofRzx6oebTUhBvOgryZ+rMV0yImKnG3w==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.9.tgz", + "integrity": "sha512-xBEoOw1XKb0rIN208YU7wM7oJEHhIYkfG7LpTJAEW913GZeaoQerzf5U/LSHI45EVvjAdgNXmXgH51cUXKZcJQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.3.2.tgz", + "integrity": "sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==", + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.1.2", + "@inquirer/confirm": "^5.1.6", + "@inquirer/editor": "^4.2.7", + "@inquirer/expand": "^4.0.9", + "@inquirer/input": "^4.1.6", + "@inquirer/number": "^3.0.9", + "@inquirer/password": "^4.0.9", + "@inquirer/rawlist": "^4.0.9", + "@inquirer/search": "^3.0.9", + "@inquirer/select": "^4.0.9" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.9.tgz", + "integrity": "sha512-+5t6ebehKqgoxV8fXwE49HkSF2Rc9ijNiVGEQZwvbMI61/Q5RcD+jWD6Gs1tKdz5lkI8GRBL31iO0HjGK1bv+A==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/type": "^3.0.4", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.9.tgz", + "integrity": "sha512-DWmKztkYo9CvldGBaRMr0ETUHgR86zE6sPDVOHsqz4ISe9o1LuiWfgJk+2r75acFclA93J/lqzhT0dTjCzHuoA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/figures": "^1.0.10", + "@inquirer/type": "^3.0.4", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.9.tgz", + "integrity": "sha512-BpJyJe7Dkhv2kz7yG7bPSbJLQuu/rqyNlF1CfiiFeFwouegfH+zh13KDyt6+d9DwucKo7hqM3wKLLyJxZMO+Xg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/figures": "^1.0.10", + "@inquirer/type": "^3.0.4", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.4.tgz", + "integrity": "sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/@ioredis/commands": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", "license": "MIT" }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@mswjs/interceptors": { "version": "0.37.6", "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.6.tgz", @@ -1281,6 +1879,34 @@ "@opentelemetry/semantic-conventions": "^1.28.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -1306,6 +1932,13 @@ "@types/node": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -1336,6 +1969,13 @@ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/jsonwebtoken": { "version": "9.0.8", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.8.tgz", @@ -1368,9 +2008,9 @@ } }, "node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", + "version": "22.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", + "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -1435,6 +2075,20 @@ "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", "license": "MIT" }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/tedious": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", @@ -1478,6 +2132,29 @@ "acorn": "^8" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1491,6 +2168,95 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1503,6 +2269,12 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -1512,12 +2284,43 @@ "node": ">=8.0.0" } }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "license": "Apache-2.0" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -1548,6 +2351,30 @@ "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", "license": "MIT" }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/btoa-lite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", @@ -1560,6 +2387,13 @@ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1582,20 +2416,73 @@ "node": ">= 0.4" } }, - "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/cjs-module-lexer": { @@ -1613,6 +2500,15 @@ "node": ">=6" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/cluster-key-slot": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", @@ -1622,12 +2518,42 @@ "node": ">=0.10.0" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", @@ -1637,6 +2563,13 @@ "node": ">=18" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1673,6 +2606,28 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", @@ -1691,6 +2646,13 @@ "ms": "2.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1700,143 +2662,490 @@ "node": ">=0.10.0" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "license": "ISC" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", + "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.2", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.21.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=0.10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "license": "ISC" - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/eslint/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", - "license": "BSD-2-Clause", + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://dotenvx.com" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "node_modules/eslint/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", "dependencies": { - "once": "^1.4.0" + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">=8" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=0.10" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "es-errors": "^1.3.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4.0" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/etag": { "version": "1.8.1", @@ -1903,12 +3212,47 @@ "url": "https://opencollective.com/express" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-copy": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", "license": "MIT" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-redact": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", @@ -1924,34 +3268,116 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "license": "MIT", "dependencies": { - "locate-path": "^3.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, "node_modules/forwarded": { @@ -1978,6 +3404,28 @@ "node": ">= 0.6" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2033,6 +3481,54 @@ "node": ">= 0.4" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -2051,6 +3547,16 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -2063,6 +3569,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2109,6 +3630,33 @@ "node": ">=0.10.0" } }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/import-in-the-middle": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.0.tgz", @@ -2121,6 +3669,16 @@ "module-details-from-path": "^1.0.3" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -2130,12 +3688,50 @@ "node": ">=8" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/inquirer": { + "version": "12.4.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.4.2.tgz", + "integrity": "sha512-reyjHcwyK2LObXgTJH4T1Dpfhwu88LNPTZmg/KenmTsy3T8lN/kZT8Oo7UwwkB9q8+ss2qjjN7GV8oFAfyz9Xg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.7", + "@inquirer/prompts": "^7.3.2", + "@inquirer/type": "^3.0.4", + "ansi-escapes": "^4.3.2", + "mute-stream": "^2.0.0", + "run-async": "^3.0.0", + "rxjs": "^7.8.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/ioredis": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.5.0.tgz", @@ -2198,6 +3794,19 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -2213,6 +3822,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-node-process": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", @@ -2220,6 +3861,23 @@ "dev": true, "license": "MIT" }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -2241,12 +3899,33 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "license": "MIT" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2303,6 +3982,30 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/load-json-file": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", @@ -2380,6 +4083,13 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -2396,6 +4106,13 @@ "node": "18 >=18.20 || 20 || >=22" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2465,6 +4182,19 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -2474,6 +4204,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", @@ -2486,6 +4229,22 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -2510,6 +4269,16 @@ "node": ">=18.20.0 <20 || >=20.12.1" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -2570,6 +4339,33 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -2613,6 +4409,25 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-diff": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.11.1.tgz", + "integrity": "sha512-Oq4j8LAOPOcssanQkIjxosjATBIEJhCxMCxPhMu+Ci4wdNmAEdx0O+a7gzbR2PyKXgKPvRLIN5g224+dJAsKHA==", + "license": "MIT" + }, "node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -2641,7 +4456,27 @@ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "license": "MIT", "engines": { - "node": ">=4" + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/path-parse": { @@ -2687,6 +4522,19 @@ "node": ">=4" } }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -2821,6 +4669,16 @@ "node": ">=0.10.0" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/probot": { "version": "13.4.3", "resolved": "https://registry.npmjs.org/probot/-/probot-13.4.3.tgz", @@ -2900,6 +4758,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -2910,6 +4774,16 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -2955,6 +4829,19 @@ "node": ">= 0.8" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -3042,6 +4929,48 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3155,6 +5084,29 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", @@ -3233,6 +5185,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/smee-client": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/smee-client/-/smee-client-2.0.4.tgz", @@ -3257,6 +5221,27 @@ "atomic-sleep": "^1.0.0" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -3288,6 +5273,32 @@ "dev": true, "license": "MIT" }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -3309,6 +5320,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3330,6 +5354,31 @@ "real-require": "^0.2.0" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -3339,6 +5388,137 @@ "node": ">=0.6" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tsconfig/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", @@ -3361,6 +5541,20 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", @@ -3401,6 +5595,16 @@ "dotenv": "*" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -3410,6 +5614,13 @@ "node": ">= 0.4.0" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", @@ -3429,6 +5640,46 @@ "node": ">= 0.8" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3443,6 +5694,41 @@ "engines": { "node": ">=0.4" } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/keploy-github-app-beta/package.json b/keploy-github-app-beta/package.json index 6b5a4b0..57542ea 100644 --- a/keploy-github-app-beta/package.json +++ b/keploy-github-app-beta/package.json @@ -12,15 +12,25 @@ "probot-app" ], "scripts": { - "start": "probot run ./index.js", - "test": "node --test" + "start": "tsc && probot run ./dist/index.js", + "test": "node --test dist/**/*.js", + "dev": "ts-node-dev --respawn --transpile-only ./index.ts" }, "dependencies": { + "axios": "^1.7.9", + "chalk": "^5.4.1", + "inquirer": "^12.4.2", + "parse-diff": "^0.11.1", "probot": "^13.0.1" }, "devDependencies": { - "nock": "^14.0.0-beta.5", - "smee-client": "^2.0.0" + "@types/node": "^22.13.5", + "eslint": "^9.21.0", + "nock": "^14.0.0- .5", + "smee-client": "^2.0.0", + "ts-node": "^10.9.2", + "ts-node-dev": "^2.0.0", + "typescript": "^5.7.3" }, "engines": { "node": ">= 18" diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts new file mode 100644 index 0000000..c465aaf --- /dev/null +++ b/keploy-github-app-beta/pr.ts @@ -0,0 +1,256 @@ +// Core data collection functions +export async function getAllPrDetails(context: any, app: any) { + const { pull_request: pr } = context.payload; + const { owner, repo } = context.repo(); + const filesResult = await getPrFilesAndDiffs(context, app, owner, repo, pr.number); + + // Extract issue number from PR body or title using regex + const issueNumber = extractIssueNumber(pr.body || pr.title); + const issueData = issueNumber ? await getLinkedIssueData(context, app, owner, repo, issueNumber) : null; + + // Get repository context + const repoContext = await getRepositoryContext(context, app); + + return { + metadata: getPrMetadata(pr), + comments: await getPrComments(context, app, owner, repo, pr.number), + files: filesResult, + relationships: { + requested_reviewers: pr.requested_reviewers?.map((u: { login: any }) => u.login) || [], + assignees: pr.assignees?.map((u: { login: any }) => u.login) || [], + labels: pr.labels?.map((l: { name: any }) => l.name) || [] + }, + code_changes: extractCodeChangesForLLM(app, filesResult), + linked_issue: issueData, + repository: repoContext + }; +} + +function extractIssueNumber(text: string): number | null { + // Look for patterns like "fixes #123", "closes #123", "related to #123" + const match = text?.match(/#(\d+)/); + return match ? parseInt(match[1]) : null; +} + +async function getLinkedIssueData(context: any, app: any, owner: string, repo: string, issueNumber: number) { + try { + const issue = await context.octokit.issues.get({ + owner, + repo, + issue_number: issueNumber + }); + + const comments = await context.octokit.paginate( + context.octokit.issues.listComments, + { owner, repo, issue_number: issueNumber } + ); + + return { + number: issueNumber, + title: issue.data.title, + body: issue.data.body, + state: issue.data.state, + author: issue.data.user.login, + created_at: issue.data.created_at, + updated_at: issue.data.updated_at, + labels: issue.data.labels.map((l: { name: any }) => l.name), + assignees: issue.data.assignees.map((a: { login: any }) => a.login), + comments: comments.map((c: any) => ({ + author: c.user.login, + body: c.body, + created_at: c.created_at + })) + }; + } catch (error) { + app.log.error('Error fetching linked issue data:', error); + return null; + } +} + +// Update extractCodeChangesForLLM to handle the files array directly +export function extractCodeChangesForLLM(app: any, files: any) { + app.log.info("Processing code changes for files"); + app.log.info(files); + + // Check if files is an array; if not, log error and return empty + if (!Array.isArray(files)) { + app.log.error('Invalid files data:', files); + return { + summary: { files_changed: 0, total_additions: 0, total_deletions: 0 }, + changes: [] + }; + } + + // const codeFileExtensions = ['.js', '.py', '.java', '.cpp', '.ts', '.go', '.rs', '.php', '.rb']; + + const codeChanges = files + // .filter((file: any) => { + // const ext = '.' + file.filename.split('.').pop().toLowerCase(); + // return codeFileExtensions.includes(ext); + // }) + .map((file: any) => { + const changes = parsePatch(file.patch); + return { + file: file.filename, + type: file.status, + changes: { + removed: changes.removed.join('\n'), + added: changes.added.join('\n') + }, + stats: { + additions: file.additions, + deletions: file.deletions + } + }; + }); + + return { + summary: { + files_changed: codeChanges.length, + total_additions: codeChanges.reduce((sum, file) => sum + file.stats.additions, 0), + total_deletions: codeChanges.reduce((sum, file) => sum + file.stats.deletions, 0) + }, + changes: codeChanges + }; +} + +// Ensure getPrFilesAndDiffs returns an empty array on error +export async function getPrFilesAndDiffs(context: any, app: any, owner: string, repo: string, prNumber: number) { + try { + const files = await context.octokit.paginate( + context.octokit.pulls.listFiles, + { owner, repo, pull_number: prNumber } + ); + return files.map((file: any) => ({ + filename: file.filename, + status: file.status, + additions: file.additions, + deletions: file.deletions, + changes: file.changes, + patch: file.patch || 'Diff too large to display' + })); + } catch (error) { + app.log.error('Error fetching files:', error); + return []; + } +} + + function getPrMetadata(pr : any) { + return { + title: pr.title, + body: pr.body, + author: pr.user.login, + state: pr.state, + draft: pr.draft, + created_at: pr.created_at, + updated_at: pr.updated_at, + mergeable: pr.mergeable, + additions: pr.additions, + deletions: pr.deletions, + changed_files: pr.changed_files, + base: { + branch: pr.base.ref, + sha: pr.base.sha + }, + head: { + branch: pr.head.ref, + sha: pr.head.sha + } + }; + } + + export async function getPrComments(context: { payload?: { pull_request: any; }; repo?: () => { owner: any; repo: any; }; octokit?: any; }, app: { log: any; on?: (arg0: string[], arg1: (context: any) => Promise) => void; }, owner: any, repo: any, prNumber: any) { + try { + const [issueComments, reviewComments] = await Promise.all([ + context.octokit.paginate(context.octokit.issues.listComments, { + owner, repo, issue_number: prNumber + }), + context.octokit.paginate(context.octokit.pulls.listReviewComments, { + owner, repo, pull_number: prNumber + }) + ]); + + return { + issue_comments: issueComments.map(formatComment), + review_comments: reviewComments.map(formatComment) + }; + } catch (error) { + app.log.error('Error fetching comments:', error); + return { error: 'Failed to fetch comments' }; + } + } + + function formatComment(comment : any) { + return { + id: comment.id, + user: comment.user?.login, + body: comment.body, + created_at: comment.created_at, + updated_at: comment.updated_at, + url: comment.html_url + }; +} + + + + function parsePatch(patch : any) { + if (!patch || patch === 'Diff too large to display') { + return { added: [], removed: [] }; + } + + const lines = patch.split('\n'); + const added: any[] = []; + const removed: any[] = []; + + lines.forEach((line: any) => { + if (line.startsWith('+') && !line.startsWith('+++')) { + added.push(line.substring(1)); + } else if (line.startsWith('-') && !line.startsWith('---')) { + removed.push(line.substring(1)); + } + }); + + return { added, removed }; + } + +async function getRepositoryContext(context: any, app: any) { + const { owner, repo } = context.repo(); + try { + // Fetch README content + const readmeResponse = await context.octokit.repos.getReadme({ + owner, + repo, + mediaType: { + format: 'raw', + }, + }); + + // Fetch repository structure using git trees + const repoStructure = await context.octokit.git.getTree({ + owner, + repo, + tree_sha: 'HEAD', + recursive: 'true' + }); + + const folderStructure = repoStructure.data.tree + .filter((item: any) => !item.path.includes('node_modules/')) // Exclude node_modules + .map((item: any) => item.path) + .join('\n'); + + return { + readme: readmeResponse.data, + structure: folderStructure, + name: repo, + owner: owner + }; + } catch (error) { + app.log.error('Error fetching repository context:', error); + return { + readme: 'Failed to fetch README', + structure: 'Failed to fetch structure', + name: repo, + owner: owner + }; + } +} \ No newline at end of file diff --git a/keploy-github-app-beta/rules.md b/keploy-github-app-beta/rules.md new file mode 100644 index 0000000..fc4c48c --- /dev/null +++ b/keploy-github-app-beta/rules.md @@ -0,0 +1,6 @@ +Does it have any Print statements? +Are the variables names camelcased? +Does it have error handling setup in for cases of failures +Is there any logging setup +Does the code ensure modularity of code within the file +Does the code have any appropriate comments for better understanding \ No newline at end of file diff --git a/keploy-github-app-beta/rules.ts b/keploy-github-app-beta/rules.ts new file mode 100644 index 0000000..e5dcfed --- /dev/null +++ b/keploy-github-app-beta/rules.ts @@ -0,0 +1,35 @@ +export async function getRulesForLLM(context: any) { + const { owner, repo } = context.repo(); + const { ref } = context.payload.pull_request.head; + + try { + const response = await context.octokit.repos.getContent({ + owner, + repo, + path: 'rules.md', + ref + }); + + const content = Buffer.from(response.data.content, 'base64').toString(); + + return { + success: true, + rules: content, + metadata: { + ref, + repo: `${owner}/${repo}`, + timestamp: new Date().toISOString() + } + }; + } catch (error: any) { + return { + success: false, + error: error.status === 404 ? 'Rules file not found' : 'Failed to fetch rules', + metadata: { + ref, + repo: `${owner}/${repo}`, + timestamp: new Date().toISOString() + } + }; + } + } \ No newline at end of file diff --git a/keploy-github-app-beta/security.ts b/keploy-github-app-beta/security.ts new file mode 100644 index 0000000..c21c887 --- /dev/null +++ b/keploy-github-app-beta/security.ts @@ -0,0 +1,27 @@ +export async function handleSecurityWorkflowTrigger(context: { repo: () => { owner: any; repo: any; }; payload: { pull_request: { head: { ref: any; }; number: any; }; }; octokit: { repos: { getContent: (arg0: { owner: any; repo: any; path: string; ref: any; }) => any; }; actions: { createWorkflowDispatch: (arg0: { owner: any; repo: any; workflow_id: string; ref: any; }) => any; }; issues: { createComment: (arg0: any) => any; }; }; }) { + const { owner, repo } = context.repo(); + const { ref } = context.payload.pull_request.head; + + try { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'Running security check' + }); + + await context.octokit.actions.createWorkflowDispatch({ + owner, repo, workflow_id: 'security.yaml', ref + }); + } catch (error : any) { + if (error.status === 404) { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'Failed to run security check' + }); + return; + } + throw error; + } + } + \ No newline at end of file diff --git a/keploy-github-app-beta/src/addLabel.ts b/keploy-github-app-beta/src/addLabel.ts new file mode 100644 index 0000000..8af8484 --- /dev/null +++ b/keploy-github-app-beta/src/addLabel.ts @@ -0,0 +1,63 @@ +interface LabelOptions { + name: string; + color: string; + description: string; +} + +export const LABEL_CONFIGS: Record = { + 'LGTM': { + name: 'LGTM', + color: '0e8a16', + description: 'Changes look good to merge' + }, + 'Needs Changes': { + name: 'Needs Changes', + color: 'd93f0b', + description: 'Changes requested by automated review' + }, + 'Spam': { + name: 'Spam', + color: 'b60205', + description: 'Potentially spam or irrelevant changes' + } +}; + +export async function determineLabelFromAnalysis(llmResponse: string): Promise { + const lowerResponse = llmResponse.toLowerCase(); + + if (lowerResponse.includes('lgtm!')) { + return 'LGTM'; + } else if (lowerResponse.includes('spam') || lowerResponse.length < 10) { + return 'Spam'; + } else { + return 'Needs Changes'; + } +} + +export async function addLabelToPR( + context: any, + prNumber: number, + labelName: string +) { + try { + // Remove existing review labels first + const existingLabels = Object.keys(LABEL_CONFIGS); + await context.octokit.issues.removeLabel({ + ...context.repo(), + issue_number: prNumber, + name: existingLabels + }).catch(() => {/* Ignore errors if labels don't exist */}); + + // Add new label + await context.octokit.issues.addLabels({ + ...context.repo(), + issue_number: prNumber, + labels: [labelName] + }); + + return true; + } catch (error) { + console.error('Error adding label:', error); + return false; + } +} diff --git a/keploy-github-app-beta/src/cli.ts b/keploy-github-app-beta/src/cli.ts new file mode 100644 index 0000000..3dcdf1a --- /dev/null +++ b/keploy-github-app-beta/src/cli.ts @@ -0,0 +1,70 @@ +import inquirer from 'inquirer'; +import { useCaseModels } from './config/models.js'; +import { ModelInfo, loadConfig, saveConfig, UserConfig } from './config/userConfig.js'; +import chalk from 'chalk'; // This will be fixed by package.json update + +export async function promptUserConfig(): Promise { + // Check for existing config + const existingConfig = loadConfig(); + if (existingConfig) { + console.log(chalk.cyan('Using existing configuration:')); + console.log(`Use Case: ${existingConfig.useCase}`); + console.log(`API Endpoint: ${existingConfig.apiEndpoint}`); + return existingConfig; + } + + // Get use case + const { useCase } = await inquirer.prompt([{ + type: 'list', + name: 'useCase', + message: 'Select your repository use case:', + choices: Object.entries(useCaseModels).map(([key, value]) => ({ + name: `${value.name} - ${value.description}`, + value: key + })) + }]); + + // Display suggested models with links + const selectedUseCase = useCaseModels[useCase]; + console.log(chalk.green('\nRecommended Open Source Models for your use case:')); + selectedUseCase.suggestedModels.forEach(model => { + console.log(chalk.yellow(`• ${model.name} `) + chalk.blue(`[${model.link}]`)); + }); + console.log(chalk.gray('\nNote: These are suggestions based on your use case.\n')); + + // After displaying suggested models, ask for model selection + const { selectedModel } = await inquirer.prompt<{ selectedModel: string }>([{ + type: 'input', + name: 'selectedModel', + message: 'Select a model to use:', + choices: selectedUseCase.suggestedModels.map(model => ({ + name: model.name, + value: model.name + })) + }]); + + // Get API endpoint + const { apiEndpoint } = await inquirer.prompt([{ + type: 'input', + name: 'apiEndpoint', + message: 'Please enter the API link:', + default: 'http://localhost:11434/api/generate', + validate: (input: string) => { + return input.startsWith('http://') || input.startsWith('https://') + ? true + : 'Please enter a valid HTTP/HTTPS URL'; + } + }]); + + const config: UserConfig = { + useCase, + apiEndpoint, + selectedModel, + }; + + // Save configuration + saveConfig(config); + console.log(chalk.green('Configuration saved successfully!')); + + return config; +} diff --git a/keploy-github-app-beta/src/config/models.ts b/keploy-github-app-beta/src/config/models.ts new file mode 100644 index 0000000..caa9adb --- /dev/null +++ b/keploy-github-app-beta/src/config/models.ts @@ -0,0 +1,75 @@ +export interface ModelConfig { + name: string; + description: string; + suggestedModels: Array<{ + name: string; + link: string; + }>; +} + +export const useCaseModels: Record = { + 'Documentation': { + name: 'Documentation Generation', + description: 'Generate and improve documentation', + suggestedModels: [ + { name: 'codellama', link: 'https://huggingface.co/codellama/CodeLlama-34b-hf' }, + { name: 'llama2', link: 'https://huggingface.co/meta-llama/Llama-2-70b-hf' }, + { name: 'mistral', link: 'https://huggingface.co/mistralai/Mistral-7B-v0.1' }, + { name: 'starcoder', link: 'https://huggingface.co/bigcode/starcoder' } + ] + }, + 'Code Review': { + name: 'Code Review & Quality', + description: 'Review code and suggest improvements', + suggestedModels: [ + { name: 'codellama', link: 'https://huggingface.co/codellama/CodeLlama-34b-hf' }, + { name: 'wizardcoder', link: 'https://huggingface.co/WizardLM/WizardCoder-Python-34B-V1.0' }, + { name: 'starcoder', link: 'https://huggingface.co/bigcode/starcoder' } + ] + }, + 'Security Analysis': { + name: 'Security Scanning', + description: 'Analyze code for security issues', + suggestedModels: [ + { name: 'llama2', link: 'https://huggingface.co/meta-llama/Llama-2-70b-hf' }, + { name: 'mistral', link: 'https://huggingface.co/mistralai/Mistral-7B-v0.1' }, + { name: 'vicuna', link: 'https://huggingface.co/lmsys/vicuna-13b-v1.5' } + ] + }, + 'Performance Optimization': { + name: 'Performance Analysis', + description: 'Identify performance bottlenecks', + suggestedModels: [ + { name: 'codellama', link: 'https://huggingface.co/codellama/CodeLlama-34b-hf' }, + { name: 'llama2', link: 'https://huggingface.co/meta-llama/Llama-2-70b-hf' }, + { name: 'wizardcoder', link: 'https://huggingface.co/WizardLM/WizardCoder-Python-34B-V1.0' } + ] + }, + 'Dependency Analysis': { + name: 'Dependency Management', + description: 'Analyze and suggest dependency updates', + suggestedModels: [ + { name: 'codellama', link: 'https://huggingface.co/codellama/CodeLlama-34b-hf' }, + { name: 'starcoder', link: 'https://huggingface.co/bigcode/starcoder' }, + { name: 'mistral', link: 'https://huggingface.co/mistralai/Mistral-7B-v0.1' } + ] + }, + 'Test Generation': { + name: 'Test Case Generation', + description: 'Generate test cases and scenarios', + suggestedModels: [ + { name: 'codellama', link: 'https://huggingface.co/codellama/CodeLlama-34b-hf' }, + { name: 'starcoder', link: 'https://huggingface.co/bigcode/starcoder' }, + { name: 'wizardcoder', link: 'https://huggingface.co/WizardLM/WizardCoder-Python-34B-V1.0' } + ] + }, + 'Architecture Review': { + name: 'Architecture Analysis', + description: 'Review system architecture and patterns', + suggestedModels: [ + { name: 'llama2', link: 'https://huggingface.co/meta-llama/Llama-2-70b-hf' }, + { name: 'mistral', link: 'https://huggingface.co/mistralai/Mistral-7B-v0.1' }, + { name: 'codellama', link: 'https://huggingface.co/codellama/CodeLlama-34b-hf' } + ] + } +}; diff --git a/keploy-github-app-beta/src/config/userConfig.ts b/keploy-github-app-beta/src/config/userConfig.ts new file mode 100644 index 0000000..9c57c01 --- /dev/null +++ b/keploy-github-app-beta/src/config/userConfig.ts @@ -0,0 +1,29 @@ +import fs from 'fs'; + +export interface ModelInfo { + name: string; + link: string; +} + +export interface UserConfig { + useCase: string; + apiEndpoint: string; + selectedModel: string; // Changed from ModelInfo to string +} + +const CONFIG_FILE = 'keploy-config.json'; + +export function saveConfig(config: UserConfig): void { + fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); +} + +export function loadConfig(): UserConfig | null { + try { + if (fs.existsSync(CONFIG_FILE)) { + return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); + } + } catch (error) { + console.error('Error loading config:', error); + } + return null; +} diff --git a/keploy-github-app-beta/test.ts b/keploy-github-app-beta/test.ts new file mode 100644 index 0000000..af72e0e --- /dev/null +++ b/keploy-github-app-beta/test.ts @@ -0,0 +1,3 @@ +console.log("This is a test PR and the following command prints hello world.") +// please do not comment the following line +// console.log("Hello World!") \ No newline at end of file diff --git a/keploy-github-app-beta/test/fixtures/mock-cert.pem b/keploy-github-app-beta/test/fixtures/mock-cert.pem deleted file mode 100644 index f2f271c..0000000 --- a/keploy-github-app-beta/test/fixtures/mock-cert.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAli7V49NdZe+XYC1pLaHM0te8kiDmZBJ1u2HJHN8GdbROB6NO -VpC3xK7NxQn6xpvZ9ux20NvcDvGle+DOptZztBH+np6h2jZQ1/kD1yG1eQvVH4th -/9oqHuIjmIfO8lIe4Hyd5Fw5xHkGqVETTGR+0c7kdZIlHmkOregUGtMYZRUi4YG+ -q0w+uFemiHpGKXbeCIAvkq7aIkisEzvPWfSyYdA6WJHpxFk7tD7D8VkzABLVRHCq -AuyqPG39BhGZcGLXx5rGK56kDBJkyTR1t3DkHpwX+JKNG5UYNwOG4LcQj1fteeta -TdkYUMjIyWbanlMYyC+dq7B5fe7el99jXQ1gXwIDAQABAoIBADKfiPOpzKLOtzzx -MbHzB0LO+75aHq7+1faayJrVxqyoYWELuB1P3NIMhknzyjdmU3t7S7WtVqkm5Twz -lBUC1q+NHUHEgRQ4GNokExpSP4SU63sdlaQTmv0cBxmkNarS6ZuMBgDy4XoLvaYX -MSUf/uukDLhg0ehFS3BteVFtdJyllhDdTenF1Nb1rAeN4egt8XLsE5NQDr1szFEG -xH5lb+8EDtzgsGpeIddWR64xP0lDIKSZWst/toYKWiwjaY9uZCfAhvYQ1RsO7L/t -sERmpYgh+rAZUh/Lr98EI8BPSPhzFcSHmtqzzejvC5zrZPHcUimz0CGA3YBiLoJX -V1OrxmECgYEAxkd8gpmVP+LEWB3lqpSvJaXcGkbzcDb9m0OPzHUAJDZtiIIf0UmO -nvL68/mzbCHSj+yFjZeG1rsrAVrOzrfDCuXjAv+JkEtEx0DIevU1u60lGnevOeky -r8Be7pmymFB9/gzQAd5ezIlTv/COgoO986a3h1yfhzrrzbqSiivw308CgYEAwecI -aZZwqH3GifR+0+Z1B48cezA5tC8LZt5yObGzUfxKTWy30d7lxe9N59t0KUVt/QL5 -qVkd7mqGzsUMyxUN2U2HVnFTWfUFMhkn/OnCnayhILs8UlCTD2Xxoy1KbQH/9FIr -xf0pbMNJLXeGfyRt/8H+BzSZKBw9opJBWE4gqfECgYBp9FdvvryHuBkt8UQCRJPX -rWsRy6pY47nf11mnazpZH5Cmqspv3zvMapF6AIxFk0leyYiQolFWvAv+HFV5F6+t -Si1mM8GCDwbA5zh6pEBDewHhw+UqMBh63HSeUhmi1RiOwrAA36CO8i+D2Pt+eQHv -ir52IiPJcs4BUNrv5Q1BdwKBgBHgVNw3LGe8QMOTMOYkRwHNZdjNl2RPOgPf2jQL -d/bFBayhq0jD/fcDmvEXQFxVtFAxKAc+2g2S8J67d/R5Gm/AQAvuIrsWZcY6n38n -pfOXaLt1x5fnKcevpFlg4Y2vM4O416RHNLx8PJDehh3Oo/2CSwMrDDuwbtZAGZok -icphAoGBAI74Tisfn+aeCZMrO8KxaWS5r2CD1KVzddEMRKlJvSKTY+dOCtJ+XKj1 -OsZdcDvDC5GtgcywHsYeOWHldgDWY1S8Z/PUo4eK9qBXYBXp3JEZQ1dqzFdz+Txi -rBn2WsFLsxV9j2/ugm0PqWVBcU2bPUCwvaRu3SOms2teaLwGCkhr ------END RSA PRIVATE KEY----- diff --git a/keploy-github-app-beta/test/fixtures/pull_request.opened.json b/keploy-github-app-beta/test/fixtures/pull_request.opened.json deleted file mode 100644 index 79e9fd9..0000000 --- a/keploy-github-app-beta/test/fixtures/pull_request.opened.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "action": "opened", - "pull_request": { - "head": { - "ref": "hiimbex-patch-1" - } - }, - "repository": { - "name": "testing-things", - "owner": { - "login": "hiimbex" - } - }, - "installation": { - "id": 2 - } -} diff --git a/keploy-github-app-beta/test/index.test.js b/keploy-github-app-beta/test/index.test.js deleted file mode 100644 index 9e7a25f..0000000 --- a/keploy-github-app-beta/test/index.test.js +++ /dev/null @@ -1,112 +0,0 @@ -import nock from "nock"; -// Requiring our app implementation -import myProbotApp from "../index.js"; -import { Probot, ProbotOctokit } from "probot"; -// Requiring our fixtures -//import payload from "./fixtures/pull_request.opened" with { type: "json" }; -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; -import { describe, beforeEach, afterEach, test } from "node:test"; -import assert from "node:assert"; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -const payload = JSON.parse( - fs.readFileSync( - path.join(__dirname, "fixtures/pull_request.opened.json"), - "utf-8", - ), -); - -const deployment = { - ref: "hiimbex-patch-1", - task: "deploy", - auto_merge: true, - required_contexts: [], - payload: { - schema: "rocks!", - }, - environment: "production", - description: "My Probot App's first deploy!", - transient_environment: false, - production_environment: true, -}; - -const deploymentStatus = { - state: "success", - log_url: "https://example.com", - description: "My Probot App set a deployment status!", - environment_url: "https://example.com", - auto_inactive: true, -}; - -const privateKey = fs.readFileSync( - path.join(__dirname, "fixtures/mock-cert.pem"), - "utf-8", -); - -describe("My Probot app", () => { - let probot; - - beforeEach(() => { - nock.disableNetConnect(); - probot = new Probot({ - appId: 123, - privateKey, - // disable request throttling and retries for testing - Octokit: ProbotOctokit.defaults({ - retry: { enabled: false }, - throttle: { enabled: false }, - }), - }); - // Load our app into probot - probot.load(myProbotApp); - }); - - test("creates a deployment and a deployment status", async () => { - const mock = nock("https://api.github.com") - // Test that we correctly return a test token - .post("/app/installations/2/access_tokens") - .reply(200, { - token: "test", - permissions: { - deployments: "write", - pull_requests: "read", - }, - }) - - // Test that a deployment is created - .post("/repos/hiimbex/testing-things/deployments", (body) => { - assert.deepStrictEqual(body, deployment); - return true; - }) - .reply(200, { id: 123 }) - - // Test that a deployment status is created - .post( - "/repos/hiimbex/testing-things/deployments/123/statuses", - (body) => { - assert.deepStrictEqual(body, deploymentStatus); - return true; - }, - ) - .reply(200); - - // Receive a webhook event - await probot.receive({ name: "pull_request", payload }); - - assert.deepStrictEqual(mock.pendingMocks(), []); - }); - - afterEach(() => { - nock.cleanAll(); - nock.enableNetConnect(); - }); -}); - -// For more information about testing with Jest see: -// https://facebook.github.io/jest/ - -// For more information about testing with Nock see: -// https://github.com/nock/nock diff --git a/keploy-github-app-beta/tsconfig.json b/keploy-github-app-beta/tsconfig.json new file mode 100644 index 0000000..4f7fda7 --- /dev/null +++ b/keploy-github-app-beta/tsconfig.json @@ -0,0 +1,111 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "NodeNext", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/keploy-github-app-beta/utils.ts b/keploy-github-app-beta/utils.ts new file mode 100644 index 0000000..e0c1808 --- /dev/null +++ b/keploy-github-app-beta/utils.ts @@ -0,0 +1,22 @@ +export function formatComment(comment : any) { + return { + id: comment.id, + user: comment.user?.login, + body: comment.body, + created_at: comment.created_at, + updated_at: comment.updated_at, + url: comment.html_url + }; + } + + // Error handler +export async function handleError(context: { octokit: { issues: { createComment: (arg0: any) => any; }; }; repo: () => any; payload: { pull_request: { number: any; }; }; }, app: { log: any; on?: (arg0: string[], arg1: (context: any) => Promise) => void; }, error: any) { + app.log.error('PR processing error:'); + app.log.error(error.message); + + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: '❌ Error processing PR: ' + error.message + }); + } From 0bd266384e561d4401e25412dd1499fdaffbea08 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 01:00:58 +0530 Subject: [PATCH 04/29] refactor: introduce type definitions and improve type safety across the application - Added a new `types.ts` file to define TypeScript interfaces for GitHub API related entities, application context, and configuration. - Updated function signatures in various files to use the new types, enhancing type safety and clarity. - Refactored existing functions to replace `any` types with specific interfaces, improving maintainability and reducing potential runtime errors. - Adjusted error handling and logging to provide clearer messages and context. This change aims to streamline the codebase and facilitate future development by leveraging TypeScript's type system. Signed-off-by: Sky Singh --- keploy-github-app-beta/index.ts | 19 ++- keploy-github-app-beta/keploy.ts | 40 +++-- keploy-github-app-beta/lint.ts | 40 +++-- keploy-github-app-beta/llm.ts | 51 +++--- keploy-github-app-beta/pr.ts | 204 ++++++++++++++--------- keploy-github-app-beta/rules.ts | 61 ++++--- keploy-github-app-beta/security.ts | 46 +++--- keploy-github-app-beta/src/addLabel.ts | 6 +- keploy-github-app-beta/types.ts | 217 +++++++++++++++++++++++++ keploy-github-app-beta/utils.ts | 51 ++++-- 10 files changed, 520 insertions(+), 215 deletions(-) create mode 100644 keploy-github-app-beta/types.ts diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts index 24c5d44..304091f 100644 --- a/keploy-github-app-beta/index.ts +++ b/keploy-github-app-beta/index.ts @@ -13,13 +13,11 @@ import { handleSecurityWorkflowTrigger } from "./security.js"; import { promptUserConfig } from './src/cli.js'; import { reviewPR } from './diffparser.js'; import { handleLintWorkflowTrigger } from "./lint.js"; +import { App, Config, GithubContext } from "./types.js"; -let config: any; +let config: Config; -export default async (app: { - log: { info: (arg0: string, arg1?: string) => void }; - on: (arg0: string[], arg1: (context: any) => Promise) => void; -}) => { +export default async (app: App) => { try { // Get user configuration through CLI config = await promptUserConfig(); @@ -27,12 +25,15 @@ export default async (app: { app.log.info(`Initialized with API url: ${config.apiEndpoint} for use case: ${config.useCase} and model : ${config.selectedModel}`); } catch (error) { app.log.info("Failed to get user configuration"); - process.exit(1); + // Using Node.js process API + if (typeof process !== 'undefined') { + process.exit(1); + } } app.log.info("Yay, the app was loaded!"); - const handlePrEvent = async (context: any) => { + const handlePrEvent = async (context: GithubContext) => { try { const prData = await getAllPrDetails(context, app); app.log.info(JSON.stringify(prData), "Full PR data collected"); @@ -51,5 +52,7 @@ export default async (app: { } }; - app.on(["pull_request.opened", "pull_request.synchronize"], handlePrEvent); + if (app.on) { + app.on(["pull_request.opened", "pull_request.synchronize"], handlePrEvent); + } }; diff --git a/keploy-github-app-beta/keploy.ts b/keploy-github-app-beta/keploy.ts index 0d2b513..da6fb99 100644 --- a/keploy-github-app-beta/keploy.ts +++ b/keploy-github-app-beta/keploy.ts @@ -1,21 +1,27 @@ -export async function handleKeployWorkflowTrigger(context: { repo: () => { owner: any; repo: any; }; payload: { pull_request: { head: { ref: any; }; number: any; }; }; octokit: { repos: { getContent: (arg0: { owner: any; repo: any; path: string; ref: any; }) => any; }; actions: { createWorkflowDispatch: (arg0: { owner: any; repo: any; workflow_id: string; ref: any; }) => any; }; issues: { createComment: (arg0: any) => any; }; }; }) { - const { owner, repo } = context.repo(); - const { ref } = context.payload.pull_request.head; - - try { - await context.octokit.actions.createWorkflowDispatch({ - owner, repo, workflow_id: 'keploy.yaml', ref +import { GithubContext } from './types.js'; + +export async function handleKeployWorkflowTrigger(context: GithubContext) { + const { owner, repo } = context.repo(); + const ref = context.payload.pull_request.head.ref; + + try { + await context.octokit.actions.createWorkflowDispatch({ + owner, + repo, + workflow_id: 'keploy.yaml', + ref + }); + } catch (error: unknown) { + const errorObj = error as { status?: number }; + if (errorObj.status === 404) { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: '⚠️ Failed to run Keploy Tests' }); - } catch (error : any) { - if (error.status === 404) { - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: '⚠️ Failed to run Keploy Tests' - }); - return; - } - throw error; + return; } + throw error; } +} \ No newline at end of file diff --git a/keploy-github-app-beta/lint.ts b/keploy-github-app-beta/lint.ts index 6bcc185..005637c 100644 --- a/keploy-github-app-beta/lint.ts +++ b/keploy-github-app-beta/lint.ts @@ -1,21 +1,27 @@ -export async function handleLintWorkflowTrigger(context: { repo: () => { owner: any; repo: any; }; payload: { pull_request: { head: { ref: any; }; number: any; }; }; octokit: { repos: { getContent: (arg0: { owner: any; repo: any; path: string; ref: any; }) => any; }; actions: { createWorkflowDispatch: (arg0: { owner: any; repo: any; workflow_id: string; ref: any; }) => any; }; issues: { createComment: (arg0: any) => any; }; }; }) { - const { owner, repo } = context.repo(); - const { ref } = context.payload.pull_request.head; - - try { - await context.octokit.actions.createWorkflowDispatch({ - owner, repo, workflow_id: 'lint.yaml', ref +import { GithubContext } from './types.js'; + +export async function handleLintWorkflowTrigger(context: GithubContext) { + const { owner, repo } = context.repo(); + const ref = context.payload.pull_request.head.ref; + + try { + await context.octokit.actions.createWorkflowDispatch({ + owner, + repo, + workflow_id: 'lint.yaml', + ref + }); + } catch (error: unknown) { + const errorObj = error as { status?: number }; + if (errorObj.status === 404) { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'Lint workflow failed' }); - } catch (error : any) { - if (error.status === 404) { - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: 'Lint workflow failed' - }); - return; - } - throw error; + return; } + throw error; } +} \ No newline at end of file diff --git a/keploy-github-app-beta/llm.ts b/keploy-github-app-beta/llm.ts index a24f93b..c5ca7ec 100644 --- a/keploy-github-app-beta/llm.ts +++ b/keploy-github-app-beta/llm.ts @@ -3,16 +3,15 @@ import { getRulesForLLM } from './rules.js'; import { loadConfig } from './src/config/userConfig.js'; import { useCaseModels } from './src/config/models.js'; import { determineLabelFromAnalysis, addLabelToPR } from './src/addLabel.js'; +import { App, GithubContext, PRData, IssueComment, Config } from './types.js'; // import { createInlineCommentsFromDiff } from './diffparser.js'; - export async function handlePrAnalysis( - context: { - octokit: { issues: { createComment: (arg0: any) => any; }; }; - repo: () => any; - payload: { pull_request: { number: any; }; }; - }, - prData: any, API : string, model: string , app: any + context: GithubContext, + prData: PRData, + API: string, + model: string, + app: App ) { // Load current configuration const config = loadConfig(); @@ -47,7 +46,7 @@ ${useCase?.suggestedModels.map(model => `- ${model.name}: ${model.link}`).join(' Assignees: ${prData.linked_issue.assignees.join(', ')} Issue Discussion: - ${prData.linked_issue.comments.map((c: any) => + ${prData.linked_issue.comments.map((c: IssueComment) => `${c.author} (${c.created_at}): ${c.body}` ).join('\n')} ` : 'No linked issue found'; @@ -83,7 +82,7 @@ ${useCase?.suggestedModels.map(model => `- ${model.name}: ${model.link}`).join(' // }); // call the LLM analysis function with selected model - const llmOutput = await analyzeLLM(prData, rules.rules , API , model, app); + const llmOutput = await analyzeLLM(prData, rules.rules, API, model, app); // Determine and add appropriate label const labelToAdd = await determineLabelFromAnalysis(llmOutput); @@ -92,8 +91,7 @@ ${useCase?.suggestedModels.map(model => `- ${model.name}: ${model.link}`).join(' return llmOutput; } -; -export async function analyzeLLM(prData: any, rules: any, API: string, model: string , app : any) { +export async function analyzeLLM(prData: PRData, rules: string, API: string, model: string, app: App) { const analysisContext = { repository: { name: prData.repository.name, @@ -244,19 +242,30 @@ LGTM! app.log.info(`Using Hugging Face API: ${API}`); app.log.info(`Using LLM model: ${model}`); app.log.info('Rules:', rules); - app.log.info('PR Data:', prData); + app.log.info('PR Data:', JSON.stringify(prData, null, 2)); // Call the API with the analysis context - var response = await axios.post(API, { - model: model, - prompt - }); - - // const stringResp = await JSON.stringify(response.data, null, 2); - // app.log.info('API Response:',stringResp); - return response.data.response; - + try { + const response = await axios.post(API, { + model: model, + prompt: prompt, + // max_tokens: 2000, + temperature: 0.7, + }, { + headers: { + 'Content-Type': 'application/json' + } + }); + + app.log.info('LLM API response:', response.data); + + // Assuming the response data contains a 'generated_text' field with the analysis + return response.data.generated_text || response.data; + } catch (error) { + app.log.error('Error calling LLM API:', error); + return `Error analyzing PR: ${error instanceof Error ? error.message : 'Unknown error'}`; + } } diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index c465aaf..adb957c 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -1,5 +1,17 @@ // Core data collection functions -export async function getAllPrDetails(context: any, app: any) { +import { + App, + GithubContext, + PullRequest, + PRData, + Comment, + FileChange, + CodeChanges, + LinkedIssue, + PatchResult +} from './types.js'; + +export async function getAllPrDetails(context: GithubContext, app: App): Promise { const { pull_request: pr } = context.payload; const { owner, repo } = context.repo(); const filesResult = await getPrFilesAndDiffs(context, app, owner, repo, pr.number); @@ -16,9 +28,9 @@ export async function getAllPrDetails(context: any, app: any) { comments: await getPrComments(context, app, owner, repo, pr.number), files: filesResult, relationships: { - requested_reviewers: pr.requested_reviewers?.map((u: { login: any }) => u.login) || [], - assignees: pr.assignees?.map((u: { login: any }) => u.login) || [], - labels: pr.labels?.map((l: { name: any }) => l.name) || [] + requested_reviewers: pr.requested_reviewers?.map((u) => u.login) || [], + assignees: pr.assignees?.map((u) => u.login) || [], + labels: pr.labels?.map((l) => l.name) || [] }, code_changes: extractCodeChangesForLLM(app, filesResult), linked_issue: issueData, @@ -32,7 +44,7 @@ function extractIssueNumber(text: string): number | null { return match ? parseInt(match[1]) : null; } -async function getLinkedIssueData(context: any, app: any, owner: string, repo: string, issueNumber: number) { +async function getLinkedIssueData(context: GithubContext, app: App, owner: string, repo: string, issueNumber: number): Promise { try { const issue = await context.octokit.issues.get({ owner, @@ -53,9 +65,9 @@ async function getLinkedIssueData(context: any, app: any, owner: string, repo: s author: issue.data.user.login, created_at: issue.data.created_at, updated_at: issue.data.updated_at, - labels: issue.data.labels.map((l: { name: any }) => l.name), - assignees: issue.data.assignees.map((a: { login: any }) => a.login), - comments: comments.map((c: any) => ({ + labels: issue.data.labels.map((l: { name: string }) => l.name), + assignees: issue.data.assignees.map((a: { login: string }) => a.login), + comments: comments.map((c: { user: { login: string }, body: string, created_at: string }) => ({ author: c.user.login, body: c.body, created_at: c.created_at @@ -68,9 +80,10 @@ async function getLinkedIssueData(context: any, app: any, owner: string, repo: s } // Update extractCodeChangesForLLM to handle the files array directly -export function extractCodeChangesForLLM(app: any, files: any) { +export function extractCodeChangesForLLM(app: App, files: FileChange[]): CodeChanges { app.log.info("Processing code changes for files"); - app.log.info(files); + // Using string interpolation to safely convert object to string for logging + app.log.info(`Files: ${files.length} items`); // Check if files is an array; if not, log error and return empty if (!Array.isArray(files)) { @@ -84,11 +97,11 @@ export function extractCodeChangesForLLM(app: any, files: any) { // const codeFileExtensions = ['.js', '.py', '.java', '.cpp', '.ts', '.go', '.rs', '.php', '.rb']; const codeChanges = files - // .filter((file: any) => { + // .filter((file) => { // const ext = '.' + file.filename.split('.').pop().toLowerCase(); // return codeFileExtensions.includes(ext); // }) - .map((file: any) => { + .map((file) => { const changes = parsePatch(file.patch); return { file: file.filename, @@ -115,13 +128,20 @@ export function extractCodeChangesForLLM(app: any, files: any) { } // Ensure getPrFilesAndDiffs returns an empty array on error -export async function getPrFilesAndDiffs(context: any, app: any, owner: string, repo: string, prNumber: number) { +export async function getPrFilesAndDiffs(context: GithubContext, app: App, owner: string, repo: string, prNumber: number): Promise { try { const files = await context.octokit.paginate( context.octokit.pulls.listFiles, { owner, repo, pull_number: prNumber } ); - return files.map((file: any) => ({ + return files.map((file: { + filename: string, + status: string, + additions: number, + deletions: number, + changes: number, + patch?: string + }) => ({ filename: file.filename, status: file.status, additions: file.additions, @@ -135,55 +155,81 @@ export async function getPrFilesAndDiffs(context: any, app: any, owner: string, } } - function getPrMetadata(pr : any) { +function getPrMetadata(pr: PullRequest) { + return { + title: pr.title, + body: pr.body, + author: pr.user.login, + state: pr.state, + draft: pr.draft, + created_at: pr.created_at, + updated_at: pr.updated_at, + mergeable: pr.mergeable, + additions: pr.additions, + deletions: pr.deletions, + changed_files: pr.changed_files, + base: { + branch: pr.base.ref, + sha: pr.base.sha + }, + head: { + branch: pr.head.ref, + sha: pr.head.sha + } + }; +} + +export async function getPrComments( + context: { + payload?: { pull_request: PullRequest }; + repo?: () => { owner: string; repo: string }; + octokit?: { + issues: { listComments: Function }; + pulls: { listReviewComments: Function }; + paginate: Function; + } + }, + app: App, + owner: string, + repo: string, + prNumber: number +) { + try { + if (!context.octokit) { + app.log.error('Octokit is undefined'); + return { issue_comments: [], review_comments: [] }; + } + + const [issueComments, reviewComments] = await Promise.all([ + context.octokit.paginate(context.octokit.issues.listComments, { + owner, repo, issue_number: prNumber + }), + context.octokit.paginate(context.octokit.pulls.listReviewComments, { + owner, repo, pull_number: prNumber + }) + ]); + return { - title: pr.title, - body: pr.body, - author: pr.user.login, - state: pr.state, - draft: pr.draft, - created_at: pr.created_at, - updated_at: pr.updated_at, - mergeable: pr.mergeable, - additions: pr.additions, - deletions: pr.deletions, - changed_files: pr.changed_files, - base: { - branch: pr.base.ref, - sha: pr.base.sha - }, - head: { - branch: pr.head.ref, - sha: pr.head.sha - } + issue_comments: issueComments.map(formatComment), + review_comments: reviewComments.map(formatComment) }; + } catch (error) { + app.log.error('Error fetching comments:', error); + return { issue_comments: [], review_comments: [] }; } - - export async function getPrComments(context: { payload?: { pull_request: any; }; repo?: () => { owner: any; repo: any; }; octokit?: any; }, app: { log: any; on?: (arg0: string[], arg1: (context: any) => Promise) => void; }, owner: any, repo: any, prNumber: any) { - try { - const [issueComments, reviewComments] = await Promise.all([ - context.octokit.paginate(context.octokit.issues.listComments, { - owner, repo, issue_number: prNumber - }), - context.octokit.paginate(context.octokit.pulls.listReviewComments, { - owner, repo, pull_number: prNumber - }) - ]); - - return { - issue_comments: issueComments.map(formatComment), - review_comments: reviewComments.map(formatComment) - }; - } catch (error) { - app.log.error('Error fetching comments:', error); - return { error: 'Failed to fetch comments' }; - } - } +} - function formatComment(comment : any) { +function formatComment(comment: { + id: number; + user?: { login: string }; + body: string; + created_at: string; + updated_at: string; + html_url: string; +}): Comment { return { id: comment.id, - user: comment.user?.login, + user: comment.user?.login || 'unknown', body: comment.body, created_at: comment.created_at, updated_at: comment.updated_at, @@ -191,29 +237,27 @@ export async function getPrFilesAndDiffs(context: any, app: any, owner: string, }; } +function parsePatch(patch: string | undefined): PatchResult { + if (!patch || patch === 'Diff too large to display') { + return { added: [], removed: [] }; + } + + const lines = patch.split('\n'); + const added: string[] = []; + const removed: string[] = []; - - function parsePatch(patch : any) { - if (!patch || patch === 'Diff too large to display') { - return { added: [], removed: [] }; + lines.forEach((line: string) => { + if (line.startsWith('+') && !line.startsWith('+++')) { + added.push(line.substring(1)); + } else if (line.startsWith('-') && !line.startsWith('---')) { + removed.push(line.substring(1)); } - - const lines = patch.split('\n'); - const added: any[] = []; - const removed: any[] = []; - - lines.forEach((line: any) => { - if (line.startsWith('+') && !line.startsWith('+++')) { - added.push(line.substring(1)); - } else if (line.startsWith('-') && !line.startsWith('---')) { - removed.push(line.substring(1)); - } - }); - - return { added, removed }; - } + }); + + return { added, removed }; +} -async function getRepositoryContext(context: any, app: any) { +async function getRepositoryContext(context: GithubContext, app: App) { const { owner, repo } = context.repo(); try { // Fetch README content @@ -234,8 +278,8 @@ async function getRepositoryContext(context: any, app: any) { }); const folderStructure = repoStructure.data.tree - .filter((item: any) => !item.path.includes('node_modules/')) // Exclude node_modules - .map((item: any) => item.path) + .filter((item: { path: string }) => !item.path.includes('node_modules/')) // Exclude node_modules + .map((item: { path: string }) => item.path) .join('\n'); return { @@ -248,7 +292,7 @@ async function getRepositoryContext(context: any, app: any) { app.log.error('Error fetching repository context:', error); return { readme: 'Failed to fetch README', - structure: 'Failed to fetch structure', + structure: 'Failed to fetch repository structure', name: repo, owner: owner }; diff --git a/keploy-github-app-beta/rules.ts b/keploy-github-app-beta/rules.ts index e5dcfed..06b74e5 100644 --- a/keploy-github-app-beta/rules.ts +++ b/keploy-github-app-beta/rules.ts @@ -1,35 +1,32 @@ -export async function getRulesForLLM(context: any) { +import { GithubContext, Rules } from './types.js'; + +export async function getRulesForLLM(context: GithubContext): Promise { + try { const { owner, repo } = context.repo(); - const { ref } = context.payload.pull_request.head; - - try { - const response = await context.octokit.repos.getContent({ - owner, - repo, - path: 'rules.md', - ref - }); - + const response = await context.octokit.repos.getContent({ + owner, + repo, + path: 'rules.md', + ref: context.payload.pull_request?.head?.ref + }); + + // Check if the response is valid and contains content + if (response.data && 'content' in response.data) { const content = Buffer.from(response.data.content, 'base64').toString(); - - return { - success: true, - rules: content, - metadata: { - ref, - repo: `${owner}/${repo}`, - timestamp: new Date().toISOString() - } - }; - } catch (error: any) { - return { - success: false, - error: error.status === 404 ? 'Rules file not found' : 'Failed to fetch rules', - metadata: { - ref, - repo: `${owner}/${repo}`, - timestamp: new Date().toISOString() - } - }; + return { success: true, rules: content }; } - } \ No newline at end of file + + return { + success: false, + rules: '', + error: 'Failed to load rules.md - unexpected response format' + }; + } catch (error: unknown) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + return { + success: false, + rules: 'No specific rules found. Please follow general good practices.', + error: `Error loading rules.md: ${errorMessage}` + }; + } +} \ No newline at end of file diff --git a/keploy-github-app-beta/security.ts b/keploy-github-app-beta/security.ts index c21c887..91b1274 100644 --- a/keploy-github-app-beta/security.ts +++ b/keploy-github-app-beta/security.ts @@ -1,27 +1,33 @@ -export async function handleSecurityWorkflowTrigger(context: { repo: () => { owner: any; repo: any; }; payload: { pull_request: { head: { ref: any; }; number: any; }; }; octokit: { repos: { getContent: (arg0: { owner: any; repo: any; path: string; ref: any; }) => any; }; actions: { createWorkflowDispatch: (arg0: { owner: any; repo: any; workflow_id: string; ref: any; }) => any; }; issues: { createComment: (arg0: any) => any; }; }; }) { - const { owner, repo } = context.repo(); - const { ref } = context.payload.pull_request.head; - - try { +import { GithubContext } from './types.js'; + +export async function handleSecurityWorkflowTrigger(context: GithubContext) { + const { owner, repo } = context.repo(); + const ref = context.payload.pull_request.head.ref; + + try { + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'Running security check' + }); + + await context.octokit.actions.createWorkflowDispatch({ + owner, + repo, + workflow_id: 'security.yaml', + ref + }); + } catch (error: unknown) { + const errorObj = error as { status?: number }; + if (errorObj.status === 404) { await context.octokit.issues.createComment({ ...context.repo(), issue_number: context.payload.pull_request.number, - body: 'Running security check' + body: 'Failed to run security check' }); - - await context.octokit.actions.createWorkflowDispatch({ - owner, repo, workflow_id: 'security.yaml', ref - }); - } catch (error : any) { - if (error.status === 404) { - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: 'Failed to run security check' - }); - return; - } - throw error; + return; } + throw error; } +} \ No newline at end of file diff --git a/keploy-github-app-beta/src/addLabel.ts b/keploy-github-app-beta/src/addLabel.ts index 8af8484..4144c86 100644 --- a/keploy-github-app-beta/src/addLabel.ts +++ b/keploy-github-app-beta/src/addLabel.ts @@ -1,3 +1,5 @@ +import { GithubContext } from '../types.js'; + interface LabelOptions { name: string; color: string; @@ -35,10 +37,10 @@ export async function determineLabelFromAnalysis(llmResponse: string): Promise { try { // Remove existing review labels first const existingLabels = Object.keys(LABEL_CONFIGS); diff --git a/keploy-github-app-beta/types.ts b/keploy-github-app-beta/types.ts new file mode 100644 index 0000000..d414743 --- /dev/null +++ b/keploy-github-app-beta/types.ts @@ -0,0 +1,217 @@ +// GitHub API related types +export interface Repository { + name: string; + owner: string; + readme: string; + structure: string; +} + +export interface User { + login: string; +} + +export interface Label { + name: string; +} + +export interface Comment { + id: number; + user: string; + body: string; + created_at: string; + updated_at: string; + url: string; +} + +export interface IssueComment { + author: string; + body: string; + created_at: string; +} + +export interface PullRequest { + title: string; + body: string | null; + user: User; + state: string; + draft: boolean; + created_at: string; + updated_at: string; + mergeable: boolean; + additions: number; + deletions: number; + changed_files: number; + number: number; + requested_reviewers?: User[]; + assignees?: User[]; + labels?: Label[]; + base: { + ref: string; + sha: string; + }; + head: { + ref: string; + sha: string; + }; +} + +export interface PRMetadata { + title: string; + body: string | null; + author: string; + state: string; + draft: boolean; + created_at: string; + updated_at: string; + mergeable: boolean; + additions: number; + deletions: number; + changed_files: number; + base: { + branch: string; + sha: string; + }; + head: { + branch: string; + sha: string; + }; +} + +export interface PRComments { + issue_comments: Comment[]; + review_comments: Comment[]; +} + +export interface FileChange { + filename: string; + status: string; + additions: number; + deletions: number; + changes: number; + patch: string; +} + +export interface CodeChange { + file: string; + type: string; + changes: { + removed: string; + added: string; + }; + stats: { + additions: number; + deletions: number; + }; +} + +export interface CodeChanges { + summary: { + files_changed: number; + total_additions: number; + total_deletions: number; + }; + changes: CodeChange[]; +} + +export interface LinkedIssue { + number: number; + title: string; + body: string | null; + state: string; + author: string; + created_at: string; + updated_at: string; + labels: string[]; + assignees: string[]; + comments: IssueComment[]; +} + +export interface PRData { + metadata: PRMetadata; + comments: PRComments; + files: FileChange[]; + relationships: { + requested_reviewers: string[]; + assignees: string[]; + labels: string[]; + }; + code_changes: CodeChanges; + linked_issue: LinkedIssue | null; + repository: Repository; +} + +// GitHub context types +export interface GithubContext { + octokit: { + issues: { + createComment: (params: any) => Promise; + get: (params: any) => Promise; + listComments: Function; + removeLabel: (params: any) => Promise; + addLabels: (params: any) => Promise; + }; + pulls: { + listFiles: Function; + listReviewComments: Function; + }; + repos: { + getReadme: (params: any) => Promise; + getContent: (params: any) => Promise; + }; + actions: { + createWorkflowDispatch: (params: any) => Promise; + }; + git: { + getTree: (params: any) => Promise; + }; + paginate: Function; + }; + repo: () => { owner: string; repo: string }; + payload: { + pull_request: PullRequest; + }; +} + +// App types +export interface App { + log: { + info: (message: string, context?: any) => void; + error: (message: string, error?: any) => void; + }; + on?: (events: string[], callback: (context: GithubContext) => Promise) => void; +} + +// Rule types +export interface Rules { + success: boolean; + rules: string; + error?: string; +} + +// Patch parsing result +export interface PatchResult { + added: string[]; + removed: string[]; +} + +// Configuration types +export interface Config { + useCase: string; + apiEndpoint: string; + selectedModel: string; +} + +// Model related types +export interface Model { + name: string; + link: string; +} + +export interface UseCase { + name: string; + suggestedModels: Model[]; +} + +export interface UseCaseModels { + [key: string]: UseCase; +} \ No newline at end of file diff --git a/keploy-github-app-beta/utils.ts b/keploy-github-app-beta/utils.ts index e0c1808..3590027 100644 --- a/keploy-github-app-beta/utils.ts +++ b/keploy-github-app-beta/utils.ts @@ -1,22 +1,37 @@ -export function formatComment(comment : any) { - return { - id: comment.id, - user: comment.user?.login, - body: comment.body, - created_at: comment.created_at, - updated_at: comment.updated_at, - url: comment.html_url - }; - } +import { App, GithubContext, Comment } from './types.js'; - // Error handler -export async function handleError(context: { octokit: { issues: { createComment: (arg0: any) => any; }; }; repo: () => any; payload: { pull_request: { number: any; }; }; }, app: { log: any; on?: (arg0: string[], arg1: (context: any) => Promise) => void; }, error: any) { - app.log.error('PR processing error:'); - app.log.error(error.message); - - await context.octokit.issues.createComment({ +export function formatComment(comment: Comment): string { + return ` +Comment by ${comment.user} (${comment.created_at}): +${comment.body} +--- +`; +} + +// Error handler +export async function handleError( + context: GithubContext, + app: App, + error: Error | unknown +): Promise { + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + + app.log.error('Error processing PR:', error); + + try { + const commentParams = { ...context.repo(), issue_number: context.payload.pull_request.number, - body: '❌ Error processing PR: ' + error.message - }); + body: `## Error Processing PR +An error occurred while analyzing this PR: +\`\`\` +${errorMessage} +\`\`\` +Please check the application logs for more details.` + }; + + await context.octokit.issues.createComment(commentParams); + } catch (commentError) { + app.log.error('Failed to post error comment:', commentError); } +} From 0d8de5c750de9d82719ba8dc626617380184e999 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 01:23:35 +0530 Subject: [PATCH 05/29] refactor: enhance type definitions and improve function signatures in diffparser.ts and types.ts - Introduced specific TypeScript interfaces for GitHub context and application parameters in `diffparser.ts`, improving type safety. - Updated function signatures to replace `any` with defined types, enhancing clarity and maintainability. - Improved error handling in `createInlineCommentsFromDiff` to provide more informative logging. - Expanded `types.ts` with additional GitHub API parameter and response types, ensuring better integration with the GitHub API. These changes aim to streamline the codebase and leverage TypeScript's capabilities for better development practices. Signed-off-by: Sky Singh --- keploy-github-app-beta/diffparser.ts | 90 ++++++++++++-- keploy-github-app-beta/types.ts | 180 ++++++++++++++++++++++++--- 2 files changed, 244 insertions(+), 26 deletions(-) diff --git a/keploy-github-app-beta/diffparser.ts b/keploy-github-app-beta/diffparser.ts index 3cf99a5..dc79bae 100644 --- a/keploy-github-app-beta/diffparser.ts +++ b/keploy-github-app-beta/diffparser.ts @@ -1,16 +1,74 @@ // diffParser.ts -import parseDiff from 'parse-diff'; +import parseDiff, { File, Chunk, Change } from 'parse-diff'; +// Define interfaces for GitHub context and app +interface Repository { + owner: { + login: string; + }; + name: string; +} + +interface PullRequest { + number: number; + head: { + sha: string; + }; +} + +interface GitHubPayload { + pull_request: PullRequest; + repository: Repository; +} + +interface IssueCommentParams { + owner: string; + repo: string; + issue_number: number; + body: string; +} + +interface ReviewCommentParams { + owner: string; + repo: string; + pull_number: number; + commit_id: string; + path: string; + body: string; + line: number; + mediaType?: { + previews: string[]; + }; +} + +interface GitHubContext { + octokit: { + issues: { + createComment: (params: IssueCommentParams) => Promise; + }; + pulls: { + createReviewComment: (params: ReviewCommentParams) => Promise; + }; + }; + repo: () => { owner: string; repo: string }; + payload: GitHubPayload; +} + +interface ProbotyApp { + log: { + info: (message: string) => void; + error: (message: string) => void; + }; +} -async function parseGitDiffFromLLMOutput(llmOutput: any) { +async function parseGitDiffFromLLMOutput(llmOutput: string): Promise { const diffStart = llmOutput.indexOf('```diff'); const diffEnd = llmOutput.indexOf('```', diffStart + 1); return llmOutput.substring(diffStart, diffEnd); } -export async function reviewPR(context: any, app: any, llmOutput: any) { -// export async function reviewPR(context: any, app: any) { +export async function reviewPR(context: GitHubContext, app: ProbotyApp, llmOutput: string): Promise { //trim the llmOutput to only include the diff const ifLGTM = llmOutput.includes('LGTM'); if (ifLGTM) { @@ -69,17 +127,19 @@ export async function reviewPR(context: any, app: any, llmOutput: any) { } -export async function createInlineCommentsFromDiff(diff: string, context: any, app: any) { - const parsedFiles = parseDiff(diff); +export async function createInlineCommentsFromDiff(diff: string, context: GitHubContext, app: ProbotyApp): Promise { + const parsedFiles: File[] = parseDiff(diff); const { pull_request, repository } = context.payload; for (const file of parsedFiles) { if (file.to === '/dev/null') { - app.log.info(`Skipping deleted file: ${file.from}`); + // Handle potential undefined value + const filePath = file.from || ''; + app.log.info(`Skipping deleted file: ${filePath}`); continue; } - const filePath = file.to || file.from; + const filePath = file.to || file.from || ''; for (const chunk of file.chunks) { for (const change of chunk.changes) { @@ -103,10 +163,16 @@ export async function createInlineCommentsFromDiff(diff: string, context: any, a }, }); app.log.info(`Created comment on ${filePath} line ${line}`); - } catch (error: any) { - app.log.error( - `Failed to create comment for ${filePath} line ${line}: ${error.message}` - ); + } catch (error) { + if (error instanceof Error) { + app.log.error( + `Failed to create comment for ${filePath} line ${line}: ${error.message}` + ); + } else { + app.log.error( + `Failed to create comment for ${filePath} line ${line}: Unknown error` + ); + } } } } diff --git a/keploy-github-app-beta/types.ts b/keploy-github-app-beta/types.ts index d414743..2f1345d 100644 --- a/keploy-github-app-beta/types.ts +++ b/keploy-github-app-beta/types.ts @@ -140,31 +140,183 @@ export interface PRData { repository: Repository; } +// GitHub API parameter and response types +export interface CreateCommentParams { + owner: string; + repo: string; + issue_number: number; + body: string; +} + +export interface CommentResponse { + id: number; + node_id: string; + url: string; + html_url: string; + body: string; + user: User; + created_at: string; + updated_at: string; +} + +export interface GetIssueParams { + owner: string; + repo: string; + issue_number: number; +} + +export interface IssueResponse { + id: number; + node_id: string; + number: number; + title: string; + user: User; + labels: Label[]; + state: string; + locked: boolean; + assignees: User[]; + body: string; + created_at: string; + updated_at: string; + closed_at: string | null; + url: string; + html_url: string; + comments: number; +} + +export interface ListCommentsParams { + owner: string; + repo: string; + issue_number: number; + per_page?: number; + page?: number; +} + +export interface RemoveLabelParams { + owner: string; + repo: string; + issue_number: number; + name: string; +} + +export interface AddLabelsParams { + owner: string; + repo: string; + issue_number: number; + labels: string[]; +} + +export interface GetReadmeParams { + owner: string; + repo: string; + ref?: string; +} + +export interface ReadmeResponse { + type: string; + encoding: string; + size: number; + name: string; + path: string; + content: string; + sha: string; + url: string; + git_url: string; + html_url: string; + download_url: string; +} + +export interface GetContentParams { + owner: string; + repo: string; + path: string; + ref?: string; +} + +export interface ContentResponse { + type: string; + encoding: string; + size: number; + name: string; + path: string; + content: string; + sha: string; + url: string; + git_url: string; + html_url: string; + download_url: string; +} + +export interface CreateWorkflowDispatchParams { + owner: string; + repo: string; + workflow_id: string; + ref: string; + inputs?: Record; +} + +export interface GetTreeParams { + owner: string; + repo: string; + tree_sha: string; + recursive?: boolean; +} + +export interface TreeResponse { + sha: string; + url: string; + tree: Array<{ + path: string; + mode: string; + type: string; + sha: string; + size?: number; + url: string; + }>; + truncated: boolean; +} + +export interface ListFilesParams { + owner: string; + repo: string; + pull_number: number; + per_page?: number; + page?: number; +} + +export interface ListReviewCommentsParams { + owner: string; + repo: string; + pull_number: number; + per_page?: number; + page?: number; +} + // GitHub context types export interface GithubContext { octokit: { issues: { - createComment: (params: any) => Promise; - get: (params: any) => Promise; - listComments: Function; - removeLabel: (params: any) => Promise; - addLabels: (params: any) => Promise; + createComment: (params: CreateCommentParams) => Promise<{ data: CommentResponse }>; + get: (params: GetIssueParams) => Promise<{ data: IssueResponse }>; + listComments: (params: ListCommentsParams) => Promise<{ data: CommentResponse[] }>; + removeLabel: (params: RemoveLabelParams) => Promise; + addLabels: (params: AddLabelsParams) => Promise<{ data: Label[] }>; }; pulls: { - listFiles: Function; - listReviewComments: Function; + listFiles: (params: ListFilesParams) => Promise<{ data: FileChange[] }>; + listReviewComments: (params: ListReviewCommentsParams) => Promise<{ data: Comment[] }>; }; repos: { - getReadme: (params: any) => Promise; - getContent: (params: any) => Promise; + getReadme: (params: GetReadmeParams) => Promise<{ data: ReadmeResponse }>; + getContent: (params: GetContentParams) => Promise<{ data: ContentResponse }>; }; actions: { - createWorkflowDispatch: (params: any) => Promise; + createWorkflowDispatch: (params: CreateWorkflowDispatchParams) => Promise; }; git: { - getTree: (params: any) => Promise; + getTree: (params: GetTreeParams) => Promise<{ data: TreeResponse }>; }; - paginate: Function; + paginate: (method: Function, params: object) => Promise; }; repo: () => { owner: string; repo: string }; payload: { @@ -175,8 +327,8 @@ export interface GithubContext { // App types export interface App { log: { - info: (message: string, context?: any) => void; - error: (message: string, error?: any) => void; + info: (message: string, context?: Record) => void; + error: (message: string, error?: Error | unknown) => void; }; on?: (events: string[], callback: (context: GithubContext) => Promise) => void; } From 06742565f0721c837d48aa12b1bc1f7a4cc3be1c Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 01:27:44 +0530 Subject: [PATCH 06/29] refactor: enhance diff parsing and error handling in diffparser.ts - Implemented regex for improved extraction of diff blocks from LLM output, ensuring more accurate parsing. - Updated the logic to handle cases where no valid diff is found, providing clearer error messages and logging. - Refined the LGTM detection to use regex for exact matching, reducing false positives. These changes aim to improve the robustness and reliability of the diff parsing functionality. Signed-off-by: Sky Singh --- keploy-github-app-beta/diffparser.ts | 76 +++++++++++++--------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/keploy-github-app-beta/diffparser.ts b/keploy-github-app-beta/diffparser.ts index dc79bae..17d87e2 100644 --- a/keploy-github-app-beta/diffparser.ts +++ b/keploy-github-app-beta/diffparser.ts @@ -1,7 +1,6 @@ // diffParser.ts import parseDiff, { File, Chunk, Change } from 'parse-diff'; -// Define interfaces for GitHub context and app interface Repository { owner: { login: string; @@ -62,15 +61,34 @@ interface ProbotyApp { } async function parseGitDiffFromLLMOutput(llmOutput: string): Promise { + // Use regex to find the diff block with exact matching + const diffRegex = /```diff([\s\S]*?)```/; + const match = diffRegex.exec(llmOutput); + + if (match && match[1]) { + // Return the content including the diff markers + return '```diff' + match[1] + '```'; + } + + // Fallback to the original method if regex doesn't match const diffStart = llmOutput.indexOf('```diff'); - const diffEnd = llmOutput.indexOf('```', diffStart + 1); - return llmOutput.substring(diffStart, diffEnd); + if (diffStart !== -1) { + const diffEnd = llmOutput.indexOf('```', diffStart + 7); + if (diffEnd !== -1) { + return llmOutput.substring(diffStart, diffEnd + 3); + } + } + + // Return empty string if no diff is found + return ''; } export async function reviewPR(context: GitHubContext, app: ProbotyApp, llmOutput: string): Promise { - //trim the llmOutput to only include the diff - const ifLGTM = llmOutput.includes('LGTM'); + // Use regex for exact LGTM matching to avoid false positives + const lgtmRegex = /\bLGTM\b/; + const ifLGTM = lgtmRegex.test(llmOutput); + if (ifLGTM) { await context.octokit.issues.createComment({ ...context.repo(), @@ -79,42 +97,20 @@ export async function reviewPR(context: GitHubContext, app: ProbotyApp, llmOutpu }); return; } + const gitDiff = await parseGitDiffFromLLMOutput(llmOutput); -// const gitDiff = `diff --git a/src/index.js b/src/index.js -// index abc1234..def5678 100644 -// --- a/src/index.js -// +++ b/src/index.js -// @@ -1,5 +1,5 @@ -// function add(a, b) { -// - return a - b; // Bug: Subtraction instead of addition -// + return a + b; // Fixed: Now correctly adds -// } - -// function subtract(a, b) { -// @@ -10,7 +10,7 @@ function subtract(a, b) { -// function multiply(a, b) { -// return a * b; -// } - -// -function divide(a, b) { -// - return a / b; -// +function divide(a, b) { -// + return b !== 0 ? a / b : NaN; // Added check for division by zero -// } -// diff --git a/tests/test.js b/tests/test.js -// index 1234567..890abcd 100644 -// --- a/tests/test.js -// +++ b/tests/test.js -// @@ -5,6 +5,6 @@ describe('Math operations', () => { -// expect(add(2, 3)).toBe(5); -// }); - -// - test('subtract should return the difference', () => { -// + test('subtract should return the correct difference', () => { -// expect(subtract(5, 3)).toBe(2); -// }); -// }); -// `; + + // Only proceed if we have a valid diff + if (!gitDiff) { + app.log.error('No valid diff found in LLM output'); + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: 'Error: Could not parse diff from LLM output', + }); + return; + } + // Create inline comments from the diff await createInlineCommentsFromDiff(gitDiff, context, app); From 80400063f92e982ce3c3d9627f0f00a4a5d081c4 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 01:50:15 +0530 Subject: [PATCH 07/29] refactor: enhance type safety and logging in various modules - Added new methods to the GitHub context interface for listing files and review comments, improving API integration. - Updated logging statements to use structured data for better clarity and debugging. - Refactored code in `pr.ts` to improve type handling and error management, ensuring more robust data processing. - Adjusted label removal logic in `addLabel.ts` to handle labels individually, enhancing reliability. These changes aim to improve maintainability and enhance the overall robustness of the application. Signed-off-by: Sky Singh --- keploy-github-app-beta/diffparser.ts | 2 + keploy-github-app-beta/index.ts | 4 +- keploy-github-app-beta/llm.ts | 6 +- keploy-github-app-beta/pr.ts | 78 ++++++++++++++++---------- keploy-github-app-beta/src/addLabel.ts | 14 +++-- 5 files changed, 63 insertions(+), 41 deletions(-) diff --git a/keploy-github-app-beta/diffparser.ts b/keploy-github-app-beta/diffparser.ts index 17d87e2..36bf0e3 100644 --- a/keploy-github-app-beta/diffparser.ts +++ b/keploy-github-app-beta/diffparser.ts @@ -47,6 +47,8 @@ interface GitHubContext { }; pulls: { createReviewComment: (params: ReviewCommentParams) => Promise; + listFiles: (params: { owner: string; repo: string; pull_number: number }) => Promise<{ data: any[] }>; + listReviewComments: (params: { owner: string; repo: string; pull_number: number }) => Promise<{ data: any[] }>; }; }; repo: () => { owner: string; repo: string }; diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts index 304091f..ea11884 100644 --- a/keploy-github-app-beta/index.ts +++ b/keploy-github-app-beta/index.ts @@ -36,12 +36,12 @@ export default async (app: App) => { const handlePrEvent = async (context: GithubContext) => { try { const prData = await getAllPrDetails(context, app); - app.log.info(JSON.stringify(prData), "Full PR data collected"); + app.log.info("Full PR data collected", { prData: JSON.stringify(prData) }); const llmOutput = await handlePrAnalysis(context, prData , config.apiEndpoint , config.selectedModel, app); // const stringllmOutput = await JSON.stringify(llmOutput); // app.log.info(JSON.stringify(stringllmOutput), "LLM analysis complete"); - await reviewPR(context, app, llmOutput); + await reviewPR(context as any, app, llmOutput); // await reviewPR(context, app); await handleKeployWorkflowTrigger(context); diff --git a/keploy-github-app-beta/llm.ts b/keploy-github-app-beta/llm.ts index c5ca7ec..6ccfac1 100644 --- a/keploy-github-app-beta/llm.ts +++ b/keploy-github-app-beta/llm.ts @@ -238,11 +238,11 @@ There's a syntax error in the add function. LGTM! ` - app.log.info('Analysis Context:', stringanalysisContext); + app.log.info('Analysis Context:', { context: stringanalysisContext }); app.log.info(`Using Hugging Face API: ${API}`); app.log.info(`Using LLM model: ${model}`); - app.log.info('Rules:', rules); - app.log.info('PR Data:', JSON.stringify(prData, null, 2)); + app.log.info('Rules:', { rules }); + app.log.info('PR Data:', { prData: JSON.stringify(prData, null, 2) }); // Call the API with the analysis context diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index adb957c..76874f9 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -67,11 +67,14 @@ async function getLinkedIssueData(context: GithubContext, app: App, owner: strin updated_at: issue.data.updated_at, labels: issue.data.labels.map((l: { name: string }) => l.name), assignees: issue.data.assignees.map((a: { login: string }) => a.login), - comments: comments.map((c: { user: { login: string }, body: string, created_at: string }) => ({ - author: c.user.login, - body: c.body, - created_at: c.created_at - })) + comments: comments.map((c) => { + const comment = c as { user: { login: string }, body: string, created_at: string }; + return { + author: comment.user.login, + body: comment.body, + created_at: comment.created_at + }; + }) }; } catch (error) { app.log.error('Error fetching linked issue data:', error); @@ -102,17 +105,25 @@ export function extractCodeChangesForLLM(app: App, files: FileChange[]): CodeCha // return codeFileExtensions.includes(ext); // }) .map((file) => { - const changes = parsePatch(file.patch); + const f = file as { + filename: string, + status: string, + additions: number, + deletions: number, + changes: number, + patch?: string + }; + const changes = parsePatch(f.patch); return { - file: file.filename, - type: file.status, + file: f.filename, + type: f.status, changes: { removed: changes.removed.join('\n'), added: changes.added.join('\n') }, stats: { - additions: file.additions, - deletions: file.deletions + additions: f.additions, + deletions: f.deletions } }; }); @@ -134,21 +145,24 @@ export async function getPrFilesAndDiffs(context: GithubContext, app: App, owner context.octokit.pulls.listFiles, { owner, repo, pull_number: prNumber } ); - return files.map((file: { - filename: string, - status: string, - additions: number, - deletions: number, - changes: number, - patch?: string - }) => ({ - filename: file.filename, - status: file.status, - additions: file.additions, - deletions: file.deletions, - changes: file.changes, - patch: file.patch || 'Diff too large to display' - })); + return files.map((file) => { + const f = file as { + filename: string, + status: string, + additions: number, + deletions: number, + changes: number, + patch?: string + }; + return { + filename: f.filename, + status: f.status, + additions: f.additions, + deletions: f.deletions, + changes: f.changes, + patch: f.patch || 'Diff too large to display' + }; + }); } catch (error) { app.log.error('Error fetching files:', error); return []; @@ -263,10 +277,7 @@ async function getRepositoryContext(context: GithubContext, app: App) { // Fetch README content const readmeResponse = await context.octokit.repos.getReadme({ owner, - repo, - mediaType: { - format: 'raw', - }, + repo }); // Fetch repository structure using git trees @@ -274,7 +285,7 @@ async function getRepositoryContext(context: GithubContext, app: App) { owner, repo, tree_sha: 'HEAD', - recursive: 'true' + recursive: true }); const folderStructure = repoStructure.data.tree @@ -282,8 +293,13 @@ async function getRepositoryContext(context: GithubContext, app: App) { .map((item: { path: string }) => item.path) .join('\n'); + // Convert ReadmeResponse to string for compatibility with Repository type + const readmeContent = typeof readmeResponse.data.content === 'string' + ? Buffer.from(readmeResponse.data.content, 'base64').toString('utf-8') + : JSON.stringify(readmeResponse.data); + return { - readme: readmeResponse.data, + readme: readmeContent, structure: folderStructure, name: repo, owner: owner diff --git a/keploy-github-app-beta/src/addLabel.ts b/keploy-github-app-beta/src/addLabel.ts index 4144c86..353abd5 100644 --- a/keploy-github-app-beta/src/addLabel.ts +++ b/keploy-github-app-beta/src/addLabel.ts @@ -44,11 +44,15 @@ export async function addLabelToPR( try { // Remove existing review labels first const existingLabels = Object.keys(LABEL_CONFIGS); - await context.octokit.issues.removeLabel({ - ...context.repo(), - issue_number: prNumber, - name: existingLabels - }).catch(() => {/* Ignore errors if labels don't exist */}); + + // Remove labels one by one since the API expects a single string + for (const label of existingLabels) { + await context.octokit.issues.removeLabel({ + ...context.repo(), + issue_number: prNumber, + name: label + }).catch(() => {/* Ignore errors if labels don't exist */}); + } // Add new label await context.octokit.issues.addLabels({ From aec11b455c117a27965c6bb1f4c854eee4b6331b Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 01:55:32 +0530 Subject: [PATCH 08/29] refactor: improve error handling and logging in workflow triggers and PR management - Enhanced error handling in `keploy.ts`, `lint.ts`, and `security.ts` to provide more specific feedback based on error status codes. - Updated logging in `pr.ts` to capture detailed error messages and context when fetching PR files and comments. - Improved user feedback by creating comments on PRs for various error scenarios, enhancing user experience and debugging capabilities. - Refined error handling in `userConfig.ts` to address specific error types and provide clearer logging for configuration loading issues. These changes aim to enhance the robustness and maintainability of the application by improving error visibility and user feedback. Signed-off-by: Sky Singh --- keploy-github-app-beta/keploy.ts | 34 ++++++++++--- keploy-github-app-beta/lint.ts | 34 ++++++++++--- keploy-github-app-beta/pr.ts | 49 +++++++++++++++++-- keploy-github-app-beta/security.ts | 34 ++++++++++--- .../src/config/userConfig.ts | 21 ++++++-- 5 files changed, 139 insertions(+), 33 deletions(-) diff --git a/keploy-github-app-beta/keploy.ts b/keploy-github-app-beta/keploy.ts index da6fb99..50190c4 100644 --- a/keploy-github-app-beta/keploy.ts +++ b/keploy-github-app-beta/keploy.ts @@ -12,16 +12,34 @@ export async function handleKeployWorkflowTrigger(context: GithubContext) { ref }); } catch (error: unknown) { - const errorObj = error as { status?: number }; + const errorObj = error as { status?: number; message?: string }; + + const errorMessage = errorObj.message || 'Unknown error'; + const statusCode = errorObj.status ? ` (Status: ${errorObj.status})` : ''; + + let commentBody: string; + if (errorObj.status === 404) { - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: '⚠️ Failed to run Keploy Tests' - }); - return; + commentBody = '⚠️ Failed to run Keploy Tests: Workflow file not found or inaccessible'; + } else if (errorObj.status === 403) { + commentBody = '⚠️ Failed to run Keploy Tests: Permission denied to access or trigger workflow'; + } else if (errorObj.status === 422) { + commentBody = '⚠️ Failed to run Keploy Tests: Request validation failed, please check workflow configuration'; + } else { + commentBody = `⚠️ Failed to run Keploy Tests: ${errorMessage}${statusCode}`; + } + + console.error('Keploy workflow error:', error); + + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: commentBody + }); + + if (errorObj.status !== 404 && errorObj.status !== 403 && errorObj.status !== 422) { + throw error; } - throw error; } } \ No newline at end of file diff --git a/keploy-github-app-beta/lint.ts b/keploy-github-app-beta/lint.ts index 005637c..c7e9688 100644 --- a/keploy-github-app-beta/lint.ts +++ b/keploy-github-app-beta/lint.ts @@ -12,16 +12,34 @@ export async function handleLintWorkflowTrigger(context: GithubContext) { ref }); } catch (error: unknown) { - const errorObj = error as { status?: number }; + const errorObj = error as { status?: number; message?: string }; + + const errorMessage = errorObj.message || 'Unknown error'; + const statusCode = errorObj.status ? ` (Status: ${errorObj.status})` : ''; + + let commentBody: string; + if (errorObj.status === 404) { - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: 'Lint workflow failed' - }); - return; + commentBody = 'Lint workflow failed: Workflow file not found or inaccessible'; + } else if (errorObj.status === 403) { + commentBody = 'Lint workflow failed: Permission denied to access or trigger workflow'; + } else if (errorObj.status === 422) { + commentBody = 'Lint workflow failed: Request validation failed, please check workflow configuration'; + } else { + commentBody = `Lint workflow failed: ${errorMessage}${statusCode}`; + } + + console.error('Lint workflow error:', error); + + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: commentBody + }); + + if (errorObj.status !== 404 && errorObj.status !== 403 && errorObj.status !== 422) { + throw error; } - throw error; } } \ No newline at end of file diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 76874f9..c2d9c68 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -163,8 +163,26 @@ export async function getPrFilesAndDiffs(context: GithubContext, app: App, owner patch: f.patch || 'Diff too large to display' }; }); - } catch (error) { - app.log.error('Error fetching files:', error); + } catch (error: unknown) { + const errorObj = error as { status?: number; message?: string }; + const errorMessage = errorObj.message || 'Unknown error'; + const statusCode = errorObj.status ? ` (Status: ${errorObj.status})` : ''; + + app.log.error(`Error fetching files: ${errorMessage}${statusCode}`, error); + + try { + if (prNumber) { + await context.octokit.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: `⚠️ Failed to fetch PR files: ${errorMessage}${statusCode}` + }); + } + } catch (commentError) { + app.log.error('Failed to post error comment:', commentError); + } + return []; } } @@ -198,7 +216,10 @@ export async function getPrComments( payload?: { pull_request: PullRequest }; repo?: () => { owner: string; repo: string }; octokit?: { - issues: { listComments: Function }; + issues: { + listComments: Function; + createComment: Function; + }; pulls: { listReviewComments: Function }; paginate: Function; } @@ -227,8 +248,26 @@ export async function getPrComments( issue_comments: issueComments.map(formatComment), review_comments: reviewComments.map(formatComment) }; - } catch (error) { - app.log.error('Error fetching comments:', error); + } catch (error: unknown) { + const errorObj = error as { status?: number; message?: string }; + const errorMessage = errorObj.message || 'Unknown error'; + const statusCode = errorObj.status ? ` (Status: ${errorObj.status})` : ''; + + app.log.error(`Error fetching comments: ${errorMessage}${statusCode}`, error); + + try { + if (context.octokit && prNumber) { + await context.octokit.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: `⚠️ Failed to fetch PR comments: ${errorMessage}${statusCode}` + }); + } + } catch (commentError) { + app.log.error('Failed to post error comment:', commentError); + } + return { issue_comments: [], review_comments: [] }; } } diff --git a/keploy-github-app-beta/security.ts b/keploy-github-app-beta/security.ts index 91b1274..67e6e14 100644 --- a/keploy-github-app-beta/security.ts +++ b/keploy-github-app-beta/security.ts @@ -18,16 +18,34 @@ export async function handleSecurityWorkflowTrigger(context: GithubContext) { ref }); } catch (error: unknown) { - const errorObj = error as { status?: number }; + const errorObj = error as { status?: number; message?: string }; + + const errorMessage = errorObj.message || 'Unknown error'; + const statusCode = errorObj.status ? ` (Status: ${errorObj.status})` : ''; + + let commentBody: string; + if (errorObj.status === 404) { - await context.octokit.issues.createComment({ - ...context.repo(), - issue_number: context.payload.pull_request.number, - body: 'Failed to run security check' - }); - return; + commentBody = 'Failed to run security check: Workflow file not found or inaccessible'; + } else if (errorObj.status === 403) { + commentBody = 'Failed to run security check: Permission denied to access or trigger workflow'; + } else if (errorObj.status === 422) { + commentBody = 'Failed to run security check: Request validation failed, please check workflow configuration'; + } else { + commentBody = `Failed to run security check: ${errorMessage}${statusCode}`; + } + + console.error('Security workflow error:', error); + + await context.octokit.issues.createComment({ + ...context.repo(), + issue_number: context.payload.pull_request.number, + body: commentBody + }); + + if (errorObj.status !== 404 && errorObj.status !== 403 && errorObj.status !== 422) { + throw error; } - throw error; } } \ No newline at end of file diff --git a/keploy-github-app-beta/src/config/userConfig.ts b/keploy-github-app-beta/src/config/userConfig.ts index 9c57c01..a30ba39 100644 --- a/keploy-github-app-beta/src/config/userConfig.ts +++ b/keploy-github-app-beta/src/config/userConfig.ts @@ -8,7 +8,7 @@ export interface ModelInfo { export interface UserConfig { useCase: string; apiEndpoint: string; - selectedModel: string; // Changed from ModelInfo to string + selectedModel: string; } const CONFIG_FILE = 'keploy-config.json'; @@ -22,8 +22,21 @@ export function loadConfig(): UserConfig | null { if (fs.existsSync(CONFIG_FILE)) { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); } - } catch (error) { - console.error('Error loading config:', error); + console.warn('Config file not found:', CONFIG_FILE); + return null; + } catch (error: unknown) { + const errorObj = error as { message?: string }; + const errorMessage = errorObj.message || 'Unknown error'; + console.error(`Error loading config: ${errorMessage}`, error); + + if (error instanceof SyntaxError) { + console.error('JSON parsing error: The config file contains invalid JSON. Please check its format.'); + } else if ((error as NodeJS.ErrnoException).code === 'EACCES') { + console.error('Permission error: Unable to access the config file due to permission restrictions.'); + } else if ((error as NodeJS.ErrnoException).code === 'EMFILE') { + console.error('System error: Too many open files. Try closing some applications and try again.'); + } + + return null; } - return null; } From 4ac4230cb708e72f805c4931fde156998ae442a5 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 02:03:05 +0530 Subject: [PATCH 09/29] feat: implement structured error handling and improve configuration loading - Introduced a new `errors.ts` file to define structured error types for better error management across the application. - Enhanced the `loadConfig` and `saveConfig` functions in `userConfig.ts` to return a `Result` type, improving error handling and logging. - Updated the `llm.ts` and `pr.ts` files to utilize the new error handling structure, providing clearer feedback on configuration loading and linked issue data retrieval. - Improved user feedback in the CLI by logging specific error messages when configuration loading fails. These changes aim to enhance the robustness and maintainability of the application by providing clearer error visibility and structured handling. Signed-off-by: Sky Singh --- keploy-github-app-beta/errors.ts | 142 ++++++++++++++++++ keploy-github-app-beta/llm.ts | 19 ++- keploy-github-app-beta/pr.ts | 47 +++++- keploy-github-app-beta/src/cli.ts | 7 +- .../src/config/userConfig.ts | 82 ++++++++-- 5 files changed, 273 insertions(+), 24 deletions(-) create mode 100644 keploy-github-app-beta/errors.ts diff --git a/keploy-github-app-beta/errors.ts b/keploy-github-app-beta/errors.ts new file mode 100644 index 0000000..cc99ab6 --- /dev/null +++ b/keploy-github-app-beta/errors.ts @@ -0,0 +1,142 @@ +// Error types for structured error handling + +// Define a Result type that can contain either a success value or an error +export type Result = + | { success: true; value: T } + | { success: false; error: E }; + +// Add a declaration for Error.captureStackTrace which exists in Node.js +declare global { + interface ErrorConstructor { + captureStackTrace(targetObject: object, constructorOpt?: Function): void; + } +} + +/** + * Base application error class that all specific error types extend + */ +export class AppError extends Error { + /** + * @param message Error message + * @param cause Optional underlying cause of the error + */ + constructor(message: string, public readonly cause?: unknown) { + super(message); + this.name = this.constructor.name; + // Maintain proper stack trace in Node.js + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } + + /** + * Gets the original error if available + */ + public getOriginalError(): Error | null { + return this.cause instanceof Error ? this.cause : null; + } + + /** + * Creates a user-friendly error message + */ + public toUserFriendlyMessage(): string { + return this.message; + } +} + +/** + * Error related to configuration issues + */ +export class ConfigError extends AppError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +/** + * Error related to file system operations + */ +export class FileSystemError extends AppError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +/** + * Error related to API requests (GitHub, etc.) + */ +export class ApiError extends AppError { + public readonly status?: number; + + constructor(message: string, cause?: unknown, status?: number) { + super(message, cause); + this.status = status; + } + + public static fromError(error: unknown): ApiError { + const errorObj = error as { status?: number; message?: string }; + const errorMessage = errorObj.message || 'Unknown API error'; + const statusCode = errorObj.status; + + return new ApiError(errorMessage, error, statusCode); + } + + public toUserFriendlyMessage(): string { + let message = this.message; + if (this.status) { + if (this.status === 404) { + return `Resource not found (404): ${this.message}`; + } else if (this.status === 403) { + return `Permission denied (403): ${this.message}`; + } else if (this.status === 422) { + return `Invalid request (422): ${this.message}`; + } + message = `${message} (Status: ${this.status})`; + } + return message; + } +} + +/** + * Error related to parsing operations + */ +export class ParseError extends AppError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +/** + * Error related to LLM/AI operations + */ +export class LLMError extends AppError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +/** + * Error for workflow-related operations + */ +export class WorkflowError extends ApiError { + constructor(message: string, cause?: unknown, status?: number) { + super(message, cause, status); + } + + public static fromApiError(error: unknown, workflowName: string): WorkflowError { + const apiError = ApiError.fromError(error); + + let message = `Failed to run ${workflowName} workflow`; + if (apiError.status === 404) { + message = `${message}: Workflow file not found or inaccessible`; + } else if (apiError.status === 403) { + message = `${message}: Permission denied to access or trigger workflow`; + } else if (apiError.status === 422) { + message = `${message}: Request validation failed, please check workflow configuration`; + } else { + message = `${message}: ${apiError.message}`; + } + + return new WorkflowError(message, error, apiError.status); + } +} \ No newline at end of file diff --git a/keploy-github-app-beta/llm.ts b/keploy-github-app-beta/llm.ts index 6ccfac1..4e3fa07 100644 --- a/keploy-github-app-beta/llm.ts +++ b/keploy-github-app-beta/llm.ts @@ -14,13 +14,24 @@ export async function handlePrAnalysis( app: App ) { // Load current configuration - const config = loadConfig(); - const useCase = config ? useCaseModels[config.useCase] : null; + const configResult = loadConfig(); + let useCase = null; + let useCaseStr = 'Not configured'; + let apiEndpoint = 'Not configured'; + + if (configResult.success) { + const config = configResult.value; + useCase = useCaseModels[config.useCase]; + useCaseStr = config.useCase; + apiEndpoint = config.apiEndpoint; + } else { + app.log.error(`Failed to load configuration: ${configResult.error.message}`); + } // Build the config info comment const configInfo = `## Keploy Configuration -Use Case: ${config?.useCase || 'Not configured'} -API Endpoint: ${config?.apiEndpoint || 'Not configured'} +Use Case: ${useCaseStr} +API Endpoint: ${apiEndpoint} ### Suggested Models for ${useCase?.name || 'current use case'}: ${useCase?.suggestedModels.map(model => `- ${model.name}: ${model.link}`).join('\n') || 'No models configured'} diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index c2d9c68..524ad36 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -11,6 +11,30 @@ import { PatchResult } from './types.js'; +// Define a local ApiError class +class ApiError extends Error { + public readonly status?: number; + + constructor(message: string, public readonly cause?: unknown, status?: number) { + super(message); + this.name = this.constructor.name; + this.status = status; + } + + public static fromError(error: unknown): ApiError { + const errorObj = error as { status?: number; message?: string }; + const errorMessage = errorObj.message || 'Unknown API error'; + const statusCode = errorObj.status; + + return new ApiError(errorMessage, error, statusCode); + } +} + +// Define a Result type for handling success/failure +type Result = + | { success: true; value: T } + | { success: false; error: E }; + export async function getAllPrDetails(context: GithubContext, app: App): Promise { const { pull_request: pr } = context.payload; const { owner, repo } = context.repo(); @@ -18,7 +42,18 @@ export async function getAllPrDetails(context: GithubContext, app: App): Promise // Extract issue number from PR body or title using regex const issueNumber = extractIssueNumber(pr.body || pr.title); - const issueData = issueNumber ? await getLinkedIssueData(context, app, owner, repo, issueNumber) : null; + + // Get linked issue data with proper error handling + let issueData: LinkedIssue | null = null; + if (issueNumber) { + const issueResult = await getLinkedIssueData(context, app, owner, repo, issueNumber); + if (issueResult.success) { + issueData = issueResult.value; + } else { + app.log.error(`Failed to get linked issue data: ${issueResult.error.message}`); + // Optionally post a comment about the issue data fetch failure + } + } // Get repository context const repoContext = await getRepositoryContext(context, app); @@ -44,7 +79,7 @@ function extractIssueNumber(text: string): number | null { return match ? parseInt(match[1]) : null; } -async function getLinkedIssueData(context: GithubContext, app: App, owner: string, repo: string, issueNumber: number): Promise { +async function getLinkedIssueData(context: GithubContext, app: App, owner: string, repo: string, issueNumber: number): Promise> { try { const issue = await context.octokit.issues.get({ owner, @@ -58,6 +93,8 @@ async function getLinkedIssueData(context: GithubContext, app: App, owner: strin ); return { + success: true, + value: { number: issueNumber, title: issue.data.title, body: issue.data.body, @@ -75,10 +112,12 @@ async function getLinkedIssueData(context: GithubContext, app: App, owner: strin created_at: comment.created_at }; }) + } }; } catch (error) { - app.log.error('Error fetching linked issue data:', error); - return null; + const appError = ApiError.fromError(error); + app.log.error(`Error fetching linked issue data: ${appError.message}`, error); + return { success: false, error: appError }; } } diff --git a/keploy-github-app-beta/src/cli.ts b/keploy-github-app-beta/src/cli.ts index 3dcdf1a..e5c40e9 100644 --- a/keploy-github-app-beta/src/cli.ts +++ b/keploy-github-app-beta/src/cli.ts @@ -5,12 +5,15 @@ import chalk from 'chalk'; // This will be fixed by package.json update export async function promptUserConfig(): Promise { // Check for existing config - const existingConfig = loadConfig(); - if (existingConfig) { + const configResult = loadConfig(); + if (configResult.success) { + const existingConfig = configResult.value; console.log(chalk.cyan('Using existing configuration:')); console.log(`Use Case: ${existingConfig.useCase}`); console.log(`API Endpoint: ${existingConfig.apiEndpoint}`); return existingConfig; + } else { + console.log(chalk.yellow(`No existing configuration found or error loading: ${configResult.error.message}`)); } // Get use case diff --git a/keploy-github-app-beta/src/config/userConfig.ts b/keploy-github-app-beta/src/config/userConfig.ts index a30ba39..25a9587 100644 --- a/keploy-github-app-beta/src/config/userConfig.ts +++ b/keploy-github-app-beta/src/config/userConfig.ts @@ -1,5 +1,36 @@ import fs from 'fs'; +// Define local error types for this file +class ConfigFileError extends Error { + constructor(message: string, public readonly cause?: unknown) { + super(message); + this.name = this.constructor.name; + } +} + +class FileSystemError extends ConfigFileError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +class ConfigError extends ConfigFileError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +class ParseError extends ConfigFileError { + constructor(message: string, cause?: unknown) { + super(message, cause); + } +} + +// Define a Result type for handling success/failure +export type Result = + | { success: true; value: T } + | { success: false; error: E }; + export interface ModelInfo { name: string; link: string; @@ -13,30 +44,53 @@ export interface UserConfig { const CONFIG_FILE = 'keploy-config.json'; -export function saveConfig(config: UserConfig): void { - fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); +export function saveConfig(config: UserConfig): Result { + try { + fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); + return { success: true, value: undefined }; + } catch (error: unknown) { + const errorObj = error as { message?: string; code?: string }; + let appError: Error; + + if (errorObj.code === 'EACCES') { + appError = new FileSystemError('Permission denied: Unable to write to config file', error); + } else if (errorObj.code === 'ENOENT') { + appError = new FileSystemError('Directory not found: Unable to write to config file', error); + } else { + appError = new ConfigError(`Failed to save configuration: ${errorObj.message || 'Unknown error'}`, error); + } + + console.error(appError.message, error); + return { success: false, error: appError }; + } } -export function loadConfig(): UserConfig | null { +export function loadConfig(): Result { try { if (fs.existsSync(CONFIG_FILE)) { - return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); + const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); + return { success: true, value: config }; } - console.warn('Config file not found:', CONFIG_FILE); - return null; + + const error = new ConfigError(`Config file not found: ${CONFIG_FILE}`); + console.warn(error.message); + return { success: false, error }; } catch (error: unknown) { - const errorObj = error as { message?: string }; + const errorObj = error as { message?: string; code?: string }; const errorMessage = errorObj.message || 'Unknown error'; - console.error(`Error loading config: ${errorMessage}`, error); + let appError: Error; if (error instanceof SyntaxError) { - console.error('JSON parsing error: The config file contains invalid JSON. Please check its format.'); - } else if ((error as NodeJS.ErrnoException).code === 'EACCES') { - console.error('Permission error: Unable to access the config file due to permission restrictions.'); - } else if ((error as NodeJS.ErrnoException).code === 'EMFILE') { - console.error('System error: Too many open files. Try closing some applications and try again.'); + appError = new ParseError('JSON parsing error: The config file contains invalid JSON. Please check its format.', error); + } else if (errorObj.code === 'EACCES') { + appError = new FileSystemError('Permission error: Unable to access the config file due to permission restrictions.', error); + } else if (errorObj.code === 'EMFILE') { + appError = new FileSystemError('System error: Too many open files. Try closing some applications and try again.', error); + } else { + appError = new ConfigError(`Error loading config: ${errorMessage}`, error); } - return null; + console.error(appError.message, error); + return { success: false, error: appError }; } } From 161ebcdb47a29f5d8ebcbcc7e9afa8c61eba05cd Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 02:07:29 +0530 Subject: [PATCH 10/29] refactor: optimize asynchronous operations in PR and workflow handling - Updated `index.ts` to run workflow triggers in parallel using `Promise.all`, improving performance. - Refactored `getAllPrDetails` in `pr.ts` to execute multiple asynchronous operations concurrently, enhancing efficiency in fetching PR details. - Modified `getLinkedIssueData` to fetch issue details and comments in parallel, streamlining data retrieval. - Improved label removal logic in `addLabel.ts` to handle label deletions concurrently, increasing responsiveness. These changes aim to enhance the application's performance and responsiveness by optimizing asynchronous operations across various modules. Signed-off-by: Sky Singh --- keploy-github-app-beta/index.ts | 9 ++- keploy-github-app-beta/pr.ts | 84 ++++++++++++++++---------- keploy-github-app-beta/src/addLabel.ts | 18 +++--- 3 files changed, 69 insertions(+), 42 deletions(-) diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts index ea11884..881b3d0 100644 --- a/keploy-github-app-beta/index.ts +++ b/keploy-github-app-beta/index.ts @@ -44,9 +44,12 @@ export default async (app: App) => { await reviewPR(context as any, app, llmOutput); // await reviewPR(context, app); - await handleKeployWorkflowTrigger(context); - await handleSecurityWorkflowTrigger(context); - await handleLintWorkflowTrigger(context); + // Run all workflow triggers in parallel + await Promise.all([ + handleKeployWorkflowTrigger(context), + handleSecurityWorkflowTrigger(context), + handleLintWorkflowTrigger(context) + ]); } catch (error) { await handleError(context, app, error); } diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 524ad36..867a293 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -38,15 +38,38 @@ type Result = export async function getAllPrDetails(context: GithubContext, app: App): Promise { const { pull_request: pr } = context.payload; const { owner, repo } = context.repo(); - const filesResult = await getPrFilesAndDiffs(context, app, owner, repo, pr.number); // Extract issue number from PR body or title using regex const issueNumber = extractIssueNumber(pr.body || pr.title); - // Get linked issue data with proper error handling - let issueData: LinkedIssue | null = null; + // Prepare all async operations to run in parallel + const promises = { + filesResult: getPrFilesAndDiffs(context, app, owner, repo, pr.number), + prComments: getPrComments(context, app, owner, repo, pr.number), + repoContext: getRepositoryContext(context, app) + }; + + // Add issue data promise conditionally + let issueDataPromise = null; if (issueNumber) { - const issueResult = await getLinkedIssueData(context, app, owner, repo, issueNumber); + issueDataPromise = getLinkedIssueData(context, app, owner, repo, issueNumber); + } + + // Execute all promises in parallel + const [ + filesResult, + prComments, + repoContext + ] = await Promise.all([ + promises.filesResult, + promises.prComments, + promises.repoContext + ]); + + // Process issue data separately since it's conditional + let issueData: LinkedIssue | null = null; + if (issueDataPromise) { + const issueResult = await issueDataPromise; if (issueResult.success) { issueData = issueResult.value; } else { @@ -54,13 +77,10 @@ export async function getAllPrDetails(context: GithubContext, app: App): Promise // Optionally post a comment about the issue data fetch failure } } - - // Get repository context - const repoContext = await getRepositoryContext(context, app); return { metadata: getPrMetadata(pr), - comments: await getPrComments(context, app, owner, repo, pr.number), + comments: prComments, files: filesResult, relationships: { requested_reviewers: pr.requested_reviewers?.map((u) => u.login) || [], @@ -81,16 +101,18 @@ function extractIssueNumber(text: string): number | null { async function getLinkedIssueData(context: GithubContext, app: App, owner: string, repo: string, issueNumber: number): Promise> { try { - const issue = await context.octokit.issues.get({ - owner, - repo, - issue_number: issueNumber - }); - - const comments = await context.octokit.paginate( - context.octokit.issues.listComments, - { owner, repo, issue_number: issueNumber } - ); + // Fetch issue details and comments in parallel + const [issue, comments] = await Promise.all([ + context.octokit.issues.get({ + owner, + repo, + issue_number: issueNumber + }), + context.octokit.paginate( + context.octokit.issues.listComments, + { owner, repo, issue_number: issueNumber } + ) + ]); return { success: true, @@ -352,19 +374,19 @@ function parsePatch(patch: string | undefined): PatchResult { async function getRepositoryContext(context: GithubContext, app: App) { const { owner, repo } = context.repo(); try { - // Fetch README content - const readmeResponse = await context.octokit.repos.getReadme({ - owner, - repo - }); - - // Fetch repository structure using git trees - const repoStructure = await context.octokit.git.getTree({ - owner, - repo, - tree_sha: 'HEAD', - recursive: true - }); + // Fetch README content and repository structure in parallel + const [readmeResponse, repoStructure] = await Promise.all([ + context.octokit.repos.getReadme({ + owner, + repo + }), + context.octokit.git.getTree({ + owner, + repo, + tree_sha: 'HEAD', + recursive: true + }) + ]); const folderStructure = repoStructure.data.tree .filter((item: { path: string }) => !item.path.includes('node_modules/')) // Exclude node_modules diff --git a/keploy-github-app-beta/src/addLabel.ts b/keploy-github-app-beta/src/addLabel.ts index 353abd5..869ed47 100644 --- a/keploy-github-app-beta/src/addLabel.ts +++ b/keploy-github-app-beta/src/addLabel.ts @@ -45,14 +45,16 @@ export async function addLabelToPR( // Remove existing review labels first const existingLabels = Object.keys(LABEL_CONFIGS); - // Remove labels one by one since the API expects a single string - for (const label of existingLabels) { - await context.octokit.issues.removeLabel({ - ...context.repo(), - issue_number: prNumber, - name: label - }).catch(() => {/* Ignore errors if labels don't exist */}); - } + // Remove labels in parallel with Promise.all + await Promise.all( + existingLabels.map(label => + context.octokit.issues.removeLabel({ + ...context.repo(), + issue_number: prNumber, + name: label + }).catch(() => {/* Ignore errors if labels don't exist */}) + ) + ); // Add new label await context.octokit.issues.addLabels({ From d0cd28f87c5647a26bd21e46e29608061ef7c6d9 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 02:11:49 +0530 Subject: [PATCH 11/29] feat: enhance linked issue handling in PR analysis - Updated `llm.ts` to support multiple linked issues, improving the context provided in PR analysis. - Refactored `pr.ts` to extract multiple issue numbers from PR titles and bodies, allowing for concurrent fetching of linked issues. - Introduced a new `LinkedIssues` interface in `types.ts` to accommodate the changes in linked issue data structure. These enhancements aim to provide a more comprehensive view of linked issues in PR analyses, improving the overall functionality of the application. Signed-off-by: Sky Singh --- keploy-github-app-beta/llm.ts | 41 +++++++------- keploy-github-app-beta/pr.ts | 99 ++++++++++++++++++--------------- keploy-github-app-beta/types.ts | 7 ++- 3 files changed, 83 insertions(+), 64 deletions(-) diff --git a/keploy-github-app-beta/llm.ts b/keploy-github-app-beta/llm.ts index 4e3fa07..ea25e66 100644 --- a/keploy-github-app-beta/llm.ts +++ b/keploy-github-app-beta/llm.ts @@ -47,20 +47,22 @@ ${useCase?.suggestedModels.map(model => `- ${model.name}: ${model.link}`).join(' const code_changes = JSON.stringify(prData.code_changes, null, 2); // Adding indentation for better readability // Build the issue context if available - const issueContext = prData.linked_issue ? ` - Linked Issue: - Number: #${prData.linked_issue.number} - Title: ${prData.linked_issue.title} - Description: ${prData.linked_issue.body} - State: ${prData.linked_issue.state} - Labels: ${prData.linked_issue.labels.join(', ')} - Assignees: ${prData.linked_issue.assignees.join(', ')} + const issueContext = prData.linked_issues && prData.linked_issues.issues_count > 0 ? ` + Linked Issues (${prData.linked_issues.issues_count}): + ${prData.linked_issues.issues.map(issue => ` + Number: #${issue.number} + Title: ${issue.title} + Description: ${issue.body} + State: ${issue.state} + Labels: ${issue.labels.join(', ')} + Assignees: ${issue.assignees.join(', ')} Issue Discussion: - ${prData.linked_issue.comments.map((c: IssueComment) => + ${issue.comments.map((c: IssueComment) => `${c.author} (${c.created_at}): ${c.body}` ).join('\n')} - ` : 'No linked issue found'; + `).join('\n')} + ` : 'No linked issues found'; // Build the analysis comment const analysis = `PR Analysis using ${API}: @@ -112,15 +114,16 @@ export async function analyzeLLM(prData: PRData, rules: string, API: string, mod }, pr: prData, rules: rules, - issue_context: prData.linked_issue ? { - issue_number: prData.linked_issue.number, - issue_title: prData.linked_issue.title, - issue_description: prData.linked_issue.body, - issue_status: prData.linked_issue.state, - issue_labels: prData.linked_issue.labels, - issue_assignees: prData.linked_issue.assignees, - issue_discussion: prData.linked_issue.comments - } : null + issue_context: prData.linked_issues && prData.linked_issues.issues_count > 0 ? + prData.linked_issues.issues.map(issue => ({ + issue_number: issue.number, + issue_title: issue.title, + issue_description: issue.body, + issue_status: issue.state, + issue_labels: issue.labels, + issue_assignees: issue.assignees, + issue_discussion: issue.comments + })) : null }; const stringanalysisContext = JSON.stringify(analysisContext, null, 2); diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 867a293..7404f84 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -8,6 +8,7 @@ import { FileChange, CodeChanges, LinkedIssue, + LinkedIssues, PatchResult } from './types.js'; @@ -40,7 +41,7 @@ export async function getAllPrDetails(context: GithubContext, app: App): Promise const { owner, repo } = context.repo(); // Extract issue number from PR body or title using regex - const issueNumber = extractIssueNumber(pr.body || pr.title); + const issueNumbers = extractIssueNumbers(pr.body || pr.title); // Prepare all async operations to run in parallel const promises = { @@ -50,9 +51,9 @@ export async function getAllPrDetails(context: GithubContext, app: App): Promise }; // Add issue data promise conditionally - let issueDataPromise = null; - if (issueNumber) { - issueDataPromise = getLinkedIssueData(context, app, owner, repo, issueNumber); + let issuesDataPromise = null; + if (issueNumbers.length > 0) { + issuesDataPromise = getLinkedIssueData(context, app, owner, repo, issueNumbers); } // Execute all promises in parallel @@ -67,13 +68,13 @@ export async function getAllPrDetails(context: GithubContext, app: App): Promise ]); // Process issue data separately since it's conditional - let issueData: LinkedIssue | null = null; - if (issueDataPromise) { - const issueResult = await issueDataPromise; - if (issueResult.success) { - issueData = issueResult.value; + let issuesData: LinkedIssues | null = null; + if (issuesDataPromise) { + const issuesResult = await issuesDataPromise; + if (issuesResult.success) { + issuesData = issuesResult.value; } else { - app.log.error(`Failed to get linked issue data: ${issueResult.error.message}`); + app.log.error(`Failed to get linked issue data: ${issuesResult.error.message}`); // Optionally post a comment about the issue data fetch failure } } @@ -88,52 +89,62 @@ export async function getAllPrDetails(context: GithubContext, app: App): Promise labels: pr.labels?.map((l) => l.name) || [] }, code_changes: extractCodeChangesForLLM(app, filesResult), - linked_issue: issueData, + linked_issues: issuesData, repository: repoContext }; } -function extractIssueNumber(text: string): number | null { +function extractIssueNumbers(text: string): number[] { + if (!text) return []; + // Look for patterns like "fixes #123", "closes #123", "related to #123" - const match = text?.match(/#(\d+)/); - return match ? parseInt(match[1]) : null; + const regex = /#(\d+)/g; + const matches = [...text.matchAll(regex)]; + return matches.map(match => parseInt(match[1])); } -async function getLinkedIssueData(context: GithubContext, app: App, owner: string, repo: string, issueNumber: number): Promise> { +async function getLinkedIssueData(context: GithubContext, app: App, owner: string, repo: string, issueNumbers: number[]): Promise> { try { - // Fetch issue details and comments in parallel - const [issue, comments] = await Promise.all([ - context.octokit.issues.get({ - owner, - repo, - issue_number: issueNumber - }), - context.octokit.paginate( - context.octokit.issues.listComments, - { owner, repo, issue_number: issueNumber } - ) - ]); + const issuePromises = issueNumbers.map(async (issueNumber) => { + const [issue, comments] = await Promise.all([ + context.octokit.issues.get({ + owner, + repo, + issue_number: issueNumber + }), + context.octokit.paginate( + context.octokit.issues.listComments, + { owner, repo, issue_number: issueNumber } + ) + ]); + return { + number: issueNumber, + title: issue.data.title, + body: issue.data.body, + state: issue.data.state, + author: issue.data.user.login, + created_at: issue.data.created_at, + updated_at: issue.data.updated_at, + labels: issue.data.labels.map((l: { name: string }) => l.name), + assignees: issue.data.assignees.map((a: { login: string }) => a.login), + comments: comments.map((c) => { + const comment = c as { user: { login: string }, body: string, created_at: string }; + return { + author: comment.user.login, + body: comment.body, + created_at: comment.created_at + }; + }) + }; + }); + + const issues = await Promise.all(issuePromises); return { success: true, value: { - number: issueNumber, - title: issue.data.title, - body: issue.data.body, - state: issue.data.state, - author: issue.data.user.login, - created_at: issue.data.created_at, - updated_at: issue.data.updated_at, - labels: issue.data.labels.map((l: { name: string }) => l.name), - assignees: issue.data.assignees.map((a: { login: string }) => a.login), - comments: comments.map((c) => { - const comment = c as { user: { login: string }, body: string, created_at: string }; - return { - author: comment.user.login, - body: comment.body, - created_at: comment.created_at - }; - }) + issues: issues, + issues_count: issues.length } }; } catch (error) { diff --git a/keploy-github-app-beta/types.ts b/keploy-github-app-beta/types.ts index 2f1345d..738be27 100644 --- a/keploy-github-app-beta/types.ts +++ b/keploy-github-app-beta/types.ts @@ -126,6 +126,11 @@ export interface LinkedIssue { comments: IssueComment[]; } +export interface LinkedIssues { + issues: LinkedIssue[]; + issues_count: number; +} + export interface PRData { metadata: PRMetadata; comments: PRComments; @@ -136,7 +141,7 @@ export interface PRData { labels: string[]; }; code_changes: CodeChanges; - linked_issue: LinkedIssue | null; + linked_issues: LinkedIssues | null; repository: Repository; } From 817708e73aeb66f1a520213eb91b5dbaf5352fb3 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 02:14:36 +0530 Subject: [PATCH 12/29] fix: improve validation of response content in getRulesForLLM - Updated the condition in `getRulesForLLM` to ensure that the response data contains valid content before processing. - Enhanced the error message for better clarity when the content is missing or invalid. These changes aim to provide more robust error handling and clearer feedback when loading rules from the GitHub API. Signed-off-by: Sky Singh --- keploy-github-app-beta/rules.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keploy-github-app-beta/rules.ts b/keploy-github-app-beta/rules.ts index 06b74e5..69e7d3f 100644 --- a/keploy-github-app-beta/rules.ts +++ b/keploy-github-app-beta/rules.ts @@ -11,7 +11,7 @@ export async function getRulesForLLM(context: GithubContext): Promise { }); // Check if the response is valid and contains content - if (response.data && 'content' in response.data) { + if (response.data && 'content' in response.data && response.data.content) { const content = Buffer.from(response.data.content, 'base64').toString(); return { success: true, rules: content }; } @@ -19,7 +19,7 @@ export async function getRulesForLLM(context: GithubContext): Promise { return { success: false, rules: '', - error: 'Failed to load rules.md - unexpected response format' + error: 'Failed to load rules.md - missing or invalid content' }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; From 8bfd0a1e0268a363e3d3df91ecbc060fcd97ed9c Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 02:18:47 +0530 Subject: [PATCH 13/29] feat: enhance label determination logic in addLabel.ts - Updated the label determination logic to include a new helper function, `isValidShortResponse`, which checks for valid short responses before categorizing them as 'Spam'. - This change improves the accuracy of label assignment based on the content of the response, ensuring that valid short responses are not incorrectly flagged. These enhancements aim to provide more precise labeling in PR analysis, improving the overall functionality of the application. Signed-off-by: Sky Singh --- keploy-github-app-beta/src/addLabel.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/keploy-github-app-beta/src/addLabel.ts b/keploy-github-app-beta/src/addLabel.ts index 869ed47..afe73e6 100644 --- a/keploy-github-app-beta/src/addLabel.ts +++ b/keploy-github-app-beta/src/addLabel.ts @@ -29,13 +29,22 @@ export async function determineLabelFromAnalysis(llmResponse: string): Promise response.includes(valid)); +} + export async function addLabelToPR( context: GithubContext, prNumber: number, From 518bc318c24fb9b6cdf38d7bd3b15b6c9b68ee82 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 15:06:17 +0530 Subject: [PATCH 14/29] feat: add PDF export functionality for pull request summaries Signed-off-by: Sky Singh --- keploy-github-app-beta/index.ts | 21 ++- keploy-github-app-beta/package-lock.json | 231 +++++++++++++++++++++++ keploy-github-app-beta/package.json | 1 + keploy-github-app-beta/pdf-export.ts | 220 +++++++++++++++++++++ 4 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 keploy-github-app-beta/pdf-export.ts diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts index 881b3d0..780283a 100644 --- a/keploy-github-app-beta/index.ts +++ b/keploy-github-app-beta/index.ts @@ -14,6 +14,7 @@ import { promptUserConfig } from './src/cli.js'; import { reviewPR } from './diffparser.js'; import { handleLintWorkflowTrigger } from "./lint.js"; import { App, Config, GithubContext } from "./types.js"; +import { savePrAsPdf } from "./pdf-export.js"; let config: Config; @@ -44,6 +45,24 @@ export default async (app: App) => { await reviewPR(context as any, app, llmOutput); // await reviewPR(context, app); + // Export PR data to PDF + try { + const { owner, repo } = context.repo(); + const prNumber = context.payload.pull_request.number; + const pdfFilename = await savePrAsPdf(prData, owner, repo, prNumber); + app.log.info(`PR exported to PDF: ${pdfFilename}`); + + // Post comment with PDF info + await context.octokit.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: `📄 PR summary has been exported as PDF: ${pdfFilename}` + }); + } catch (pdfError) { + app.log.error("Failed to export PR as PDF", pdfError); + } + // Run all workflow triggers in parallel await Promise.all([ handleKeployWorkflowTrigger(context), @@ -58,4 +77,4 @@ export default async (app: App) => { if (app.on) { app.on(["pull_request.opened", "pull_request.synchronize"], handlePrEvent); } -}; +}; \ No newline at end of file diff --git a/keploy-github-app-beta/package-lock.json b/keploy-github-app-beta/package-lock.json index de6da01..6c106f2 100644 --- a/keploy-github-app-beta/package-lock.json +++ b/keploy-github-app-beta/package-lock.json @@ -12,6 +12,7 @@ "axios": "^1.7.9", "chalk": "^5.4.1", "inquirer": "^12.4.2", + "jspdf": "^3.0.0", "parse-diff": "^0.11.1", "probot": "^13.0.1" }, @@ -28,6 +29,18 @@ "node": ">= 18" } }, + "node_modules/@babel/runtime": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -2042,6 +2055,13 @@ "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", "license": "MIT" }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", @@ -2098,6 +2118,13 @@ "@types/node": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2275,6 +2302,18 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -2302,6 +2341,16 @@ "dev": true, "license": "MIT" }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -2375,6 +2424,18 @@ "node": ">=8" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/btoa-lite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", @@ -2442,6 +2503,33 @@ "node": ">=6" } }, + "node_modules/canvg": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", + "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/canvg/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "optional": true + }, "node_modules/chalk": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", @@ -2606,6 +2694,18 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, + "node_modules/core-js": { + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", + "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2628,6 +2728,16 @@ "node": ">= 8" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", @@ -2715,6 +2825,16 @@ "node": ">=0.3.1" } }, + "node_modules/dompurify": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", + "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dotenv": { "version": "16.4.7", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", @@ -3268,6 +3388,12 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -3602,6 +3728,20 @@ "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", "license": "MIT" }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "optional": true, + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -3961,6 +4101,24 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/jspdf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.0.tgz", + "integrity": "sha512-QvuQZvOI8CjfjVgtajdL0ihrDYif1cN5gXiF9lb9Pd9JOpmocvnNyFO9sdiJ/8RA5Bu8zyGOUjJLj5kiku16ug==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^3.2.4", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -4491,6 +4649,13 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT", + "optional": true + }, "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", @@ -4805,6 +4970,16 @@ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "license": "MIT" }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "license": "MIT", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -4872,6 +5047,12 @@ "node": ">=4" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, "node_modules/require-in-the-middle": { "version": "7.5.1", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.1.tgz", @@ -4939,6 +5120,16 @@ "node": ">=4" } }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -5251,6 +5442,16 @@ "node": ">= 10.x" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -5345,6 +5546,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/thread-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", @@ -5614,6 +5835,16 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/keploy-github-app-beta/package.json b/keploy-github-app-beta/package.json index 57542ea..a7d7ad8 100644 --- a/keploy-github-app-beta/package.json +++ b/keploy-github-app-beta/package.json @@ -20,6 +20,7 @@ "axios": "^1.7.9", "chalk": "^5.4.1", "inquirer": "^12.4.2", + "jspdf": "^3.0.0", "parse-diff": "^0.11.1", "probot": "^13.0.1" }, diff --git a/keploy-github-app-beta/pdf-export.ts b/keploy-github-app-beta/pdf-export.ts new file mode 100644 index 0000000..d10357c --- /dev/null +++ b/keploy-github-app-beta/pdf-export.ts @@ -0,0 +1,220 @@ +import jsPDF from 'jspdf'; +import { PRData, Comment, FileChange, CodeChange, LinkedIssue } from './types.js'; +import fs from 'fs'; +import path from 'path'; + +/** + * Generates a PDF document containing all PR information + * @param prData The complete PR data + * @returns Buffer containing the PDF document + */ +export async function generatePrPdf(prData: PRData): Promise { + // Create a new PDF document + const doc = new jsPDF(); + let y = 10; // Initial y position + + // Add PR title + doc.setFontSize(18); + doc.text(`PR #${prData.metadata.title}`, 10, y); + y += 10; + + // Add PR metadata + doc.setFontSize(12); + doc.text(`Author: ${prData.metadata.author}`, 10, y); + y += 7; + doc.text(`Created: ${new Date(prData.metadata.created_at).toLocaleString()}`, 10, y); + y += 7; + doc.text(`Status: ${prData.metadata.state} ${prData.metadata.draft ? '(Draft)' : ''}`, 10, y); + y += 7; + doc.text(`Changes: ${prData.metadata.changed_files} files, +${prData.metadata.additions} -${prData.metadata.deletions}`, 10, y); + y += 14; + + // Add PR description if present + if (prData.metadata.body) { + doc.setFontSize(14); + doc.text('Description:', 10, y); + y += 7; + doc.setFontSize(10); + + // Handle multiline description + const descriptionLines = prData.metadata.body.split('\n'); + for (const line of descriptionLines) { + // Check if we need a new page + if (y > 280) { + doc.addPage(); + y = 10; + } + + const wrappedText = doc.splitTextToSize(line, 180); + doc.text(wrappedText, 10, y); + y += wrappedText.length * 5; + } + y += 10; + } + + // Add code changes section + doc.setFontSize(14); + doc.text('Code Changes:', 10, y); + y += 10; + + // List changed files + doc.setFontSize(12); + for (const file of prData.files) { + // Check if we need a new page + if (y > 280) { + doc.addPage(); + y = 10; + } + + doc.text(`${file.filename} (${file.status}): +${file.additions} -${file.deletions}`, 10, y); + y += 7; + } + y += 10; + + // Add comments section + doc.addPage(); + y = 10; + doc.setFontSize(14); + doc.text('PR Comments:', 10, y); + y += 10; + + // List issue comments + if (prData.comments.issue_comments.length > 0) { + doc.setFontSize(12); + doc.text('Issue Comments:', 10, y); + y += 7; + + for (const comment of prData.comments.issue_comments) { + // Check if we need a new page + if (y > 280) { + doc.addPage(); + y = 10; + } + + doc.setFontSize(10); + doc.text(`${comment.user} (${new Date(comment.created_at).toLocaleString()}):`, 10, y); + y += 5; + + const commentLines = doc.splitTextToSize(comment.body, 180); + doc.text(commentLines, 15, y); + y += commentLines.length * 5 + 5; + } + } else { + doc.setFontSize(10); + doc.text('No issue comments', 10, y); + y += 7; + } + + // List review comments + y += 10; + doc.setFontSize(12); + doc.text('Review Comments:', 10, y); + y += 7; + + if (prData.comments.review_comments.length > 0) { + for (const comment of prData.comments.review_comments) { + // Check if we need a new page + if (y > 280) { + doc.addPage(); + y = 10; + } + + doc.setFontSize(10); + doc.text(`${comment.user} (${new Date(comment.created_at).toLocaleString()}):`, 10, y); + y += 5; + + const commentLines = doc.splitTextToSize(comment.body, 180); + doc.text(commentLines, 15, y); + y += commentLines.length * 5 + 5; + } + } else { + doc.setFontSize(10); + doc.text('No review comments', 10, y); + y += 7; + } + + // Add linked issues section if present + if (prData.linked_issues && prData.linked_issues.issues.length > 0) { + doc.addPage(); + y = 10; + doc.setFontSize(14); + doc.text('Linked Issues:', 10, y); + y += 10; + + for (const issue of prData.linked_issues.issues) { + // Check if we need a new page + if (y > 280) { + doc.addPage(); + y = 10; + } + + doc.setFontSize(12); + doc.text(`Issue #${issue.number}: ${issue.title}`, 10, y); + y += 7; + doc.setFontSize(10); + doc.text(`Author: ${issue.author} | State: ${issue.state}`, 15, y); + y += 5; + + if (issue.body) { + const bodyLines = doc.splitTextToSize(issue.body, 175); + doc.text(bodyLines, 15, y); + y += bodyLines.length * 5 + 5; + } + + // Add issue comments if present + if (issue.comments.length > 0) { + doc.text('Comments:', 15, y); + y += 5; + + for (const comment of issue.comments) { + // Check if we need a new page + if (y > 280) { + doc.addPage(); + y = 10; + } + + doc.text(`${comment.author} (${new Date(comment.created_at).toLocaleString()}):`, 20, y); + y += 5; + + const commentLines = doc.splitTextToSize(comment.body, 170); + doc.text(commentLines, 25, y); + y += commentLines.length * 5 + 5; + } + } + + y += 10; + } + } + + // Generate Buffer from PDF + const pdfBuffer = Buffer.from(doc.output('arraybuffer')); + return pdfBuffer; +} + +/** + * Saves PR data as a PDF file with a specific filename format + * @param prData The complete PR data + * @param owner Repository owner + * @param repo Repository name + * @param prNumber Pull request number + * @returns Filename of the saved PDF + */ +export async function savePrAsPdf(prData: PRData, owner: string, repo: string, prNumber: number): Promise { + const pdfBuffer = await generatePrPdf(prData); + + // Create artifacts directory if it doesn't exist + const artifactsDir = path.join(process.cwd(), 'artifacts'); + if (!fs.existsSync(artifactsDir)) { + fs.mkdirSync(artifactsDir, { recursive: true }); + } + + // Generate filename with timestamp + const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); + const filename = `${owner}-${repo}-pr-${prNumber}-${timestamp}.pdf`; + const filePath = path.join(artifactsDir, filename); + + // Write PDF buffer to file + fs.writeFileSync(filePath, pdfBuffer); + + return filePath; +} \ No newline at end of file From d1c86ed05842d1d53e8329a9822277d880e8d060 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 15:28:28 +0530 Subject: [PATCH 15/29] feat: implement user feedback improvements in PR analysis - Enhanced user feedback mechanisms in the PR analysis workflow, providing clearer notifications and updates during processing. - Updated logging to capture more detailed information about the analysis steps, improving transparency for users. - Refined error handling to ensure users receive specific feedback when issues arise, enhancing the overall user experience. These changes aim to improve user engagement and clarity during PR analysis, making the application more user-friendly. Signed-off-by: Sky Singh --- keploy-github-app-beta/keploy-config.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 keploy-github-app-beta/keploy-config.json diff --git a/keploy-github-app-beta/keploy-config.json b/keploy-github-app-beta/keploy-config.json new file mode 100644 index 0000000..fa4d342 --- /dev/null +++ b/keploy-github-app-beta/keploy-config.json @@ -0,0 +1,5 @@ +{ + "useCase": "Documentation", + "apiEndpoint": "https://xyz/api/generate", + "selectedModel": "llama2" +} \ No newline at end of file From 31dbc3f642055588da206a536cb4d27a94876fe2 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 16:51:25 +0530 Subject: [PATCH 16/29] fix: update API endpoint in configuration - Removed the existing API endpoint URL in `keploy-config.json`, setting it to an empty string. This change may be part of a broader update to the configuration management or a temporary adjustment for testing purposes. Signed-off-by: Sky Singh --- keploy-github-app-beta/keploy-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keploy-github-app-beta/keploy-config.json b/keploy-github-app-beta/keploy-config.json index fa4d342..609581b 100644 --- a/keploy-github-app-beta/keploy-config.json +++ b/keploy-github-app-beta/keploy-config.json @@ -1,5 +1,5 @@ { "useCase": "Documentation", - "apiEndpoint": "https://xyz/api/generate", + "apiEndpoint": "", "selectedModel": "llama2" } \ No newline at end of file From de71c91772332eb2ce9a526e60ec4b7823f22666 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Sun, 16 Mar 2025 17:07:07 +0530 Subject: [PATCH 17/29] fix: clear selected model in configuration - Removed the previously set model "llama2" in `keploy-config.json`, leaving the selected model as an empty string. This change may be part of a configuration reset or adjustment for future updates. Signed-off-by: Sky Singh --- keploy-github-app-beta/keploy-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keploy-github-app-beta/keploy-config.json b/keploy-github-app-beta/keploy-config.json index 609581b..aa8a96b 100644 --- a/keploy-github-app-beta/keploy-config.json +++ b/keploy-github-app-beta/keploy-config.json @@ -1,5 +1,5 @@ { "useCase": "Documentation", "apiEndpoint": "", - "selectedModel": "llama2" + "selectedModel": "" } \ No newline at end of file From 7628857309652ea758412ed3eb4e41a77c56253a Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 17:01:30 +0530 Subject: [PATCH 18/29] refactor: remove unnecessary comment from types.ts - Removed the comment regarding GitHub API related types in `types.ts` to streamline the code and improve clarity. Signed-off-by: Sky Singh --- keploy-github-app-beta/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/keploy-github-app-beta/types.ts b/keploy-github-app-beta/types.ts index 738be27..dab8ec6 100644 --- a/keploy-github-app-beta/types.ts +++ b/keploy-github-app-beta/types.ts @@ -1,4 +1,3 @@ -// GitHub API related types export interface Repository { name: string; owner: string; From e8f9aec31de3c6ef8b3148a8fead1d08d374ac1d Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 17:06:45 +0530 Subject: [PATCH 19/29] refactor: remove unnecessary comment from pr.ts - Removed a comment regarding core data collection functions in `pr.ts` to improve code clarity and maintainability. Signed-off-by: Sky Singh --- keploy-github-app-beta/pr.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 7404f84..2c44a7d 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -1,4 +1,3 @@ -// Core data collection functions import { App, GithubContext, From fd313b92e126d96dd120b883ad79045903bf014f Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 17:12:08 +0530 Subject: [PATCH 20/29] chore: add comment for core data collection functions in pr.ts - Introduced a comment at the beginning of `pr.ts` to clarify the purpose of the core data collection functions, enhancing code readability and maintainability. Signed-off-by: Sky Singh --- keploy-github-app-beta/pr.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 2c44a7d..7404f84 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -1,3 +1,4 @@ +// Core data collection functions import { App, GithubContext, From 27192ee278b861c9d31c9dfb2683cba04dd3873c Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 17:17:34 +0530 Subject: [PATCH 21/29] feat: add CI workflows for testing, linting, and security scanning - Introduced three new GitHub Actions workflows: `keploy.yaml` for running tests with Keploy, `lint.yaml` for code linting across multiple languages, and `security.yaml` for performing security scans using Trivy. - Each workflow is triggered on pull requests to the main branch and supports manual execution. - The workflows include steps for setting up the environment, running tests or analysis, and commenting results on the pull request. These additions enhance the CI/CD pipeline by ensuring code quality, security, and functionality before merging changes. Signed-off-by: Sky Singh --- .github/workflows/keploy.yaml | 106 +++++++++++++++++++++++++ .github/workflows/lint.yaml | 134 ++++++++++++++++++++++++++++++++ .github/workflows/security.yaml | 57 ++++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 .github/workflows/keploy.yaml create mode 100644 .github/workflows/lint.yaml create mode 100644 .github/workflows/security.yaml diff --git a/.github/workflows/keploy.yaml b/.github/workflows/keploy.yaml new file mode 100644 index 0000000..1f79ead --- /dev/null +++ b/.github/workflows/keploy.yaml @@ -0,0 +1,106 @@ +name: Keploy Test Runner + +on: + pull_request: + branches: [ main ] + workflow_dispatch: + inputs: + command: + description: 'Command to run the application' + required: true + working-directory: + description: 'Working directory' + required: true + default: '.' + delay: + description: 'Startup delay' + required: true + default: '10' + keploy-path: + description: 'Path to keploy' + required: true + default: './' + container-name: + description: 'Container name for docker compose' + required: false + build-delay: + description: 'Docker build delay' + default: '50s' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Go + if: contains(inputs.command, 'go') + uses: actions/setup-go@v4 + with: + go-version: '1.21' + + - name: Setup Node.js + if: contains(inputs.command, 'node') + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Setup Java + if: contains(inputs.command, 'java') || contains(inputs.command, 'mvn') + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Python + if: contains(inputs.command, 'python') + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Keploy + shell: bash + run: | + curl --silent --location "https://github.com/keploy/keploy/releases/latest/download/keploy_linux_amd64.tar.gz" | tar xz -C /tmp + sudo mv /tmp/keploy /usr/local/bin/keploy + chmod +x /usr/local/bin/keploy + + - name: Run Tests + id: keploy-test + shell: bash + env: + COMMAND: ${{ github.event.inputs.command }} + WORKING_DIR: ${{ github.event.inputs.working-directory }} + DELAY: ${{ github.event.inputs.delay }} + KEPLOY_PATH: ${{ github.event.inputs.keploy-path }} + CONTAINER_NAME: ${{ github.event.inputs.container-name }} + BUILD_DELAY: ${{ github.event.inputs.build-delay }} + run: | + cd "$WORKING_DIR" + go mod download + sudo -E keploy test -c "go run main.go" --delay "10" --path "." + grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total tests: [0-9]+" report.txt | sed -r "s/\x1B\[[0-9;]*[mGK]//g" > final_total_tests.out + grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total test passed: [0-9]+" report.txt | sed -r "s/\x1B\[[0-9;]*[mGK]//g" > final_total_passed.out + grep -oE "COMPLETE TESTRUN SUMMARY\.\s+Total test failed: [0-9]+" report.txt | sed -r "s/\x1B\[[0-9;]*[mGK]//g" > final_total_failed.out + + echo 'KEPLOY_REPORT<> $GITHUB_OUTPUT + cat final_total_tests.out final_total_passed.out final_total_failed.out >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT + + - name: Comment PR + if: success() + uses: actions/github-script@v6 + env: + KEPLOY_REPORT: ${{ steps.keploy-test.outputs.KEPLOY_REPORT }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + if (!process.env.KEPLOY_REPORT) { + throw new Error('KEPLOY_REPORT not found'); + } + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: process.env.KEPLOY_REPORT + }); \ No newline at end of file diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..317e138 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,134 @@ +name: Lint Workflow + +on: + workflow_dispatch: + pull_request: + branches: + - main +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up environment variables + run: echo "WORKDIR=${{ github.workspace }}/${{ inputs.working-directory }}" >> $GITHUB_ENV + + - name: Detect languages + id: language-detection + shell: bash + run: | + declare -A extensions=( + ["go"]="go" + ["js"]="javascript" + ["ts"]="javascript" + ["py"]="python" + ["java"]="java" + ) + + LANGUAGES="" + + # Find all files in the repository and extract unique file extensions + for file in $(find . -type f); do + echo $file + ext="${file##*.}" + if [[ -n "${extensions[$ext]}" ]]; then + LANGUAGES+="${extensions[$ext]} " + fi + done + + # Get unique languages + UNIQUE_LANGS=$(echo "$LANGUAGES" | tr ' ' '\n' | sort -u | tr '\n' ' ') + echo "languages=$UNIQUE_LANGS" >> $GITHUB_ENV + + - name: Install analysis tools + shell: bash + run: | + for lang in ${{ env.languages }}; do + case "$lang" in + go) + go install golang.org/x/lint/golint@latest + ;; + javascript) + npm install -g eslint + ;; + python) + pip install flake8 + ;; + esac + done + + - name: Run Code Analysis + shell: bash + run: | + mkdir -p analysis-reports + cd $WORKDIR + + for lang in ${{ env.languages }}; do + echo $lang + case "$lang" in + go) + golangci-lint run --out-format=github-actions ./... > analysis-reports/go-lint.txt || true + ;; + javascript) + eslint . --format junit -o analysis-reports/js-lint.xml || true + ;; + python) + which flake8 || pip install flake8 + + flake8 . --output-file=analysis-reports/py-lint.txt || true + ;; + esac + done + + - name: Combine Analysis Reports + shell: bash + run: | + mkdir -p analysis-reports + temp_file=$(mktemp) # Temporary file to avoid 'input file is output file' issue + + for report in analysis-reports/*; do + if [ -f "$report" ]; then + echo "### $(basename "$report")" >> "$temp_file" + cat "$report" >> "$temp_file" + echo -e "\n---\n" >> "$temp_file" + fi + done + + mv "$temp_file" analysis-reports/final-report.txt + + - name: Upload Final Report as Artifact + uses: actions/upload-artifact@v4 + with: + name: TestGPT-Analysis-Report + path: analysis-reports/final-report.txt + if-no-files-found: warn + + - name: Read Full Lint Report + id: read_report + run: | + { + echo "REPORT<> "$GITHUB_ENV" + + - name: Comment Full Lint Report on PR + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + ## 🔍 Lint Scan Results + ``` + ${{ env.REPORT }} + ``` + token: ${{ secrets.GITHUB_TOKEN }} + + diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml new file mode 100644 index 0000000..8996f0d --- /dev/null +++ b/.github/workflows/security.yaml @@ -0,0 +1,57 @@ +name: Security Scan with Trivy + +on: + workflow_dispatch: + pull_request: + branches: + - main + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + security-scan: + name: Run Trivy Security Scan + runs-on: ubuntu-latest + + steps: + - name: Checkout PR Code + uses: actions/checkout@v4 + + - name: Run Trivy Scan + uses: aquasecurity/trivy-action@master + env: + TRIVY_DISABLE_VEX_NOTICE: true + with: + scan-type: "fs" + format: "table" + ignore-unfixed: true + output: trivy_report.txt + + - name: Upload Trivy Report as Artifact + uses: actions/upload-artifact@v4 + with: + name: trivy-security-report + path: trivy_report.txt + + - name: Read Full Trivy Report + id: read_report + run: | + { + echo "REPORT<> "$GITHUB_ENV" + + - name: Comment Full Trivy Report on PR + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + ## 🔍 Trivy Security Scan Results + ``` + ${{ env.REPORT }} + ``` + token: ${{ secrets.GITHUB_TOKEN }} From ce2c164858e4f6379fe4ef5dff9d59647040ba88 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 17:19:42 +0530 Subject: [PATCH 22/29] refactor: update logging for LLM output in PR analysis - Modified the logging of the LLM output in `index.ts` to ensure the output is properly stringified before logging. This change enhances the clarity of the logged information during the PR analysis process. Signed-off-by: Sky Singh --- keploy-github-app-beta/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts index 780283a..19a08aa 100644 --- a/keploy-github-app-beta/index.ts +++ b/keploy-github-app-beta/index.ts @@ -40,8 +40,8 @@ export default async (app: App) => { app.log.info("Full PR data collected", { prData: JSON.stringify(prData) }); const llmOutput = await handlePrAnalysis(context, prData , config.apiEndpoint , config.selectedModel, app); - // const stringllmOutput = await JSON.stringify(llmOutput); - // app.log.info(JSON.stringify(stringllmOutput), "LLM analysis complete"); + const stringllmOutput = await JSON.stringify(llmOutput); + app.log.info(JSON.stringify(stringllmOutput)); await reviewPR(context as any, app, llmOutput); // await reviewPR(context, app); From 76fc8aeaaee9147a1e6ba20c1b33fd67d0dca12f Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 17:30:25 +0530 Subject: [PATCH 23/29] feat: add README for Keploy Github App - Introduced a comprehensive README.md for the Keploy Github App, detailing its features, setup instructions, usage guidelines, and contribution process. This documentation aims to enhance user understanding and facilitate easier onboarding for new contributors. Signed-off-by: Sky Singh --- keploy-github-app-beta/README.md | 168 +++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 keploy-github-app-beta/README.md diff --git a/keploy-github-app-beta/README.md b/keploy-github-app-beta/README.md new file mode 100644 index 0000000..d4944f2 --- /dev/null +++ b/keploy-github-app-beta/README.md @@ -0,0 +1,168 @@ +# Keploy Github App + +**Streamline your code reviews with flexible, AI-powered analysis** + +Keploy Github App is an open-source, self-hosted AI tool designed to automate and enhance reviews of code, documentation, and more. It empowers teams to enforce standards, streamline workflows, and improve security without vendor lock-in or hidden costs. Choose any language model (LLM), including self-hosted ones via Ollama or open-source alternatives. + +## 🌟 Key Features + +### 1️⃣ **Customizable Review Rules** +- Define your team's standards in a `RULES.md`, YAML, or JSON file +- Enforce coding standards, documentation guidelines, and security best practices +- Automatically flag inconsistencies like mixed naming conventions or inadequate error handling + +### 2️⃣ **Static Analysis + AI-Powered Review** +- Combines traditional static analysis with advanced AI reasoning +- Analyzes PRs based on your custom rule set +- Highlights style, security, and architectural concerns +- Provides actionable improvement suggestions + +### 3️⃣ **Flexible LLM Integration** +- Choose the best model for your specific use case: + - For code reviews: Models like OpenAI Codex or Mistral + - For documentation: Models better suited for writing, such as GPT-4 or Claude +- Supports both open-source and commercial LLMs +- Configure via `keploy-config.json` file + +### 4️⃣ **GitHub Integration** +- Automatically reviews pull requests when opened or updated +- Provides inline comments directly in your PRs +- Works with your existing GitHub workflow + +## 🚀 Setup Instructions + +### Prerequisites +- Node.js v18 or higher +- npm or yarn +- GitHub account and repository (for GitHub integration) + +### Installation + +1. **Clone the repository and checkout the branch** + ```bash + git clone https://github.com/SkySingh04/testGPT.git + git fetch + git checkout github-app-pr + cd keploy-github-app-beta + ``` + +2. **Install dependencies** + ```bash + npm install + ``` + +3. **Configure the app** + Run the CLI configuration tool to set up the app for your use case: + ```bash + npm run dev + ``` + + This will prompt you to select: + - Your use case (code review, documentation review, etc.) + - API endpoint for your LLM + - Preferred language model + + Alternatively, you can manually create a `keploy-config.json` file in the project root: + ```json + { + "useCase": "Code Review", + "apiEndpoint": "YOUR_LLM_API_ENDPOINT", + "selectedModel": "YOUR_PREFERRED_MODEL" + } + ``` + +4. **Setup GitHub App (for GitHub integration)** + + - Create a new GitHub App in your GitHub account + - Set the following permissions: + - Pull requests: Read & Write + - Repository contents: Read + - Subscribe to pull request events + - Generate and download a private key + - Install the app on your repositories + - Configure environment variables (create a `.env` file): + ``` + APP_ID=your_github_app_id + PRIVATE_KEY=your_github_app_private_key + WEBHOOK_SECRET=your_webhook_secret + ``` + +5. **Start Keploy Github App** + ```bash + npm start + ``` + +## 📋 Usage + +### Define Review Rules +Create a `RULES.md` file in your repository with your team's standards: + +```markdown +# Code Review Rules + +## Naming Conventions +- Use camelCase for variables and functions +- Use PascalCase for classes and interfaces + +## Error Handling +- All errors must be properly caught and logged +- No empty catch blocks allowed + +## Documentation +- All public functions must have JSDoc comments +- Include examples for complex functions +``` + +### Running Keploy Github App Locally +To review code locally before committing: + +```bash +npm run start +``` + +### GitHub Integration +Once configured, Keploy Github App will automatically: +1. Monitor pull requests in repositories where the GitHub App is installed +2. Analyze the code changes against your defined rules +3. Provide feedback as comments directly in the PR + +## 🔧 Advanced Configuration + +### Custom LLM Configuration +For using specific LLMs, update your `keploy-config.json`: + +```json +{ + "useCase": "Security Review", + "apiEndpoint": "https://api.openai.com/v1/chat/completions", + "selectedModel": "gpt-4" +} +``` + +## 👥 Contributing + +We welcome contributions from the community! Please check our [CONTRIBUTING.md](./CONTRIBUTING.md) guide for: + +1. **Development Setup** + - Fork and clone the repository + - Install dependencies: `npm install` + - Start the development server: `npm run start` + +2. **Coding Standards** + - Use TypeScript for all new code + - Follow the existing code style + - Add comments for complex logic + - Include tests for new features + +3. **Pull Request Process** + - Create a branch for your changes + - Make your changes and commit them + - Write clear commit messages + - Update documentation if needed + - Submit a PR with a description of your changes + +Looking for something to work on? Check out our good first issues - these are perfect for getting started! + +### DEMO VIDEO : + +https://github.com/user-attachments/assets/8ee879b8-3200-41bd-a015-674db3e13534 From b0d8d329bca71154d00e71fa6cc44f859f28f94f Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 18:05:18 +0530 Subject: [PATCH 24/29] feat: update JavaScript linting configuration - Modified the JavaScript linting step in `lint.yaml` to use a custom ESLint configuration file located at `keploy-github-app-beta/eslint.config.js`. This change allows for more tailored linting rules and ignores specific directories. - Added a new ESLint configuration file that specifies rules for JavaScript files, including warnings for unused variables and console statements, and enforcing semicolons. Signed-off-by: Sky Singh --- .github/workflows/lint.yaml | 2 +- keploy-github-app-beta/eslint.config.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 keploy-github-app-beta/eslint.config.js diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 317e138..c2846da 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -78,7 +78,7 @@ jobs: golangci-lint run --out-format=github-actions ./... > analysis-reports/go-lint.txt || true ;; javascript) - eslint . --format junit -o analysis-reports/js-lint.xml || true + eslint . --config keploy-github-app-beta/eslint.config.js --format junit -o analysis-reports/js-lint.xml || true ;; python) which flake8 || pip install flake8 diff --git a/keploy-github-app-beta/eslint.config.js b/keploy-github-app-beta/eslint.config.js new file mode 100644 index 0000000..3fb87b9 --- /dev/null +++ b/keploy-github-app-beta/eslint.config.js @@ -0,0 +1,13 @@ +export default [ + { + ignores: ["node_modules/**", "dist/**"], + }, + { + files: ["**/*.js", "**/*.mjs"], + rules: { + "no-unused-vars": "warn", + "no-console": "warn", + "semi": "error" + } + } +]; From 0a1126c91a08d0922630e7dd8a41a8fe0d8d3e3f Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 18:06:44 +0530 Subject: [PATCH 25/29] feat: add ESLint formatter for improved reporting - Added the `eslint-formatter-junit` package to the JavaScript linting step in `lint.yaml`. This formatter will enhance the output of ESLint results, making it easier to integrate with CI tools and improve reporting capabilities. Signed-off-by: Sky Singh --- .github/workflows/lint.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index c2846da..e221ead 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -58,6 +58,7 @@ jobs: ;; javascript) npm install -g eslint + npm install -D eslint-formatter-junit ;; python) pip install flake8 From 0f3a9a00d404df412972bde55c5c2b8f67b0a937 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Thu, 20 Mar 2025 18:11:40 +0530 Subject: [PATCH 26/29] feat: add whitespace for improved code formatting - Introduced a blank line at the beginning of `keploy.ts` to enhance code readability and maintain consistency with formatting standards. Signed-off-by: Sky Singh --- keploy-github-app-beta/keploy.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/keploy-github-app-beta/keploy.ts b/keploy-github-app-beta/keploy.ts index 50190c4..2fc9021 100644 --- a/keploy-github-app-beta/keploy.ts +++ b/keploy-github-app-beta/keploy.ts @@ -1,5 +1,6 @@ import { GithubContext } from './types.js'; + export async function handleKeployWorkflowTrigger(context: GithubContext) { const { owner, repo } = context.repo(); const ref = context.payload.pull_request.head.ref; From 5f0f1ede8526c0ef67d2429d6b62c7c15b45aacf Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Fri, 21 Mar 2025 20:20:43 +0530 Subject: [PATCH 27/29] feat: enhance error logging across the application - Introduced a new utility function `logError` in `utils.ts` to standardize error logging with full stack traces. - Updated various modules (`diffparser.ts`, `index.ts`, `keploy.ts`, `lint.ts`, `llm.ts`, `pr.ts`, `security.ts`, `src/addLabel.ts`, `src/config/userConfig.ts`) to utilize the new logging function, improving consistency and clarity in error reporting. Signed-off-by: Sky Singh --- keploy-github-app-beta/diffparser.ts | 11 +----- keploy-github-app-beta/errors.ts | 13 +++++++ keploy-github-app-beta/index.ts | 3 +- keploy-github-app-beta/keploy.ts | 3 +- keploy-github-app-beta/lint.ts | 11 +++--- keploy-github-app-beta/llm.ts | 3 +- keploy-github-app-beta/pr.ts | 1 + keploy-github-app-beta/security.ts | 3 +- keploy-github-app-beta/src/addLabel.ts | 24 +++++++++++- .../src/config/userConfig.ts | 37 +++++++++++++++++-- keploy-github-app-beta/utils.ts | 27 ++++++++++++++ 11 files changed, 114 insertions(+), 22 deletions(-) diff --git a/keploy-github-app-beta/diffparser.ts b/keploy-github-app-beta/diffparser.ts index 36bf0e3..34e07fa 100644 --- a/keploy-github-app-beta/diffparser.ts +++ b/keploy-github-app-beta/diffparser.ts @@ -1,5 +1,6 @@ // diffParser.ts import parseDiff, { File, Chunk, Change } from 'parse-diff'; +import { logError } from './utils.js'; interface Repository { owner: { @@ -162,15 +163,7 @@ export async function createInlineCommentsFromDiff(diff: string, context: GitHub }); app.log.info(`Created comment on ${filePath} line ${line}`); } catch (error) { - if (error instanceof Error) { - app.log.error( - `Failed to create comment for ${filePath} line ${line}: ${error.message}` - ); - } else { - app.log.error( - `Failed to create comment for ${filePath} line ${line}: Unknown error` - ); - } + logError(`Failed to create comment for ${filePath} line ${line}:`, error); } } } diff --git a/keploy-github-app-beta/errors.ts b/keploy-github-app-beta/errors.ts index cc99ab6..16b95d5 100644 --- a/keploy-github-app-beta/errors.ts +++ b/keploy-github-app-beta/errors.ts @@ -27,6 +27,11 @@ export class AppError extends Error { if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } + + // Append the cause's stack to this error's stack if available + if (this.cause instanceof Error && this.cause.stack) { + this.stack = this.stack ? `${this.stack}\nCaused by: ${this.cause.stack}` : this.cause.stack; + } } /** @@ -42,6 +47,14 @@ export class AppError extends Error { public toUserFriendlyMessage(): string { return this.message; } + + /** + * Returns the full error stack including nested causes + */ + public getFullStack(): string { + if (!this.stack) return this.message; + return this.stack; + } } /** diff --git a/keploy-github-app-beta/index.ts b/keploy-github-app-beta/index.ts index 19a08aa..7644c9c 100644 --- a/keploy-github-app-beta/index.ts +++ b/keploy-github-app-beta/index.ts @@ -8,7 +8,7 @@ import { getAllPrDetails } from "./pr.js"; import { handlePrAnalysis } from "./llm.js"; import { handleKeployWorkflowTrigger } from "./keploy.js"; -import { handleError } from "./utils.js"; +import { handleError, logError } from "./utils.js"; import { handleSecurityWorkflowTrigger } from "./security.js"; import { promptUserConfig } from './src/cli.js'; import { reviewPR } from './diffparser.js'; @@ -70,6 +70,7 @@ export default async (app: App) => { handleLintWorkflowTrigger(context) ]); } catch (error) { + logError('Error processing PR event:', error); await handleError(context, app, error); } }; diff --git a/keploy-github-app-beta/keploy.ts b/keploy-github-app-beta/keploy.ts index 2fc9021..cc9abf2 100644 --- a/keploy-github-app-beta/keploy.ts +++ b/keploy-github-app-beta/keploy.ts @@ -1,4 +1,5 @@ import { GithubContext } from './types.js'; +import { logError } from './utils.js'; export async function handleKeployWorkflowTrigger(context: GithubContext) { @@ -30,7 +31,7 @@ export async function handleKeployWorkflowTrigger(context: GithubContext) { commentBody = `⚠️ Failed to run Keploy Tests: ${errorMessage}${statusCode}`; } - console.error('Keploy workflow error:', error); + logError('Keploy workflow error:', error); await context.octokit.issues.createComment({ ...context.repo(), diff --git a/keploy-github-app-beta/lint.ts b/keploy-github-app-beta/lint.ts index c7e9688..d007591 100644 --- a/keploy-github-app-beta/lint.ts +++ b/keploy-github-app-beta/lint.ts @@ -1,4 +1,5 @@ import { GithubContext } from './types.js'; +import { logError } from './utils.js'; export async function handleLintWorkflowTrigger(context: GithubContext) { const { owner, repo } = context.repo(); @@ -20,16 +21,16 @@ export async function handleLintWorkflowTrigger(context: GithubContext) { let commentBody: string; if (errorObj.status === 404) { - commentBody = 'Lint workflow failed: Workflow file not found or inaccessible'; + commentBody = 'Failed to run linting: Workflow file not found or inaccessible'; } else if (errorObj.status === 403) { - commentBody = 'Lint workflow failed: Permission denied to access or trigger workflow'; + commentBody = 'Failed to run linting: Permission denied to access or trigger workflow'; } else if (errorObj.status === 422) { - commentBody = 'Lint workflow failed: Request validation failed, please check workflow configuration'; + commentBody = 'Failed to run linting: Request validation failed, please check workflow configuration'; } else { - commentBody = `Lint workflow failed: ${errorMessage}${statusCode}`; + commentBody = `Failed to run linting: ${errorMessage}${statusCode}`; } - console.error('Lint workflow error:', error); + logError('Lint workflow error:', error); await context.octokit.issues.createComment({ ...context.repo(), diff --git a/keploy-github-app-beta/llm.ts b/keploy-github-app-beta/llm.ts index ea25e66..89b689f 100644 --- a/keploy-github-app-beta/llm.ts +++ b/keploy-github-app-beta/llm.ts @@ -4,6 +4,7 @@ import { loadConfig } from './src/config/userConfig.js'; import { useCaseModels } from './src/config/models.js'; import { determineLabelFromAnalysis, addLabelToPR } from './src/addLabel.js'; import { App, GithubContext, PRData, IssueComment, Config } from './types.js'; +import { logError } from './utils.js'; // import { createInlineCommentsFromDiff } from './diffparser.js'; export async function handlePrAnalysis( @@ -277,7 +278,7 @@ LGTM! // Assuming the response data contains a 'generated_text' field with the analysis return response.data.generated_text || response.data; } catch (error) { - app.log.error('Error calling LLM API:', error); + logError('Error in LLM processing:', error); return `Error analyzing PR: ${error instanceof Error ? error.message : 'Unknown error'}`; } } diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 7404f84..5f8598f 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -11,6 +11,7 @@ import { LinkedIssues, PatchResult } from './types.js'; +import { logError } from './utils.js'; // Define a local ApiError class class ApiError extends Error { diff --git a/keploy-github-app-beta/security.ts b/keploy-github-app-beta/security.ts index 67e6e14..591cfb9 100644 --- a/keploy-github-app-beta/security.ts +++ b/keploy-github-app-beta/security.ts @@ -1,4 +1,5 @@ import { GithubContext } from './types.js'; +import { logError } from './utils.js'; export async function handleSecurityWorkflowTrigger(context: GithubContext) { const { owner, repo } = context.repo(); @@ -35,7 +36,7 @@ export async function handleSecurityWorkflowTrigger(context: GithubContext) { commentBody = `Failed to run security check: ${errorMessage}${statusCode}`; } - console.error('Security workflow error:', error); + logError('Security workflow error:', error); await context.octokit.issues.createComment({ ...context.repo(), diff --git a/keploy-github-app-beta/src/addLabel.ts b/keploy-github-app-beta/src/addLabel.ts index afe73e6..cc42525 100644 --- a/keploy-github-app-beta/src/addLabel.ts +++ b/keploy-github-app-beta/src/addLabel.ts @@ -45,6 +45,28 @@ function isValidShortResponse(response: string): boolean { return validShortResponses.some(valid => response.includes(valid)); } +/** + * Utility function to log errors with full stack traces + * @param message Custom error message + * @param error The error object + */ +function logError(message: string, error: unknown): void { + console.error(message); + + if (error instanceof Error) { + console.error('Error details:', error); + console.error('Stack trace:', error.stack); + + // If it's an error with a cause, log the cause stack too + if ('cause' in error && error.cause instanceof Error) { + console.error('Caused by:', error.cause); + console.error('Cause stack trace:', error.cause.stack); + } + } else { + console.error('Unknown error type:', error); + } +} + export async function addLabelToPR( context: GithubContext, prNumber: number, @@ -74,7 +96,7 @@ export async function addLabelToPR( return true; } catch (error) { - console.error('Error adding label:', error); + logError('Error adding label:', error); return false; } } diff --git a/keploy-github-app-beta/src/config/userConfig.ts b/keploy-github-app-beta/src/config/userConfig.ts index 25a9587..fdebbb1 100644 --- a/keploy-github-app-beta/src/config/userConfig.ts +++ b/keploy-github-app-beta/src/config/userConfig.ts @@ -1,10 +1,19 @@ -import fs from 'fs'; +import * as fs from 'fs'; // Define local error types for this file class ConfigFileError extends Error { constructor(message: string, public readonly cause?: unknown) { super(message); this.name = this.constructor.name; + // Maintain proper stack trace in Node.js + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + + // Append the cause's stack to this error's stack if available + if (this.cause instanceof Error && this.cause.stack) { + this.stack = this.stack ? `${this.stack}\nCaused by: ${this.cause.stack}` : this.cause.stack; + } } } @@ -44,6 +53,28 @@ export interface UserConfig { const CONFIG_FILE = 'keploy-config.json'; +/** + * Utility function to log errors with full stack traces + * @param message Custom error message + * @param error The error object + */ +function logError(message: string, error: unknown): void { + console.error(message); + + if (error instanceof Error) { + console.error('Error details:', error); + console.error('Stack trace:', error.stack); + + // If it's our custom error with a cause, log the cause stack too + if ('cause' in error && error.cause instanceof Error) { + console.error('Caused by:', error.cause); + console.error('Cause stack trace:', error.cause.stack); + } + } else { + console.error('Unknown error type:', error); + } +} + export function saveConfig(config: UserConfig): Result { try { fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); @@ -60,7 +91,7 @@ export function saveConfig(config: UserConfig): Result { appError = new ConfigError(`Failed to save configuration: ${errorObj.message || 'Unknown error'}`, error); } - console.error(appError.message, error); + logError(appError.message, error); return { success: false, error: appError }; } } @@ -90,7 +121,7 @@ export function loadConfig(): Result { appError = new ConfigError(`Error loading config: ${errorMessage}`, error); } - console.error(appError.message, error); + logError(appError.message, error); return { success: false, error: appError }; } } diff --git a/keploy-github-app-beta/utils.ts b/keploy-github-app-beta/utils.ts index 3590027..26828dd 100644 --- a/keploy-github-app-beta/utils.ts +++ b/keploy-github-app-beta/utils.ts @@ -35,3 +35,30 @@ Please check the application logs for more details.` app.log.error('Failed to post error comment:', commentError); } } + +/** + * Utility function to log errors with full stack traces + * @param message Custom error message + * @param error The error object + */ +export function logError(message: string, error: unknown): void { + console.error(message); + + if (error instanceof Error) { + console.error('Error details:', error); + console.error('Stack trace:', error.stack); + + // If it's our custom AppError with a cause, log the cause stack too + if ('cause' in error && error.cause instanceof Error) { + console.error('Caused by:', error.cause); + console.error('Cause stack trace:', error.cause.stack); + } + + // If our custom AppError has getFullStack method, use it + if ('getFullStack' in error && typeof (error as any).getFullStack === 'function') { + console.error('Full stack trace:', (error as any).getFullStack()); + } + } else { + console.error('Unknown error type:', error); + } +} From 29f7c3ab5484ca8ead411db49f01ba0bfc5a7772 Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Fri, 21 Mar 2025 20:36:50 +0530 Subject: [PATCH 28/29] feat: improve data handling and type safety in PR and types files - Updated `getLinkedIssueData` in `pr.ts` to handle optional fields for issue body and author, ensuring defaults are set for missing data. - Enhanced label and assignee processing to check for array types, providing fallback values for better robustness. - Refactored `GithubContext` in `types.ts` to utilize `ProbotOctokit` for improved type safety and clarity in GitHub API interactions. Signed-off-by: Sky Singh --- keploy-github-app-beta/pr.ts | 18 +++++++++++------- keploy-github-app-beta/types.ts | 28 ++++------------------------ 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/keploy-github-app-beta/pr.ts b/keploy-github-app-beta/pr.ts index 5f8598f..cd9e4e0 100644 --- a/keploy-github-app-beta/pr.ts +++ b/keploy-github-app-beta/pr.ts @@ -121,13 +121,17 @@ async function getLinkedIssueData(context: GithubContext, app: App, owner: strin return { number: issueNumber, title: issue.data.title, - body: issue.data.body, + body: issue.data.body ?? null, state: issue.data.state, - author: issue.data.user.login, + author: issue.data.user?.login || 'unknown', created_at: issue.data.created_at, updated_at: issue.data.updated_at, - labels: issue.data.labels.map((l: { name: string }) => l.name), - assignees: issue.data.assignees.map((a: { login: string }) => a.login), + labels: Array.isArray(issue.data.labels) + ? issue.data.labels.map((l: any) => typeof l === 'string' ? l : (l.name || '')) + : [], + assignees: Array.isArray(issue.data.assignees) + ? issue.data.assignees.map((a: any) => a.login || '') + : [], comments: comments.map((c) => { const comment = c as { user: { login: string }, body: string, created_at: string }; return { @@ -396,13 +400,13 @@ async function getRepositoryContext(context: GithubContext, app: App) { owner, repo, tree_sha: 'HEAD', - recursive: true + recursive: 'true' }) ]); const folderStructure = repoStructure.data.tree - .filter((item: { path: string }) => !item.path.includes('node_modules/')) // Exclude node_modules - .map((item: { path: string }) => item.path) + .filter((item: any) => item.path && !item.path.includes('node_modules/')) + .map((item: any) => item.path || '') .join('\n'); // Convert ReadmeResponse to string for compatibility with Repository type diff --git a/keploy-github-app-beta/types.ts b/keploy-github-app-beta/types.ts index dab8ec6..a4a70ca 100644 --- a/keploy-github-app-beta/types.ts +++ b/keploy-github-app-beta/types.ts @@ -1,3 +1,6 @@ +// For better type safety with Octokit +import type { ProbotOctokit } from 'probot/lib/octokit/probot-octokit.js'; + export interface Repository { name: string; owner: string; @@ -298,30 +301,7 @@ export interface ListReviewCommentsParams { // GitHub context types export interface GithubContext { - octokit: { - issues: { - createComment: (params: CreateCommentParams) => Promise<{ data: CommentResponse }>; - get: (params: GetIssueParams) => Promise<{ data: IssueResponse }>; - listComments: (params: ListCommentsParams) => Promise<{ data: CommentResponse[] }>; - removeLabel: (params: RemoveLabelParams) => Promise; - addLabels: (params: AddLabelsParams) => Promise<{ data: Label[] }>; - }; - pulls: { - listFiles: (params: ListFilesParams) => Promise<{ data: FileChange[] }>; - listReviewComments: (params: ListReviewCommentsParams) => Promise<{ data: Comment[] }>; - }; - repos: { - getReadme: (params: GetReadmeParams) => Promise<{ data: ReadmeResponse }>; - getContent: (params: GetContentParams) => Promise<{ data: ContentResponse }>; - }; - actions: { - createWorkflowDispatch: (params: CreateWorkflowDispatchParams) => Promise; - }; - git: { - getTree: (params: GetTreeParams) => Promise<{ data: TreeResponse }>; - }; - paginate: (method: Function, params: object) => Promise; - }; + octokit: ProbotOctokit; repo: () => { owner: string; repo: string }; payload: { pull_request: PullRequest; From 6c0de73966ba85bcccd1729febeafc898414eb5a Mon Sep 17 00:00:00 2001 From: Sky Singh Date: Fri, 21 Mar 2025 20:39:45 +0530 Subject: [PATCH 29/29] feat: enhance type safety and structure in diffparser.ts - Renamed the file to follow consistent casing conventions. - Introduced `ProbotOctokit` type in the `GitHubContext` interface for improved type safety. - Refactored the `GitHubContext` structure to include detailed payload information for better clarity in GitHub API interactions. Signed-off-by: Sky Singh --- keploy-github-app-beta/diffparser.ts | 38 ++++++++++++++++------------ 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/keploy-github-app-beta/diffparser.ts b/keploy-github-app-beta/diffparser.ts index 34e07fa..ea44671 100644 --- a/keploy-github-app-beta/diffparser.ts +++ b/keploy-github-app-beta/diffparser.ts @@ -1,6 +1,8 @@ -// diffParser.ts +// diffparser.ts import parseDiff, { File, Chunk, Change } from 'parse-diff'; import { logError } from './utils.js'; +import type { ProbotOctokit } from 'probot/lib/octokit/probot-octokit.js'; +import { App } from './types.js'; interface Repository { owner: { @@ -41,21 +43,6 @@ interface ReviewCommentParams { }; } -interface GitHubContext { - octokit: { - issues: { - createComment: (params: IssueCommentParams) => Promise; - }; - pulls: { - createReviewComment: (params: ReviewCommentParams) => Promise; - listFiles: (params: { owner: string; repo: string; pull_number: number }) => Promise<{ data: any[] }>; - listReviewComments: (params: { owner: string; repo: string; pull_number: number }) => Promise<{ data: any[] }>; - }; - }; - repo: () => { owner: string; repo: string }; - payload: GitHubPayload; -} - interface ProbotyApp { log: { info: (message: string) => void; @@ -63,6 +50,25 @@ interface ProbotyApp { }; } +interface GitHubContext { + octokit: ProbotOctokit; + repo: () => { owner: string; repo: string }; + payload: { + pull_request: { + number: number; + head: { + sha: string; + }; + }; + repository: { + owner: { + login: string; + }; + name: string; + }; + }; +} + async function parseGitDiffFromLLMOutput(llmOutput: string): Promise { // Use regex to find the diff block with exact matching const diffRegex = /```diff([\s\S]*?)```/;