diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..589a402 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,95 @@ +version: 2.1 +defaults: &defaults + docker: + - image: cimg/python:3.13.5-browsers +install_dependency: &install_dependency + name: Installation of build and deployment dependencies. + command: | + pip3 install awscli --upgrade +install_deploysuite: &install_deploysuite + name: Installation of install_deploysuite. + command: | + git clone --branch v1.4.17 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript + cp ./../buildscript/master_deploy.sh . + cp ./../buildscript/buildenv.sh . + cp ./../buildscript/awsconfiguration.sh . + cp ./../buildscript/psvar-processor.sh . + +restore_cache_settings_for_build: &restore_cache_settings_for_build + key: docker-node-modules-{{ checksum "pnpm-lock.yaml" }} + +save_cache_settings: &save_cache_settings + key: docker-node-modules-{{ checksum "pnpm-lock.yaml" }} + paths: + - node_modules + + +builddeploy_steps: &builddeploy_steps +- checkout +- setup_remote_docker +- run: *install_dependency +- run: *install_deploysuite +- restore_cache: *restore_cache_settings_for_build +- run: + name: "Build docker image" + command: | + ./build.sh +- save_cache: *save_cache_settings +- deploy: + name: Running MasterScript. + command: | + ./awsconfiguration.sh $DEPLOY_ENV + source awsenvconf + ./psvar-processor.sh -t appenv -p /config/${APPNAME}/deployvar + source deployvar_env + ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -j /config/${APPNAME}/appvar -i ${APPNAME} -p FARGATE +jobs: + # Build & Deploy against development backend + "build-dev": + !!merge <<: *defaults + environment: + DEPLOY_ENV: "DEV" + LOGICAL_ENV: "dev" + APPNAME: "tc-mcp" + steps: *builddeploy_steps + + "build-qa": + !!merge <<: *defaults + environment: + DEPLOY_ENV: "QA" + LOGICAL_ENV: "qa" + APPNAME: "tc-mcp" + steps: *builddeploy_steps + + "build-prod": + !!merge <<: *defaults + environment: + DEPLOY_ENV: "PROD" + LOGICAL_ENV: "prod" + APPNAME: "tc-mcp" + steps: *builddeploy_steps + +workflows: + version: 2 + build: + jobs: + # Development builds are executed on "develop" branch only. + - "build-dev": + context: org-global + filters: + branches: + only: + - dev + + - "build-qa": + context: org-global + filters: + branches: + only: + - qa + + - "build-prod": + context: org-global + filters: + branches: + only: master diff --git a/.github/workflows/tc_agent.yml b/.github/workflows/tc_agent.yml new file mode 100644 index 0000000..8e9c29d --- /dev/null +++ b/.github/workflows/tc_agent.yml @@ -0,0 +1,24 @@ +name: TC Action Agent - Do It + +on: issue_comment + +jobs: + pr_commented: + # This job only runs for pull request comments + name: '[PR Comment] - Use TC AI Agent' + if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '@tc-ai') }} + runs-on: ubuntu-latest + steps: + - run: | + echo A comment on PR $NUMBER + env: + NUMBER: ${{ github.event.issue.number }} + + tc_agent_tagged_in_issue_comment: + # This job only runs for issue comments where the agent is tagged with @tc-ai + name: '[Issue Comment] - Use TC AI Agent' + if: ${{ !github.event.issue.pull_request && contains(github.event.comment.body, '@tc-ai') }} + runs-on: ubuntu-latest + steps: + - name: Call TC AI Agent + uses: topcoder-platform/tc-action-agent@master \ No newline at end of file diff --git a/README.md b/README.md index 06dcc8f..49d81b4 100644 --- a/README.md +++ b/README.md @@ -1 +1,56 @@ # Topcoder Model Context Protocol (MCP) Server + +## Authentication Based Access via Guards + +Tools/Resources/Prompts support authentication via TC JWT and/or M2M JWT. Providing JWT in the requests to the MCP server will result in specific listings and bahavior based on JWT access level/roles/permissions. + +#### Using `authGuard` - requires TC jwt presence for access + +```ts + @Tool({ + name: 'query-tc-challenges-private', + description: + 'Returns a list of Topcoder challenges based on the query parameters.', + parameters: QUERY_CHALLENGES_TOOL_PARAMETERS, + outputSchema: QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA, + annotations: { + title: 'Query Public Topcoder Challenges', + readOnlyHint: true, + }, + canActivate: authGuard, + }) +``` + +#### Using `checkHasUserRole(Role.Admin)` - TC Role based guard + +```ts + @Tool({ + name: 'query-tc-challenges-protected', + description: + 'Returns a list of Topcoder challenges based on the query parameters.', + parameters: QUERY_CHALLENGES_TOOL_PARAMETERS, + outputSchema: QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA, + annotations: { + title: 'Query Public Topcoder Challenges', + readOnlyHint: true, + }, + canActivate: checkHasUserRole(Role.Admin), + }) +``` + +#### Using `canActivate: checkM2MScope(M2mScope.QueryPublicChallenges)` - M2M based access via scopes + +```ts + @Tool({ + name: 'query-tc-challenges-m2m', + description: + 'Returns a list of Topcoder challenges based on the query parameters.', + parameters: QUERY_CHALLENGES_TOOL_PARAMETERS, + outputSchema: QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA, + annotations: { + title: 'Query Public Topcoder Challenges', + readOnlyHint: true, + }, + canActivate: checkM2MScope(M2mScope.QueryPublicChallenges), + }) +``` diff --git a/build.sh b/build.sh index 048a4bf..c3c0f18 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/bin/bash set -eo pipefail -docker buildx build --no-cache=true -t ${APPNAME}}:latest . \ No newline at end of file +docker buildx build --no-cache=true -t ${APPNAME}:latest . \ No newline at end of file diff --git a/package.json b/package.json index 7f09332..692a379 100644 --- a/package.json +++ b/package.json @@ -24,14 +24,14 @@ "@nestjs/common": "^11.0.1", "@nestjs/core": "^11.0.1", "@nestjs/platform-express": "^11.0.1", - "@rekog/mcp-nest": "^1.6.2", + "@tc/mcp-nest": "topcoder-platform/MCP-Nest.git", + "axios": "^1.10.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "dotenv": "^16.5.0", "json-stringify-safe": "^5.0.1", "jsonwebtoken": "^9.0.2", "jwks-rsa": "^3.2.0", - "nanoid": "^5.1.5", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "zod": "^3.25.67" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f0d218..70a2ae8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@modelcontextprotocol/sdk': specifier: ^1.13.0 - version: 1.13.0 + version: 1.13.3 '@nestjs/common': specifier: ^11.0.1 version: 11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -20,9 +20,12 @@ importers: '@nestjs/platform-express': specifier: ^11.0.1 version: 11.1.3(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3) - '@rekog/mcp-nest': - specifier: ^1.6.2 - version: 1.6.2(@modelcontextprotocol/sdk@1.13.0)(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)(express@5.1.0)(reflect-metadata@0.2.2)(zod-to-json-schema@3.24.5(zod@3.25.67))(zod@3.25.67) + '@tc/mcp-nest': + specifier: topcoder-platform/MCP-Nest.git + version: https://codeload.github.com/topcoder-platform/MCP-Nest/tar.gz/025395f5f3a665e8439e481f84c25c6e6ed97933(@modelcontextprotocol/sdk@1.13.3)(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)(express@5.1.0)(reflect-metadata@0.2.2)(zod-to-json-schema@3.24.6(zod@3.25.71))(zod@3.25.71) + axios: + specifier: ^1.10.0 + version: 1.10.0 class-transformer: specifier: ^0.5.1 version: 0.5.1 @@ -31,7 +34,7 @@ importers: version: 0.14.2 dotenv: specifier: ^16.5.0 - version: 16.5.0 + version: 16.6.1 json-stringify-safe: specifier: ^5.0.1 version: 5.0.1 @@ -41,9 +44,6 @@ importers: jwks-rsa: specifier: ^3.2.0 version: 3.2.0 - nanoid: - specifier: ^5.1.5 - version: 5.1.5 reflect-metadata: specifier: ^0.2.2 version: 0.2.2 @@ -52,17 +52,17 @@ importers: version: 7.8.2 zod: specifier: ^3.25.67 - version: 3.25.67 + version: 3.25.71 devDependencies: '@eslint/eslintrc': specifier: ^3.2.0 version: 3.3.1 '@eslint/js': specifier: ^9.18.0 - version: 9.29.0 + version: 9.30.1 '@nestjs/cli': specifier: ^11.0.0 - version: 11.0.7(@swc/cli@0.6.0(@swc/core@1.12.3)(chokidar@4.0.3))(@swc/core@1.12.3)(@types/node@22.15.32) + version: 11.0.7(@swc/cli@0.6.0(@swc/core@1.12.9)(chokidar@4.0.3))(@swc/core@1.12.9)(@types/node@22.16.0) '@nestjs/schematics': specifier: ^11.0.0 version: 11.0.5(chokidar@4.0.3)(typescript@5.8.3) @@ -71,10 +71,10 @@ importers: version: 11.1.3(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)(@nestjs/platform-express@11.1.3) '@swc/cli': specifier: ^0.6.0 - version: 0.6.0(@swc/core@1.12.3)(chokidar@4.0.3) + version: 0.6.0(@swc/core@1.12.9)(chokidar@4.0.3) '@swc/core': specifier: ^1.10.7 - version: 1.12.3 + version: 1.12.9 '@types/express': specifier: ^5.0.0 version: 5.0.3 @@ -83,28 +83,28 @@ importers: version: 29.5.14 '@types/node': specifier: ^22.15.32 - version: 22.15.32 + version: 22.16.0 '@types/supertest': specifier: ^6.0.2 version: 6.0.3 eslint: specifier: ^9.18.0 - version: 9.29.0 + version: 9.30.1 eslint-config-prettier: specifier: ^10.0.1 - version: 10.1.5(eslint@9.29.0) + version: 10.1.5(eslint@9.30.1) eslint-plugin-prettier: specifier: ^5.2.2 - version: 5.5.0(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.29.0))(eslint@9.29.0)(prettier@3.5.3) + version: 5.5.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.30.1))(eslint@9.30.1)(prettier@3.6.2) globals: specifier: ^15.14.0 version: 15.15.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + version: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) prettier: specifier: ^3.4.2 - version: 3.5.3 + version: 3.6.2 source-map-support: specifier: ^0.5.21 version: 0.5.21 @@ -113,13 +113,13 @@ importers: version: 7.1.1 ts-jest: specifier: ^29.2.5 - version: 29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3) + version: 29.4.0(@babel/core@7.28.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)))(typescript@5.8.3) ts-loader: specifier: ^9.5.2 - version: 9.5.2(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.3)) + version: 9.5.2(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.9)) ts-node: specifier: ^10.9.2 - version: 10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3) + version: 10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3) tsconfig-paths: specifier: ^4.2.0 version: 4.2.0 @@ -128,7 +128,7 @@ importers: version: 5.8.3 typescript-eslint: specifier: ^8.20.0 - version: 8.34.1(eslint@9.29.0)(typescript@5.8.3) + version: 8.35.1(eslint@9.30.1)(typescript@5.8.3) packages: @@ -171,22 +171,26 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.27.5': - resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} + '@babel/compat-data@7.28.0': + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} engines: {node: '>=6.9.0'} - '@babel/core@7.27.4': - resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} + '@babel/core@7.28.0': + resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} engines: {node: '>=6.9.0'} - '@babel/generator@7.27.5': - resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} @@ -217,8 +221,8 @@ packages: resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.5': - resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} engines: {node: '>=6.0.0'} hasBin: true @@ -317,12 +321,12 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.27.4': - resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.6': - resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} + '@babel/types@7.28.0': + resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': @@ -346,36 +350,36 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.20.1': - resolution: {integrity: sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==} + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.2.3': - resolution: {integrity: sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==} + '@eslint/config-helpers@0.3.0': + resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.14.0': resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.15.0': - resolution: {integrity: sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==} + '@eslint/core@0.15.1': + resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.29.0': - resolution: {integrity: sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==} + '@eslint/js@9.30.1': + resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.2': - resolution: {integrity: sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==} + '@eslint/plugin-kit@0.3.3': + resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanfs/core@0.19.1': @@ -398,8 +402,8 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@inquirer/checkbox@4.1.8': - resolution: {integrity: sha512-d/QAsnwuHX2OPolxvYcgSj7A9DO9H6gVOy2DvBTx+P2LH2iRTo/RSGV3iwCzW024nP9hw98KIuDmdyhZQj1UQg==} + '@inquirer/checkbox@4.1.9': + resolution: {integrity: sha512-DBJBkzI5Wx4jFaYm221LHvAhpKYkhVS0k9plqHwaHhofGNxvYB7J3Bz8w+bFJ05zaMb0sZNHo4KdmENQFlNTuQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -407,8 +411,8 @@ packages: '@types/node': optional: true - '@inquirer/confirm@5.1.12': - resolution: {integrity: sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==} + '@inquirer/confirm@5.1.13': + resolution: {integrity: sha512-EkCtvp67ICIVVzjsquUiVSd+V5HRGOGQfsqA4E4vMWhYnB7InUL0pa0TIWt1i+OfP16Gkds8CdIu6yGZwOM1Yw==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -416,8 +420,8 @@ packages: '@types/node': optional: true - '@inquirer/core@10.1.13': - resolution: {integrity: sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==} + '@inquirer/core@10.1.14': + resolution: {integrity: sha512-Ma+ZpOJPewtIYl6HZHZckeX1STvDnHTCB2GVINNUlSEn2Am6LddWwfPkIGY0IUFVjUUrr/93XlBwTK6mfLjf0A==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -425,8 +429,8 @@ packages: '@types/node': optional: true - '@inquirer/editor@4.2.13': - resolution: {integrity: sha512-WbicD9SUQt/K8O5Vyk9iC2ojq5RHoCLK6itpp2fHsWe44VxxcA9z3GTWlvjSTGmMQpZr+lbVmrxdHcumJoLbMA==} + '@inquirer/editor@4.2.14': + resolution: {integrity: sha512-yd2qtLl4QIIax9DTMZ1ZN2pFrrj+yL3kgIWxm34SS6uwCr0sIhsNyudUjAo5q3TqI03xx4SEBkUJqZuAInp9uA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -434,8 +438,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@4.0.15': - resolution: {integrity: sha512-4Y+pbr/U9Qcvf+N/goHzPEXiHH8680lM3Dr3Y9h9FFw4gHS+zVpbj8LfbKWIb/jayIB4aSO4pWiBTrBYWkvi5A==} + '@inquirer/expand@4.0.16': + resolution: {integrity: sha512-oiDqafWzMtofeJyyGkb1CTPaxUkjIcSxePHHQCfif8t3HV9pHcw1Kgdw3/uGpDvaFfeTluwQtWiqzPVjAqS3zA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -447,8 +451,8 @@ packages: resolution: {integrity: sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==} engines: {node: '>=18'} - '@inquirer/input@4.1.12': - resolution: {integrity: sha512-xJ6PFZpDjC+tC1P8ImGprgcsrzQRsUh9aH3IZixm1lAZFK49UGHxM3ltFfuInN2kPYNfyoPRh+tU4ftsjPLKqQ==} + '@inquirer/input@4.2.0': + resolution: {integrity: sha512-opqpHPB1NjAmDISi3uvZOTrjEEU5CWVu/HBkDby8t93+6UxYX0Z7Ps0Ltjm5sZiEbWenjubwUkivAEYQmy9xHw==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -456,8 +460,8 @@ packages: '@types/node': optional: true - '@inquirer/number@3.0.15': - resolution: {integrity: sha512-xWg+iYfqdhRiM55MvqiTCleHzszpoigUpN5+t1OMcRkJrUrw7va3AzXaxvS+Ak7Gny0j2mFSTv2JJj8sMtbV2g==} + '@inquirer/number@3.0.16': + resolution: {integrity: sha512-kMrXAaKGavBEoBYUCgualbwA9jWUx2TjMA46ek+pEKy38+LFpL9QHlTd8PO2kWPUgI/KB+qi02o4y2rwXbzr3Q==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -465,8 +469,8 @@ packages: '@types/node': optional: true - '@inquirer/password@4.0.15': - resolution: {integrity: sha512-75CT2p43DGEnfGTaqFpbDC2p2EEMrq0S+IRrf9iJvYreMy5mAWj087+mdKyLHapUEPLjN10mNvABpGbk8Wdraw==} + '@inquirer/password@4.0.16': + resolution: {integrity: sha512-g8BVNBj5Zeb5/Y3cSN+hDUL7CsIFDIuVxb9EPty3lkxBaYpjL5BNRKSYOF9yOLe+JOcKFd+TSVeADQ4iSY7rbg==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -492,8 +496,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@4.1.3': - resolution: {integrity: sha512-7XrV//6kwYumNDSsvJIPeAqa8+p7GJh7H5kRuxirct2cgOcSWwwNGoXDRgpNFbY/MG2vQ4ccIWCi8+IXXyFMZA==} + '@inquirer/rawlist@4.1.4': + resolution: {integrity: sha512-5GGvxVpXXMmfZNtvWw4IsHpR7RzqAR624xtkPd1NxxlV5M+pShMqzL4oRddRkg8rVEOK9fKdJp1jjVML2Lr7TQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -501,8 +505,8 @@ packages: '@types/node': optional: true - '@inquirer/search@3.0.15': - resolution: {integrity: sha512-YBMwPxYBrADqyvP4nNItpwkBnGGglAvCLVW8u4pRmmvOsHUtCAUIMbUrLX5B3tFL1/WsLGdQ2HNzkqswMs5Uaw==} + '@inquirer/search@3.0.16': + resolution: {integrity: sha512-POCmXo+j97kTGU6aeRjsPyuCpQQfKcMXdeTMw708ZMtWrj5aykZvlUxH4Qgz3+Y1L/cAVZsSpA+UgZCu2GMOMg==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -510,8 +514,8 @@ packages: '@types/node': optional: true - '@inquirer/select@4.2.3': - resolution: {integrity: sha512-OAGhXU0Cvh0PhLz9xTF/kx6g6x+sP+PcyTiLvCrewI99P3BBeexD+VbuwkNDvqGkk3y2h5ZiWLeRP7BFlhkUDg==} + '@inquirer/select@4.2.4': + resolution: {integrity: sha512-unTppUcTjmnbl/q+h8XeQDhAqIOmwWYWNyiiP2e3orXrg6tOaa5DHXja9PChCSbChOsktyKgOieRZFnajzxoBg==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -614,26 +618,21 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/source-map@0.3.6': - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -642,8 +641,8 @@ packages: resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} engines: {node: '>=8'} - '@modelcontextprotocol/sdk@1.13.0': - resolution: {integrity: sha512-P5FZsXU0kY881F6Hbk9GhsYx02/KgWK1DYf7/tyE/1lcFKhDYPQR9iYjhQXJn+Sg6hQleMo3DB7h7+p4wgp2Lw==} + '@modelcontextprotocol/sdk@1.13.3': + resolution: {integrity: sha512-bGwA78F/U5G2jrnsdRkPY3IwIwZeWUEfb5o764b79lb0rJmMT76TLwKhdNZOWakOQtedYefwIR4emisEMvInKA==} engines: {node: '>=18'} '@napi-rs/nice-android-arm-eabi@1.0.1': @@ -842,17 +841,6 @@ packages: resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@rekog/mcp-nest@1.6.2': - resolution: {integrity: sha512-swcu99a/woQ5T1f4E/YJct1w/xzszH83bhzEuZwXh+cYRnQUJKhaJd5Aey/XyOtt/D9lQTKSdnoKdpija8kuWA==} - peerDependencies: - '@modelcontextprotocol/sdk': '>=1.10.0' - '@nestjs/common': '>=9.0.0' - '@nestjs/core': '>=9.0.0' - express: '>=4.0.0' - reflect-metadata: '>=0.1.14' - zod: '>=3.0.0' - zod-to-json-schema: '>=3.23.0' - '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -880,68 +868,68 @@ packages: chokidar: optional: true - '@swc/core-darwin-arm64@1.12.3': - resolution: {integrity: sha512-QCV9vQ/s27AMxm8j8MTDL/nDoiEMrANiENRrWnb0Fxvz/O39CajPVShp/W7HlOkzt1GYtUXPdQJpSKylugfrWw==} + '@swc/core-darwin-arm64@1.12.9': + resolution: {integrity: sha512-GACFEp4nD6V+TZNR2JwbMZRHB+Yyvp14FrcmB6UCUYmhuNWjkxi+CLnEvdbuiKyQYv0zA+TRpCHZ+whEs6gwfA==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.12.3': - resolution: {integrity: sha512-LylCMfzGhdvl5tyKaTT9ePetHUX7wSsST7hxWiHzS+cUMj7FnhcfdEr6kcNVT7y1RJn3fCvuv7T98ZB+T2q3HA==} + '@swc/core-darwin-x64@1.12.9': + resolution: {integrity: sha512-hv2kls7Ilkm2EpeJz+I9MCil7pGS3z55ZAgZfxklEuYsxpICycxeH+RNRv4EraggN44ms+FWCjtZFu0LGg2V3g==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.12.3': - resolution: {integrity: sha512-DQODb7S+q+pwQY41Azcavwb2rb4rGxP70niScRDxB9X68hHOM9D0w9fxzC+Nr3AHcPSmVJUYUIiq5h38O5hVgQ==} + '@swc/core-linux-arm-gnueabihf@1.12.9': + resolution: {integrity: sha512-od9tDPiG+wMU9wKtd6y3nYJdNqgDOyLdgRRcrj1/hrbHoUPOM8wZQZdwQYGarw63iLXGgsw7t5HAF9Yc51ilFA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.12.3': - resolution: {integrity: sha512-nTxtJSq78AjeaQBueYImoFBs5j7qXbgOxtirpyt8jE29NQBd0VFzDzRBhkr6I9jq0hNiChgMkqBN4eUkEQjytg==} + '@swc/core-linux-arm64-gnu@1.12.9': + resolution: {integrity: sha512-6qx1ka9LHcLzxIgn2Mros+CZLkHK2TawlXzi/h7DJeNnzi8F1Hw0Yzjp8WimxNCg6s2n+o3jnmin1oXB7gg8rw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.12.3': - resolution: {integrity: sha512-lBGvC5UgPSxqLr/y1NZxQhyRQ7nXy3/Ec1Z47YNXtqtpKiG1EcOGPyS0UZgwiYQkXqq8NBFMHnyHmpKnXTvRDA==} + '@swc/core-linux-arm64-musl@1.12.9': + resolution: {integrity: sha512-yghFZWKPVVGbUdqiD7ft23G0JX6YFGDJPz9YbLLAwGuKZ9th3/jlWoQDAw1Naci31LQhVC+oIji6ozihSuwB2A==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.12.3': - resolution: {integrity: sha512-61wZ8hwxNYzBY9MCWB50v90ICzdIhOuPk1O1qXswz9AXw5O6iQStEBHQ1rozPkfQ/rmhepk0pOf/6LCwssJOwg==} + '@swc/core-linux-x64-gnu@1.12.9': + resolution: {integrity: sha512-SFUxyhWLZRNL8QmgGNqdi2Q43PNyFVkRZ2zIif30SOGFSxnxcf2JNeSeBgKIGVgaLSuk6xFVVCtJ3KIeaStgRg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.12.3': - resolution: {integrity: sha512-NNeBiTpCgWt80vumTKVoaj6Fa/ZjUcaNQNM7np3PIgB8EbuXfyztboV7vUxpkmD/lUgsk8GlEFYViHvo6VMefQ==} + '@swc/core-linux-x64-musl@1.12.9': + resolution: {integrity: sha512-9FB0wM+6idCGTI20YsBNBg9xSWtkDBymnpaTCsZM3qDc0l4uOpJMqbfWhQvp17x7r/ulZfb2QY8RDvQmCL6AcQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.12.3': - resolution: {integrity: sha512-fxraM7exaPb1/W0CoHW45EFNOQUQh0nonBEcNFm2iv095mziBwttyxZyQBoDkQocpkd5NtsZw3xW5FTBPnn+Vw==} + '@swc/core-win32-arm64-msvc@1.12.9': + resolution: {integrity: sha512-zHOusMVbOH9ik5RtRrMiGzLpKwxrPXgXkBm3SbUCa65HAdjV33NZ0/R9Rv1uPESALtEl2tzMYLUxYA5ECFDFhA==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.12.3': - resolution: {integrity: sha512-FFIhMPXIDjRcewomwbYGPvem7Fj76AsuzbRahnAyp+OzJwrrtxVmra/kyUCfj4kix7vdGByY0WvVfiVCf5b7Mg==} + '@swc/core-win32-ia32-msvc@1.12.9': + resolution: {integrity: sha512-aWZf0PqE0ot7tCuhAjRkDFf41AzzSQO0x2xRfTbnhpROp57BRJ/N5eee1VULO/UA2PIJRG7GKQky5bSGBYlFug==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.12.3': - resolution: {integrity: sha512-Sf4iSg+IYT5AzFSDDmii08DfeKcvtkVxIuo+uS8BJMbiLjFNjgMkkVlBthknGyJcSK15ncg9248XjnM4jU8DZA==} + '@swc/core-win32-x64-msvc@1.12.9': + resolution: {integrity: sha512-C25fYftXOras3P3anSUeXXIpxmEkdAcsIL9yrr0j1xepTZ/yKwpnQ6g3coj8UXdeJy4GTVlR6+Ow/QiBgZQNOg==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.12.3': - resolution: {integrity: sha512-c4NeXW8P3gPqcFwtm+4aH+F2Cj5KJLMiLaKhSj3mpv19glq+jmekomdktAw/VHyjsXlsmouOeNWrk8rVlkCRsg==} + '@swc/core@1.12.9': + resolution: {integrity: sha512-O+LfT2JlVMsIMWG9x+rdxg8GzpzeGtCZQfXV7cKc1PjIKUkLFf1QJ7okuseA4f/9vncu37dQ2ZcRrPKy0Ndd5g==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -959,6 +947,18 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} + '@tc/mcp-nest@https://codeload.github.com/topcoder-platform/MCP-Nest/tar.gz/025395f5f3a665e8439e481f84c25c6e6ed97933': + resolution: {tarball: https://codeload.github.com/topcoder-platform/MCP-Nest/tar.gz/025395f5f3a665e8439e481f84c25c6e6ed97933} + version: 1.6.2 + peerDependencies: + '@modelcontextprotocol/sdk': '>=1.10.0' + '@nestjs/common': '>=9.0.0' + '@nestjs/core': '>=9.0.0' + express: '>=4.0.0' + reflect-metadata: '>=0.1.14' + zod: '>=3.0.0' + zod-to-json-schema: '>=3.23.0' + '@tokenizer/inflate@0.2.7': resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} engines: {node: '>=18'} @@ -1056,8 +1056,8 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@22.15.32': - resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==} + '@types/node@22.16.0': + resolution: {integrity: sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==} '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} @@ -1089,63 +1089,63 @@ packages: '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - '@typescript-eslint/eslint-plugin@8.34.1': - resolution: {integrity: sha512-STXcN6ebF6li4PxwNeFnqF8/2BNDvBupf2OPx2yWNzr6mKNGF7q49VM00Pz5FaomJyqvbXpY6PhO+T9w139YEQ==} + '@typescript-eslint/eslint-plugin@8.35.1': + resolution: {integrity: sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.34.1 + '@typescript-eslint/parser': ^8.35.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.34.1': - resolution: {integrity: sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==} + '@typescript-eslint/parser@8.35.1': + resolution: {integrity: sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/project-service@8.34.1': - resolution: {integrity: sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==} + '@typescript-eslint/project-service@8.35.1': + resolution: {integrity: sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.34.1': - resolution: {integrity: sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==} + '@typescript-eslint/scope-manager@8.35.1': + resolution: {integrity: sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.34.1': - resolution: {integrity: sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==} + '@typescript-eslint/tsconfig-utils@8.35.1': + resolution: {integrity: sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/type-utils@8.34.1': - resolution: {integrity: sha512-Tv7tCCr6e5m8hP4+xFugcrwTOucB8lshffJ6zf1mF1TbU67R+ntCc6DzLNKM+s/uzDyv8gLq7tufaAhIBYeV8g==} + '@typescript-eslint/type-utils@8.35.1': + resolution: {integrity: sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.34.1': - resolution: {integrity: sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==} + '@typescript-eslint/types@8.35.1': + resolution: {integrity: sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.34.1': - resolution: {integrity: sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==} + '@typescript-eslint/typescript-estree@8.35.1': + resolution: {integrity: sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.34.1': - resolution: {integrity: sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==} + '@typescript-eslint/utils@8.35.1': + resolution: {integrity: sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.34.1': - resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==} + '@typescript-eslint/visitor-keys@8.35.1': + resolution: {integrity: sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@webassemblyjs/ast@1.14.1': @@ -1352,6 +1352,9 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + axios@1.10.0: + resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==} + b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} @@ -1414,8 +1417,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.25.0: - resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} + browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1474,8 +1477,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001723: - resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} + caniuse-lite@1.0.30001726: + resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1700,8 +1703,8 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dotenv@16.5.0: - resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} dunder-proto@1.0.1: @@ -1722,8 +1725,8 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.170: - resolution: {integrity: sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==} + electron-to-chromium@1.5.179: + resolution: {integrity: sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -1739,8 +1742,8 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} - enhanced-resolve@5.18.1: - resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + enhanced-resolve@5.18.2: + resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} engines: {node: '>=10.13.0'} error-ex@1.3.2: @@ -1786,8 +1789,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-prettier@5.5.0: - resolution: {integrity: sha512-8qsOYwkkGrahrgoUv76NZi23koqXOGiiEzXMrT8Q7VcYaUISR+5MorIUxfWqYXN0fN/31WbSrxCxFkVQ43wwrA==} + eslint-plugin-prettier@5.5.1: + resolution: {integrity: sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1816,8 +1819,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.29.0: - resolution: {integrity: sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==} + eslint@9.30.1: + resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1863,9 +1866,9 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.0.2: - resolution: {integrity: sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==} - engines: {node: '>=18.0.0'} + eventsource-parser@3.0.3: + resolution: {integrity: sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==} + engines: {node: '>=20.0.0'} eventsource@3.0.7: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} @@ -1883,11 +1886,11 @@ packages: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - express-rate-limit@7.5.0: - resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} + express-rate-limit@7.5.1: + resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==} engines: {node: '>= 16'} peerDependencies: - express: ^4.11 || 5 || ^5.0.0-beta.1 + express: '>= 4.11' express@5.1.0: resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} @@ -1989,6 +1992,15 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -2086,10 +2098,6 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -2698,11 +2706,6 @@ packages: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} - nanoid@5.1.5: - resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} - engines: {node: ^18 || >=20} - hasBin: true - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -2879,8 +2882,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier@3.5.3: - resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} engines: {node: '>=14'} hasBin: true @@ -2896,6 +2899,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -3262,8 +3268,8 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - token-types@6.0.0: - resolution: {integrity: sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==} + token-types@6.0.3: + resolution: {integrity: sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ==} engines: {node: '>=14.16'} tree-kill@1.2.2: @@ -3362,8 +3368,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@8.34.1: - resolution: {integrity: sha512-XjS+b6Vg9oT1BaIUfkW3M3LvqZE++rbzAMEHuccCfO/YkP43ha6w3jTEMilQxMF92nVOYCcdjv1ZUhAa1D/0ow==} + typescript-eslint@8.35.1: + resolution: {integrity: sha512-xslJjFzhOmHYQzSB/QTeASAHbjmxOGEP6Coh93TXmUBFQoJ1VU35UHIDmG06Jd6taf3wqqC1ntBnCMeymy5Ovw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3437,8 +3443,8 @@ packages: resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==} engines: {node: '>=6'} - webpack-sources@3.3.2: - resolution: {integrity: sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==} + webpack-sources@3.3.3: + resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} webpack@5.99.6: @@ -3517,20 +3523,20 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} - zod-to-json-schema@3.24.5: - resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + zod-to-json-schema@3.24.6: + resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==} peerDependencies: zod: ^3.24.1 - zod@3.25.67: - resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + zod@3.25.71: + resolution: {integrity: sha512-BsBc/NPk7h8WsUWYWYL+BajcJPY8YhjelaWu2NMLuzgraKAz4Lb4/6K11g9jpuDetjMiqhZ6YaexFLOC0Ogi3Q==} snapshots: '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 '@angular-devkit/core@19.2.6(chokidar@4.0.3)': dependencies: @@ -3554,11 +3560,11 @@ snapshots: optionalDependencies: chokidar: 4.0.3 - '@angular-devkit/schematics-cli@19.2.8(@types/node@22.15.32)(chokidar@4.0.3)': + '@angular-devkit/schematics-cli@19.2.8(@types/node@22.16.0)(chokidar@4.0.3)': dependencies: '@angular-devkit/core': 19.2.8(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.8(chokidar@4.0.3) - '@inquirer/prompts': 7.3.2(@types/node@22.15.32) + '@inquirer/prompts': 7.3.2(@types/node@22.16.0) ansi-colors: 4.1.3 symbol-observable: 4.0.0 yargs-parser: 21.1.1 @@ -3592,20 +3598,20 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.27.5': {} + '@babel/compat-data@7.28.0': {} - '@babel/core@7.27.4': + '@babel/core@7.28.0': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.5 + '@babel/generator': 7.28.0 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4) + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) '@babel/helpers': 7.27.6 - '@babel/parser': 7.27.5 + '@babel/parser': 7.28.0 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.4 - '@babel/types': 7.27.6 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 convert-source-map: 2.0.0 debug: 4.4.1 gensync: 1.0.0-beta.2 @@ -3614,35 +3620,37 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.27.5': + '@babel/generator@7.28.0': dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 jsesc: 3.1.0 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.27.5 + '@babel/compat-data': 7.28.0 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.25.0 + browserslist: 4.25.1 lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.27.4 - '@babel/types': 7.27.6 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)': + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.4 + '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color @@ -3657,116 +3665,116 @@ snapshots: '@babel/helpers@7.27.6': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.27.6 + '@babel/types': 7.28.0 - '@babel/parser@7.27.5': + '@babel/parser@7.28.0': dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.28.0 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.4)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.4)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.4)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.4)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.4)': + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.4)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.4)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.4)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.4)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.4)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.4)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.4)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.4)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.4)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.4)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.4)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.4)': + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 - '@babel/traverse@7.27.4': + '@babel/traverse@7.28.0': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.5 - '@babel/parser': 7.27.5 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 '@babel/template': 7.27.2 - '@babel/types': 7.27.6 + '@babel/types': 7.28.0 debug: 4.4.1 - globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.27.6': + '@babel/types@7.28.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 @@ -3780,14 +3788,14 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@eslint-community/eslint-utils@4.7.0(eslint@9.29.0)': + '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1)': dependencies: - eslint: 9.29.0 + eslint: 9.30.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/config-array@0.20.1': + '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 debug: 4.4.1 @@ -3795,13 +3803,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.2.3': {} + '@eslint/config-helpers@0.3.0': {} '@eslint/core@0.14.0': dependencies: '@types/json-schema': 7.0.15 - '@eslint/core@0.15.0': + '@eslint/core@0.15.1': dependencies: '@types/json-schema': 7.0.15 @@ -3819,13 +3827,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.29.0': {} + '@eslint/js@9.30.1': {} '@eslint/object-schema@2.1.6': {} - '@eslint/plugin-kit@0.3.2': + '@eslint/plugin-kit@0.3.3': dependencies: - '@eslint/core': 0.15.0 + '@eslint/core': 0.15.1 levn: 0.4.1 '@humanfs/core@0.19.1': {} @@ -3841,27 +3849,27 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@inquirer/checkbox@4.1.8(@types/node@22.15.32)': + '@inquirer/checkbox@4.1.9(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) '@inquirer/figures': 1.0.12 - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.16.0) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/confirm@5.1.12(@types/node@22.15.32)': + '@inquirer/confirm@5.1.13(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/core@10.1.13(@types/node@22.15.32)': + '@inquirer/core@10.1.14(@types/node@22.16.0)': dependencies: '@inquirer/figures': 1.0.12 - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.16.0) ansi-escapes: 4.3.2 cli-width: 4.1.0 mute-stream: 2.0.0 @@ -3869,108 +3877,108 @@ snapshots: wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/editor@4.2.13(@types/node@22.15.32)': + '@inquirer/editor@4.2.14(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) external-editor: 3.1.0 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/expand@4.0.15(@types/node@22.15.32)': + '@inquirer/expand@4.0.16(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@inquirer/figures@1.0.12': {} - '@inquirer/input@4.1.12(@types/node@22.15.32)': + '@inquirer/input@4.2.0(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/number@3.0.15(@types/node@22.15.32)': + '@inquirer/number@3.0.16(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/password@4.0.15(@types/node@22.15.32)': + '@inquirer/password@4.0.16(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) ansi-escapes: 4.3.2 optionalDependencies: - '@types/node': 22.15.32 - - '@inquirer/prompts@7.3.2(@types/node@22.15.32)': - dependencies: - '@inquirer/checkbox': 4.1.8(@types/node@22.15.32) - '@inquirer/confirm': 5.1.12(@types/node@22.15.32) - '@inquirer/editor': 4.2.13(@types/node@22.15.32) - '@inquirer/expand': 4.0.15(@types/node@22.15.32) - '@inquirer/input': 4.1.12(@types/node@22.15.32) - '@inquirer/number': 3.0.15(@types/node@22.15.32) - '@inquirer/password': 4.0.15(@types/node@22.15.32) - '@inquirer/rawlist': 4.1.3(@types/node@22.15.32) - '@inquirer/search': 3.0.15(@types/node@22.15.32) - '@inquirer/select': 4.2.3(@types/node@22.15.32) + '@types/node': 22.16.0 + + '@inquirer/prompts@7.3.2(@types/node@22.16.0)': + dependencies: + '@inquirer/checkbox': 4.1.9(@types/node@22.16.0) + '@inquirer/confirm': 5.1.13(@types/node@22.16.0) + '@inquirer/editor': 4.2.14(@types/node@22.16.0) + '@inquirer/expand': 4.0.16(@types/node@22.16.0) + '@inquirer/input': 4.2.0(@types/node@22.16.0) + '@inquirer/number': 3.0.16(@types/node@22.16.0) + '@inquirer/password': 4.0.16(@types/node@22.16.0) + '@inquirer/rawlist': 4.1.4(@types/node@22.16.0) + '@inquirer/search': 3.0.16(@types/node@22.16.0) + '@inquirer/select': 4.2.4(@types/node@22.16.0) optionalDependencies: - '@types/node': 22.15.32 - - '@inquirer/prompts@7.4.1(@types/node@22.15.32)': - dependencies: - '@inquirer/checkbox': 4.1.8(@types/node@22.15.32) - '@inquirer/confirm': 5.1.12(@types/node@22.15.32) - '@inquirer/editor': 4.2.13(@types/node@22.15.32) - '@inquirer/expand': 4.0.15(@types/node@22.15.32) - '@inquirer/input': 4.1.12(@types/node@22.15.32) - '@inquirer/number': 3.0.15(@types/node@22.15.32) - '@inquirer/password': 4.0.15(@types/node@22.15.32) - '@inquirer/rawlist': 4.1.3(@types/node@22.15.32) - '@inquirer/search': 3.0.15(@types/node@22.15.32) - '@inquirer/select': 4.2.3(@types/node@22.15.32) + '@types/node': 22.16.0 + + '@inquirer/prompts@7.4.1(@types/node@22.16.0)': + dependencies: + '@inquirer/checkbox': 4.1.9(@types/node@22.16.0) + '@inquirer/confirm': 5.1.13(@types/node@22.16.0) + '@inquirer/editor': 4.2.14(@types/node@22.16.0) + '@inquirer/expand': 4.0.16(@types/node@22.16.0) + '@inquirer/input': 4.2.0(@types/node@22.16.0) + '@inquirer/number': 3.0.16(@types/node@22.16.0) + '@inquirer/password': 4.0.16(@types/node@22.16.0) + '@inquirer/rawlist': 4.1.4(@types/node@22.16.0) + '@inquirer/search': 3.0.16(@types/node@22.16.0) + '@inquirer/select': 4.2.4(@types/node@22.16.0) optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/rawlist@4.1.3(@types/node@22.15.32)': + '@inquirer/rawlist@4.1.4(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) + '@inquirer/type': 3.0.7(@types/node@22.16.0) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/search@3.0.15(@types/node@22.15.32)': + '@inquirer/search@3.0.16(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) '@inquirer/figures': 1.0.12 - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.16.0) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/select@4.2.3(@types/node@22.15.32)': + '@inquirer/select@4.2.4(@types/node@22.16.0)': dependencies: - '@inquirer/core': 10.1.13(@types/node@22.15.32) + '@inquirer/core': 10.1.14(@types/node@22.16.0) '@inquirer/figures': 1.0.12 - '@inquirer/type': 3.0.7(@types/node@22.15.32) + '@inquirer/type': 3.0.7(@types/node@22.16.0) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 - '@inquirer/type@3.0.7(@types/node@22.15.32)': + '@inquirer/type@3.0.7(@types/node@22.16.0)': optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@isaacs/balanced-match@4.0.1': {} @@ -4000,27 +4008,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3))': + '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + jest-config: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -4045,7 +4053,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -4063,7 +4071,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.15.32 + '@types/node': 22.16.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -4084,8 +4092,8 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.15.32 + '@jridgewell/trace-mapping': 0.3.29 + '@types/node': 22.16.0 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -4112,7 +4120,7 @@ snapshots: '@jest/source-map@29.6.3': dependencies: - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.29 callsites: 3.1.0 graceful-fs: 4.2.11 @@ -4132,9 +4140,9 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.29 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 convert-source-map: 2.0.0 @@ -4155,52 +4163,50 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/yargs': 17.0.33 chalk: 4.1.2 - '@jridgewell/gen-mapping@0.3.8': + '@jridgewell/gen-mapping@0.3.12': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/source-map@0.3.6': + '@jridgewell/source-map@0.3.10': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 - '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.4': {} - '@jridgewell/trace-mapping@0.3.25': + '@jridgewell/trace-mapping@0.3.29': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.4 '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.4 '@lukeed/csprng@1.1.0': {} - '@modelcontextprotocol/sdk@1.13.0': + '@modelcontextprotocol/sdk@1.13.3': dependencies: ajv: 6.12.6 content-type: 1.0.5 cors: 2.8.5 cross-spawn: 7.0.6 eventsource: 3.0.7 + eventsource-parser: 3.0.3 express: 5.1.0 - express-rate-limit: 7.5.0(express@5.1.0) + express-rate-limit: 7.5.1(express@5.1.0) pkce-challenge: 5.0.0 raw-body: 3.0.0 - zod: 3.25.67 - zod-to-json-schema: 3.24.5(zod@3.25.67) + zod: 3.25.71 + zod-to-json-schema: 3.24.6(zod@3.25.71) transitivePeerDependencies: - supports-color @@ -4272,18 +4278,18 @@ snapshots: '@napi-rs/nice-win32-x64-msvc': 1.0.1 optional: true - '@nestjs/cli@11.0.7(@swc/cli@0.6.0(@swc/core@1.12.3)(chokidar@4.0.3))(@swc/core@1.12.3)(@types/node@22.15.32)': + '@nestjs/cli@11.0.7(@swc/cli@0.6.0(@swc/core@1.12.9)(chokidar@4.0.3))(@swc/core@1.12.9)(@types/node@22.16.0)': dependencies: '@angular-devkit/core': 19.2.8(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.8(chokidar@4.0.3) - '@angular-devkit/schematics-cli': 19.2.8(@types/node@22.15.32)(chokidar@4.0.3) - '@inquirer/prompts': 7.4.1(@types/node@22.15.32) + '@angular-devkit/schematics-cli': 19.2.8(@types/node@22.16.0)(chokidar@4.0.3) + '@inquirer/prompts': 7.4.1(@types/node@22.16.0) '@nestjs/schematics': 11.0.5(chokidar@4.0.3)(typescript@5.8.3) ansis: 3.17.0 chokidar: 4.0.3 cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.3)) + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.9)) glob: 11.0.1 node-emoji: 1.11.0 ora: 5.4.1 @@ -4291,11 +4297,11 @@ snapshots: tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.2.0 typescript: 5.8.3 - webpack: 5.99.6(@swc/core@1.12.3) + webpack: 5.99.6(@swc/core@1.12.9) webpack-node-externals: 3.0.0 optionalDependencies: - '@swc/cli': 0.6.0(@swc/core@1.12.3)(chokidar@4.0.3) - '@swc/core': 1.12.3 + '@swc/cli': 0.6.0(@swc/core@1.12.9)(chokidar@4.0.3) + '@swc/core': 1.12.9 transitivePeerDependencies: - '@types/node' - esbuild @@ -4386,17 +4392,6 @@ snapshots: '@pkgr/core@0.2.7': {} - '@rekog/mcp-nest@1.6.2(@modelcontextprotocol/sdk@1.13.0)(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)(express@5.1.0)(reflect-metadata@0.2.2)(zod-to-json-schema@3.24.5(zod@3.25.67))(zod@3.25.67)': - dependencies: - '@modelcontextprotocol/sdk': 1.13.0 - '@nestjs/common': 11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.3(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) - express: 5.1.0 - path-to-regexp: 8.2.0 - reflect-metadata: 0.2.2 - zod: 3.25.67 - zod-to-json-schema: 3.24.5(zod@3.25.67) - '@sec-ant/readable-stream@0.4.1': {} '@sinclair/typebox@0.27.8': {} @@ -4411,9 +4406,9 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@swc/cli@0.6.0(@swc/core@1.12.3)(chokidar@4.0.3)': + '@swc/cli@0.6.0(@swc/core@1.12.9)(chokidar@4.0.3)': dependencies: - '@swc/core': 1.12.3 + '@swc/core': 1.12.9 '@swc/counter': 0.1.3 '@xhmikosr/bin-wrapper': 13.0.5 commander: 8.3.0 @@ -4426,51 +4421,51 @@ snapshots: optionalDependencies: chokidar: 4.0.3 - '@swc/core-darwin-arm64@1.12.3': + '@swc/core-darwin-arm64@1.12.9': optional: true - '@swc/core-darwin-x64@1.12.3': + '@swc/core-darwin-x64@1.12.9': optional: true - '@swc/core-linux-arm-gnueabihf@1.12.3': + '@swc/core-linux-arm-gnueabihf@1.12.9': optional: true - '@swc/core-linux-arm64-gnu@1.12.3': + '@swc/core-linux-arm64-gnu@1.12.9': optional: true - '@swc/core-linux-arm64-musl@1.12.3': + '@swc/core-linux-arm64-musl@1.12.9': optional: true - '@swc/core-linux-x64-gnu@1.12.3': + '@swc/core-linux-x64-gnu@1.12.9': optional: true - '@swc/core-linux-x64-musl@1.12.3': + '@swc/core-linux-x64-musl@1.12.9': optional: true - '@swc/core-win32-arm64-msvc@1.12.3': + '@swc/core-win32-arm64-msvc@1.12.9': optional: true - '@swc/core-win32-ia32-msvc@1.12.3': + '@swc/core-win32-ia32-msvc@1.12.9': optional: true - '@swc/core-win32-x64-msvc@1.12.3': + '@swc/core-win32-x64-msvc@1.12.9': optional: true - '@swc/core@1.12.3': + '@swc/core@1.12.9': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.23 optionalDependencies: - '@swc/core-darwin-arm64': 1.12.3 - '@swc/core-darwin-x64': 1.12.3 - '@swc/core-linux-arm-gnueabihf': 1.12.3 - '@swc/core-linux-arm64-gnu': 1.12.3 - '@swc/core-linux-arm64-musl': 1.12.3 - '@swc/core-linux-x64-gnu': 1.12.3 - '@swc/core-linux-x64-musl': 1.12.3 - '@swc/core-win32-arm64-msvc': 1.12.3 - '@swc/core-win32-ia32-msvc': 1.12.3 - '@swc/core-win32-x64-msvc': 1.12.3 + '@swc/core-darwin-arm64': 1.12.9 + '@swc/core-darwin-x64': 1.12.9 + '@swc/core-linux-arm-gnueabihf': 1.12.9 + '@swc/core-linux-arm64-gnu': 1.12.9 + '@swc/core-linux-arm64-musl': 1.12.9 + '@swc/core-linux-x64-gnu': 1.12.9 + '@swc/core-linux-x64-musl': 1.12.9 + '@swc/core-win32-arm64-msvc': 1.12.9 + '@swc/core-win32-ia32-msvc': 1.12.9 + '@swc/core-win32-x64-msvc': 1.12.9 '@swc/counter@0.1.3': {} @@ -4482,11 +4477,22 @@ snapshots: dependencies: defer-to-connect: 2.0.1 + '@tc/mcp-nest@https://codeload.github.com/topcoder-platform/MCP-Nest/tar.gz/025395f5f3a665e8439e481f84c25c6e6ed97933(@modelcontextprotocol/sdk@1.13.3)(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)(express@5.1.0)(reflect-metadata@0.2.2)(zod-to-json-schema@3.24.6(zod@3.25.71))(zod@3.25.71)': + dependencies: + '@modelcontextprotocol/sdk': 1.13.3 + '@nestjs/common': 11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.3(@nestjs/common@11.1.3(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) + express: 5.1.0 + path-to-regexp: 8.2.0 + reflect-metadata: 0.2.2 + zod: 3.25.71 + zod-to-json-schema: 3.24.6(zod@3.25.71) + '@tokenizer/inflate@0.2.7': dependencies: debug: 4.4.1 fflate: 0.8.2 - token-types: 6.0.0 + token-types: 6.0.3 transitivePeerDependencies: - supports-color @@ -4502,33 +4508,33 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.7 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.28.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.0 '@types/babel__traverse@7.20.7': dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.28.0 '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/connect@3.4.38': dependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/cookiejar@2.1.5': {} @@ -4546,14 +4552,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 '@types/express-serve-static-core@5.0.6': dependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -4573,7 +4579,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/http-cache-semantics@4.0.4': {} @@ -4599,7 +4605,7 @@ snapshots: '@types/jsonwebtoken@9.0.10': dependencies: '@types/ms': 2.1.0 - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/methods@1.1.4': {} @@ -4607,7 +4613,7 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@22.15.32': + '@types/node@22.16.0': dependencies: undici-types: 6.21.0 @@ -4618,12 +4624,12 @@ snapshots: '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.15.32 + '@types/node': 22.16.0 '@types/send': 0.17.5 '@types/stack-utils@2.0.3': {} @@ -4632,7 +4638,7 @@ snapshots: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 22.15.32 + '@types/node': 22.16.0 form-data: 4.0.3 '@types/supertest@6.0.3': @@ -4648,15 +4654,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0)(typescript@5.8.3))(eslint@9.29.0)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.34.1(eslint@9.29.0)(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.34.1 - '@typescript-eslint/type-utils': 8.34.1(eslint@9.29.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.1(eslint@9.29.0)(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.34.1 - eslint: 9.29.0 + '@typescript-eslint/parser': 8.35.1(eslint@9.30.1)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.35.1 + '@typescript-eslint/type-utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.35.1 + eslint: 9.30.1 graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -4665,55 +4671,55 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.34.1(eslint@9.29.0)(typescript@5.8.3)': + '@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.34.1 - '@typescript-eslint/types': 8.34.1 - '@typescript-eslint/typescript-estree': 8.34.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.34.1 + '@typescript-eslint/scope-manager': 8.35.1 + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.35.1 debug: 4.4.1 - eslint: 9.29.0 + eslint: 9.30.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.34.1(typescript@5.8.3)': + '@typescript-eslint/project-service@8.35.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.34.1(typescript@5.8.3) - '@typescript-eslint/types': 8.34.1 + '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3) + '@typescript-eslint/types': 8.35.1 debug: 4.4.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.34.1': + '@typescript-eslint/scope-manager@8.35.1': dependencies: - '@typescript-eslint/types': 8.34.1 - '@typescript-eslint/visitor-keys': 8.34.1 + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/visitor-keys': 8.35.1 - '@typescript-eslint/tsconfig-utils@8.34.1(typescript@5.8.3)': + '@typescript-eslint/tsconfig-utils@8.35.1(typescript@5.8.3)': dependencies: typescript: 5.8.3 - '@typescript-eslint/type-utils@8.34.1(eslint@9.29.0)(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.35.1(eslint@9.30.1)(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.34.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.1(eslint@9.29.0)(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) debug: 4.4.1 - eslint: 9.29.0 + eslint: 9.30.1 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.34.1': {} + '@typescript-eslint/types@8.35.1': {} - '@typescript-eslint/typescript-estree@8.34.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.35.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/project-service': 8.34.1(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.34.1(typescript@5.8.3) - '@typescript-eslint/types': 8.34.1 - '@typescript-eslint/visitor-keys': 8.34.1 + '@typescript-eslint/project-service': 8.35.1(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3) + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/visitor-keys': 8.35.1 debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -4724,20 +4730,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.34.1(eslint@9.29.0)(typescript@5.8.3)': + '@typescript-eslint/utils@8.35.1(eslint@9.30.1)(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0) - '@typescript-eslint/scope-manager': 8.34.1 - '@typescript-eslint/types': 8.34.1 - '@typescript-eslint/typescript-estree': 8.34.1(typescript@5.8.3) - eslint: 9.29.0 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1) + '@typescript-eslint/scope-manager': 8.35.1 + '@typescript-eslint/types': 8.35.1 + '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) + eslint: 9.30.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.34.1': + '@typescript-eslint/visitor-keys@8.35.1': dependencies: - '@typescript-eslint/types': 8.34.1 + '@typescript-eslint/types': 8.35.1 eslint-visitor-keys: 4.2.1 '@webassemblyjs/ast@1.14.1': @@ -4979,15 +4985,23 @@ snapshots: asynckit@0.4.0: {} + axios@1.10.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.3 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + b4a@1.6.7: {} - babel-jest@29.7.0(@babel/core@7.27.4): + babel-jest@29.7.0(@babel/core@7.28.0): dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.27.4) + babel-preset-jest: 29.6.3(@babel/core@7.28.0) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -5007,34 +5021,34 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.27.6 + '@babel/types': 7.28.0 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.7 - babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.4): - dependencies: - '@babel/core': 7.27.4 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.4) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.27.4) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.27.4) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.4) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.4) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.27.4) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.27.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.4) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.27.4) - - babel-preset-jest@29.6.3(@babel/core@7.27.4): - dependencies: - '@babel/core': 7.27.4 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.0): + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.0) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.0) + + babel-preset-jest@29.6.3(@babel/core@7.28.0): + dependencies: + '@babel/core': 7.28.0 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) balanced-match@1.0.2: {} @@ -5087,12 +5101,12 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.25.0: + browserslist@4.25.1: dependencies: - caniuse-lite: 1.0.30001723 - electron-to-chromium: 1.5.170 + caniuse-lite: 1.0.30001726 + electron-to-chromium: 1.5.179 node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.0) + update-browserslist-db: 1.1.3(browserslist@4.25.1) bs-logger@0.2.6: dependencies: @@ -5147,7 +5161,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001723: {} + caniuse-lite@1.0.30001726: {} chalk@4.1.2: dependencies: @@ -5275,13 +5289,13 @@ snapshots: optionalDependencies: typescript: 5.8.3 - create-jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)): + create-jest@29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + jest-config: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -5335,7 +5349,7 @@ snapshots: diff@4.0.2: {} - dotenv@16.5.0: {} + dotenv@16.6.1: {} dunder-proto@1.0.1: dependencies: @@ -5355,7 +5369,7 @@ snapshots: dependencies: jake: 10.9.2 - electron-to-chromium@1.5.170: {} + electron-to-chromium@1.5.179: {} emittery@0.13.1: {} @@ -5365,7 +5379,7 @@ snapshots: encodeurl@2.0.0: {} - enhanced-resolve@5.18.1: + enhanced-resolve@5.18.2: dependencies: graceful-fs: 4.2.11 tapable: 2.2.2 @@ -5399,19 +5413,19 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.5(eslint@9.29.0): + eslint-config-prettier@10.1.5(eslint@9.30.1): dependencies: - eslint: 9.29.0 + eslint: 9.30.1 - eslint-plugin-prettier@5.5.0(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.29.0))(eslint@9.29.0)(prettier@3.5.3): + eslint-plugin-prettier@5.5.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.30.1))(eslint@9.30.1)(prettier@3.6.2): dependencies: - eslint: 9.29.0 - prettier: 3.5.3 + eslint: 9.30.1 + prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.8 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.5(eslint@9.29.0) + eslint-config-prettier: 10.1.5(eslint@9.30.1) eslint-scope@5.1.1: dependencies: @@ -5427,16 +5441,16 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.29.0: + eslint@9.30.1: dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1) '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.20.1 - '@eslint/config-helpers': 0.2.3 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.0 '@eslint/core': 0.14.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.29.0 - '@eslint/plugin-kit': 0.3.2 + '@eslint/js': 9.30.1 + '@eslint/plugin-kit': 0.3.3 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -5493,11 +5507,11 @@ snapshots: events@3.3.0: {} - eventsource-parser@3.0.2: {} + eventsource-parser@3.0.3: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.0.2 + eventsource-parser: 3.0.3 execa@5.1.1: dependencies: @@ -5521,7 +5535,7 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 - express-rate-limit@7.5.0(express@5.1.0): + express-rate-limit@7.5.1(express@5.1.0): dependencies: express: 5.1.0 @@ -5612,14 +5626,14 @@ snapshots: dependencies: get-stream: 9.0.1 strtok3: 9.1.1 - token-types: 6.0.0 + token-types: 6.0.3 uint8array-extras: 1.4.0 file-type@21.0.0: dependencies: '@tokenizer/inflate': 0.2.7 strtok3: 10.3.1 - token-types: 6.0.0 + token-types: 6.0.3 uint8array-extras: 1.4.0 transitivePeerDependencies: - supports-color @@ -5670,12 +5684,14 @@ snapshots: flatted@3.3.3: {} + follow-redirects@1.15.9: {} + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@9.1.0(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.3)): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.9)): dependencies: '@babel/code-frame': 7.27.1 chalk: 4.1.2 @@ -5690,7 +5706,7 @@ snapshots: semver: 7.7.2 tapable: 2.2.2 typescript: 5.8.3 - webpack: 5.99.6(@swc/core@1.12.3) + webpack: 5.99.6(@swc/core@1.12.9) form-data-encoder@2.1.4: {} @@ -5786,8 +5802,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - globals@11.12.0: {} - globals@14.0.0: {} globals@15.15.0: {} @@ -5920,8 +5934,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.27.4 - '@babel/parser': 7.27.5 + '@babel/core': 7.28.0 + '@babel/parser': 7.28.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -5930,8 +5944,8 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.27.4 - '@babel/parser': 7.27.5 + '@babel/core': 7.28.0 + '@babel/parser': 7.28.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.7.2 @@ -5982,7 +5996,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.6.0 @@ -6002,16 +6016,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)): + jest-cli@29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + create-jest: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + jest-config: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -6021,12 +6035,12 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)): + jest-config@29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)): dependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.27.4) + babel-jest: 29.7.0(@babel/core@7.28.0) chalk: 4.1.2 ci-info: 3.9.0 deepmerge: 4.3.1 @@ -6046,8 +6060,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.15.32 - ts-node: 10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3) + '@types/node': 22.16.0 + ts-node: 10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -6076,7 +6090,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -6086,7 +6100,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.15.32 + '@types/node': 22.16.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -6125,7 +6139,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -6160,7 +6174,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -6188,7 +6202,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 chalk: 4.1.2 cjs-module-lexer: 1.4.3 collect-v8-coverage: 1.0.2 @@ -6208,15 +6222,15 @@ snapshots: jest-snapshot@29.7.0: dependencies: - '@babel/core': 7.27.4 - '@babel/generator': 7.27.5 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.4) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.4) - '@babel/types': 7.27.6 + '@babel/core': 7.28.0 + '@babel/generator': 7.28.0 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/types': 7.28.0 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4) + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.0) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -6234,7 +6248,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -6253,7 +6267,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.32 + '@types/node': 22.16.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -6262,23 +6276,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 22.15.32 + '@types/node': 22.16.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)): + jest@29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + jest-cli: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -6436,7 +6450,7 @@ snapshots: magic-string@0.30.17: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.4 make-dir@4.0.0: dependencies: @@ -6529,8 +6543,6 @@ snapshots: mute-stream@2.0.0: {} - nanoid@5.1.5: {} - natural-compare@1.4.0: {} negotiator@1.0.0: {} @@ -6676,7 +6688,7 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier@3.5.3: {} + prettier@3.6.2: {} pretty-format@29.7.0: dependencies: @@ -6694,6 +6706,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -7029,20 +7043,20 @@ snapshots: fast-fifo: 1.3.2 streamx: 2.22.1 - terser-webpack-plugin@5.3.14(@swc/core@1.12.3)(webpack@5.99.6(@swc/core@1.12.3)): + terser-webpack-plugin@5.3.14(@swc/core@1.12.9)(webpack@5.99.6(@swc/core@1.12.9)): dependencies: - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.29 jest-worker: 27.5.1 schema-utils: 4.3.2 serialize-javascript: 6.0.2 terser: 5.43.1 - webpack: 5.99.6(@swc/core@1.12.3) + webpack: 5.99.6(@swc/core@1.12.9) optionalDependencies: - '@swc/core': 1.12.3 + '@swc/core': 1.12.9 terser@5.43.1: dependencies: - '@jridgewell/source-map': 0.3.6 + '@jridgewell/source-map': 0.3.10 acorn: 8.15.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -7071,7 +7085,7 @@ snapshots: toidentifier@1.0.1: {} - token-types@6.0.0: + token-types@6.0.3: dependencies: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 @@ -7082,12 +7096,12 @@ snapshots: dependencies: typescript: 5.8.3 - ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3): + ts-jest@29.4.0(@babel/core@7.28.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.0))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)))(typescript@5.8.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3)) + jest: 29.7.0(@types/node@22.16.0)(ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -7096,30 +7110,30 @@ snapshots: typescript: 5.8.3 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.27.4 + '@babel/core': 7.28.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.27.4) + babel-jest: 29.7.0(@babel/core@7.28.0) jest-util: 29.7.0 - ts-loader@9.5.2(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.3)): + ts-loader@9.5.2(typescript@5.8.3)(webpack@5.99.6(@swc/core@1.12.9)): dependencies: chalk: 4.1.2 - enhanced-resolve: 5.18.1 + enhanced-resolve: 5.18.2 micromatch: 4.0.8 semver: 7.7.2 source-map: 0.7.4 typescript: 5.8.3 - webpack: 5.99.6(@swc/core@1.12.3) + webpack: 5.99.6(@swc/core@1.12.9) - ts-node@10.9.2(@swc/core@1.12.3)(@types/node@22.15.32)(typescript@5.8.3): + ts-node@10.9.2(@swc/core@1.12.9)(@types/node@22.16.0)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.15.32 + '@types/node': 22.16.0 acorn: 8.15.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -7130,12 +7144,12 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.12.3 + '@swc/core': 1.12.9 tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 - enhanced-resolve: 5.18.1 + enhanced-resolve: 5.18.2 tapable: 2.2.2 tsconfig-paths: 4.2.0 @@ -7170,12 +7184,12 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@8.34.1(eslint@9.29.0)(typescript@5.8.3): + typescript-eslint@8.35.1(eslint@9.30.1)(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0)(typescript@5.8.3))(eslint@9.29.0)(typescript@5.8.3) - '@typescript-eslint/parser': 8.34.1(eslint@9.29.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.1(eslint@9.29.0)(typescript@5.8.3) - eslint: 9.29.0 + '@typescript-eslint/eslint-plugin': 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3) + '@typescript-eslint/parser': 8.35.1(eslint@9.30.1)(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.1(eslint@9.30.1)(typescript@5.8.3) + eslint: 9.30.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -7199,9 +7213,9 @@ snapshots: unpipe@1.0.0: {} - update-browserslist-db@1.1.3(browserslist@4.25.0): + update-browserslist-db@1.1.3(browserslist@4.25.1): dependencies: - browserslist: 4.25.0 + browserslist: 4.25.1 escalade: 3.2.0 picocolors: 1.1.1 @@ -7215,7 +7229,7 @@ snapshots: v8-to-istanbul@9.3.0: dependencies: - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.29 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 @@ -7238,9 +7252,9 @@ snapshots: webpack-node-externals@3.0.0: {} - webpack-sources@3.3.2: {} + webpack-sources@3.3.3: {} - webpack@5.99.6(@swc/core@1.12.3): + webpack@5.99.6(@swc/core@1.12.9): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -7248,9 +7262,9 @@ snapshots: '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 - browserslist: 4.25.0 + browserslist: 4.25.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.1 + enhanced-resolve: 5.18.2 es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -7262,9 +7276,9 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.2 tapable: 2.2.2 - terser-webpack-plugin: 5.3.14(@swc/core@1.12.3)(webpack@5.99.6(@swc/core@1.12.3)) + terser-webpack-plugin: 5.3.14(@swc/core@1.12.9)(webpack@5.99.6(@swc/core@1.12.9)) watchpack: 2.4.4 - webpack-sources: 3.3.2 + webpack-sources: 3.3.3 transitivePeerDependencies: - '@swc/core' - esbuild @@ -7332,8 +7346,8 @@ snapshots: yoctocolors-cjs@2.1.2: {} - zod-to-json-schema@3.24.5(zod@3.25.67): + zod-to-json-schema@3.24.6(zod@3.25.71): dependencies: - zod: 3.25.67 + zod: 3.25.71 - zod@3.25.67: {} + zod@3.25.71: {} diff --git a/src/api/health-check/healthCheck.controller.ts b/src/api/health-check/healthCheck.controller.ts index b47a761..4dc6266 100644 --- a/src/api/health-check/healthCheck.controller.ts +++ b/src/api/health-check/healthCheck.controller.ts @@ -19,7 +19,7 @@ export class HealthCheckController { @Public() @Version([VERSION_NEUTRAL, '1']) - @Get('/healthcheck') + @Get('/health') healthCheck(): Promise { const response = new GetHealthCheckResponseDto(); diff --git a/src/app.module.ts b/src/app.module.ts index d53eeec..9214a26 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,14 +1,12 @@ import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; -import { McpModule } from '@rekog/mcp-nest'; -import { QueryChallengesTool } from './mcp/tools/challenges/queryChallenges.tool'; -import { randomUUID } from 'crypto'; -import { GlobalProvidersModule } from './shared/global/globalProviders.module'; -import { TopcoderModule } from './shared/topcoder/topcoder.module'; +import { McpModule } from '@tc/mcp-nest'; import { HealthCheckController } from './api/health-check/healthCheck.controller'; import { TokenValidatorMiddleware } from './core/auth/middleware/tokenValidator.middleware'; -import { CreateRequestStoreMiddleware } from './core/request/createRequestStore.middleware'; -import { AuthGuard, RolesGuard } from './core/auth/guards'; -import { APP_GUARD } from '@nestjs/core'; +import { ToolsModule } from './mcp/tools/tools.module'; +import { GlobalProvidersModule } from './shared/global/globalProviders.module'; +import { ResourcesModule } from './mcp/resources/resources.module'; +import { randomUUID } from 'crypto'; +import { TimingInterceptorMiddleware } from './shared/global/timingInterceptor'; @Module({ imports: [ @@ -20,27 +18,17 @@ import { APP_GUARD } from '@nestjs/core'; sessionIdGenerator: () => randomUUID(), statelessMode: false, }, - // guards: [AuthGuard, RolesGuard], }), GlobalProvidersModule, - TopcoderModule, + ToolsModule, + ResourcesModule, ], controllers: [HealthCheckController], - providers: [ - // { - // provide: APP_GUARD, - // useClass: AuthGuard, - // }, - // { - // provide: APP_GUARD, - // useClass: RolesGuard, - // }, - QueryChallengesTool, - ], + providers: [], }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { - // consumer.apply(TokenValidatorMiddleware).forRoutes('*'); - // consumer.apply(CreateRequestStoreMiddleware).forRoutes('*'); + consumer.apply(TokenValidatorMiddleware).forRoutes('*'); + consumer.apply(TimingInterceptorMiddleware).forRoutes('*'); } } diff --git a/src/config/config.env.ts b/src/config/config.env.ts index 0130772..81a48f6 100644 --- a/src/config/config.env.ts +++ b/src/config/config.env.ts @@ -16,4 +16,8 @@ export class ConfigEnv { @IsString() AUTH0_CLIENT_ID!: string; + + @IsString() + @IsOptional() + API_BASE = '/v6/mcp'; } diff --git a/src/core/auth/auth.constants.ts b/src/core/auth/auth.constants.ts index 71de54c..e0d1620 100644 --- a/src/core/auth/auth.constants.ts +++ b/src/core/auth/auth.constants.ts @@ -1,5 +1,8 @@ export enum Role { + Admin = 'administrator', User = 'Topcoder User', } -export enum M2mScope {} +export enum M2mScope { + QueryPublicChallenges = 'query:public:challenges', +} diff --git a/src/core/auth/decorators/index.ts b/src/core/auth/decorators/index.ts index 05c68d6..07b77ea 100644 --- a/src/core/auth/decorators/index.ts +++ b/src/core/auth/decorators/index.ts @@ -1,5 +1,4 @@ export * from './m2m.decorator'; export * from './m2mScope.decorator'; export * from './public.decorator'; -export * from './roles.decorator'; export * from './user.decorator'; diff --git a/src/core/auth/decorators/roles.decorator.ts b/src/core/auth/decorators/roles.decorator.ts deleted file mode 100644 index 9ffe82c..0000000 --- a/src/core/auth/decorators/roles.decorator.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SetMetadata } from '@nestjs/common'; -import { Role } from '../auth.constants'; - -export const ROLES_KEY = 'roles'; -export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles); diff --git a/src/core/auth/guards/auth.guard.ts b/src/core/auth/guards/auth.guard.ts index 921ae5b..a63de76 100644 --- a/src/core/auth/guards/auth.guard.ts +++ b/src/core/auth/guards/auth.guard.ts @@ -1,59 +1,16 @@ -import { - CanActivate, - ExecutionContext, - Injectable, - UnauthorizedException, -} from '@nestjs/common'; -import { Reflector } from '@nestjs/core'; -import { IS_PUBLIC_KEY } from '../decorators/public.decorator'; -import { IS_M2M_KEY } from '../decorators/m2m.decorator'; -import { M2mScope } from '../auth.constants'; -import { SCOPES_KEY } from '../decorators/m2mScope.decorator'; - -@Injectable() -export class AuthGuard implements CanActivate { - constructor(private reflector: Reflector) {} - - canActivate(context: ExecutionContext): boolean { - const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ - context.getHandler(), - context.getClass(), - ]); - - if (isPublic) return true; - - const req = context.switchToHttp().getRequest(); - const isM2M = this.reflector.getAllAndOverride(IS_M2M_KEY, [ - context.getHandler(), - context.getClass(), - ]); - - const { m2mUserId } = req; - if (m2mUserId) { - req.user = { - id: m2mUserId, - handle: '', - }; - } - - // Regular authentication - check that we have user's email and have verified the id token - if (!isM2M) { - return Boolean(req.email && req.idTokenVerified); - } - - // M2M authentication - check scopes - if (!req.idTokenVerified || !req.m2mTokenScope) - throw new UnauthorizedException(); - - const allowedM2mScopes = this.reflector.getAllAndOverride( - SCOPES_KEY, - [context.getHandler(), context.getClass()], - ); - - const reqScopes = req.m2mTokenScope.split(' '); - if (reqScopes.some((reqScope) => allowedM2mScopes.includes(reqScope))) { - return true; - } +import { Request } from 'express'; +import { decodeAuthToken } from './guards.utils'; + +/** + * Auth guard function to validate the authorization token from the request headers. + * + * @param req - The incoming HTTP request object. + * @returns A promise that resolves to `true` if the authorization token is valid, otherwise `false`. + */ +export const authGuard = async (req: Request) => { + if (!(await decodeAuthToken(req.headers.authorization ?? ''))) { return false; } -} + + return true; +}; diff --git a/src/core/auth/guards/guards.utils.ts b/src/core/auth/guards/guards.utils.ts new file mode 100644 index 0000000..f2045fa --- /dev/null +++ b/src/core/auth/guards/guards.utils.ts @@ -0,0 +1,36 @@ +/* eslint-disable @typescript-eslint/no-redundant-type-constituents */ +import * as jwt from 'jsonwebtoken'; +import { Logger } from 'src/shared/global'; +import { getSigningKey } from '../jwt'; + +const logger = new Logger('guards.utils()'); + +/** + * Decodes and verifies a JWT token from the provided authorization header. + * + * @param authHeader - The authorization header containing the token, expected in the format "Bearer ". + * @returns A promise that resolves to the decoded JWT payload if the token is valid, + * a string if the payload is a string, or `false` if the token is invalid or the header is improperly formatted. + * + * @throws This function does not throw directly but will return `false` if an error occurs during verification. + */ +export const decodeAuthToken = async ( + authHeader: string, +): Promise => { + const [type, idToken] = authHeader?.split(' ') ?? []; + + if (type !== 'Bearer' || !idToken) { + return false; + } + + let decoded: jwt.JwtPayload | string; + try { + const signingKey = await getSigningKey(idToken); + decoded = jwt.verify(idToken, signingKey); + } catch (error) { + logger.error('Error verifying JWT', error); + return false; + } + + return decoded; +}; diff --git a/src/core/auth/guards/index.ts b/src/core/auth/guards/index.ts index 4ae679c..49afb20 100644 --- a/src/core/auth/guards/index.ts +++ b/src/core/auth/guards/index.ts @@ -1,2 +1,3 @@ export * from './auth.guard'; -export * from './roles.guard'; +export * from './m2m-scope.guard'; +export * from './role.guard'; diff --git a/src/core/auth/guards/m2m-scope.guard.ts b/src/core/auth/guards/m2m-scope.guard.ts new file mode 100644 index 0000000..b1d85a5 --- /dev/null +++ b/src/core/auth/guards/m2m-scope.guard.ts @@ -0,0 +1,30 @@ +import { Request } from 'express'; +import { decodeAuthToken } from './guards.utils'; +import { JwtPayload } from 'jsonwebtoken'; +import { M2mScope } from '../auth.constants'; + +/** + * A utility function to check if the required M2M (Machine-to-Machine) scopes are present + * in the authorization token provided in the request headers. + * + * @param {...M2mScope[]} requiredM2mScopes - The list of required M2M scopes to validate against. + * @returns {Promise<(req: Request) => boolean>} A function that takes an Express `Request` object + * and returns a boolean indicating whether the required scopes are present. + * + * The function decodes the authorization token from the request headers and checks if + * the required scopes are included in the token's scope claim. + */ +export const checkM2MScope = + (...requiredM2mScopes: M2mScope[]) => + async (req: Request) => { + const decodedAuth = await decodeAuthToken(req.headers.authorization ?? ''); + + const authorizedScopes = ((decodedAuth as JwtPayload).scope ?? '').split( + ' ', + ); + if (!requiredM2mScopes.some((scope) => authorizedScopes.includes(scope))) { + return false; + } + + return true; + }; diff --git a/src/core/auth/guards/role.guard.ts b/src/core/auth/guards/role.guard.ts new file mode 100644 index 0000000..15fbc50 --- /dev/null +++ b/src/core/auth/guards/role.guard.ts @@ -0,0 +1,34 @@ +import { Request } from 'express'; +import { decodeAuthToken } from './guards.utils'; +import { Role } from '../auth.constants'; + +/** + * A utility function to check if the required user role are present + * in the authorization token provided in the request headers. + * + * @param {...Role[]} requiredUserRoles - The list of required user roles to validate against. + * @returns {Promise<(req: Request) => boolean>} A function that takes an Express `Request` object + * and returns a boolean indicating whether the required scopes are present. + * + * The function decodes the authorization token from the request headers and checks if + * the required user roles are included in the token's scope claim. + */ +export const checkHasUserRole = + (...requiredUserRoles: Role[]) => + async (req: Request) => { + const decodedAuth = await decodeAuthToken(req.headers.authorization ?? ''); + + const decodedUserRoles = Object.keys(decodedAuth).reduce((roles, key) => { + if (key.match(/claims\/roles$/gi)) { + return decodedAuth[key] as string[]; + } + + return roles; + }, []); + + if (!requiredUserRoles.some((role) => decodedUserRoles.includes(role))) { + return false; + } + + return true; + }; diff --git a/src/core/auth/guards/roles.guard.ts b/src/core/auth/guards/roles.guard.ts deleted file mode 100644 index 8145cce..0000000 --- a/src/core/auth/guards/roles.guard.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; -import { Reflector } from '@nestjs/core'; -import { ROLES_KEY } from '../decorators/roles.decorator'; - -@Injectable() -export class RolesGuard implements CanActivate { - constructor(private reflector: Reflector) {} - - canActivate(context: ExecutionContext): boolean { - const requiredRoles = this.reflector.getAllAndOverride( - ROLES_KEY, - [context.getHandler(), context.getClass()], - ); - - if (!requiredRoles) { - return true; - } - - const request = context.switchToHttp().getRequest(); - const { auth0User } = request; - const userRoles = Object.keys(auth0User).reduce((roles, key) => { - if (key.match(/claims\/roles$/gi)) { - return auth0User[key] as string[]; - } - - return roles; - }, []); - - if (!requiredRoles.some((role) => userRoles.includes(role))) { - return false; - } - - const userHandle = Object.keys(auth0User).reduce((handles, key) => { - if (key.match(/claims\/handle$/gi)) { - return auth0User[key] as string; - } - - return handles; - }, []); - - const userId = Object.keys(auth0User).reduce((ids, key) => { - if (key.match(/claims\/userId$/gi)) { - return auth0User[key] as string; - } - - return ids; - }, []); - - request.user = { - id: userId, - handle: userHandle, - email: request.email, - }; - - return true; - } -} diff --git a/src/core/request/createRequestStore.middleware.ts b/src/core/request/createRequestStore.middleware.ts deleted file mode 100644 index 1b45180..0000000 --- a/src/core/request/createRequestStore.middleware.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Injectable, NestMiddleware } from '@nestjs/common'; -import { Response, NextFunction } from 'express'; -import { RequestMetadata, saveStore } from './requestStore'; - -@Injectable() -export class CreateRequestStoreMiddleware implements NestMiddleware { - constructor() {} - - use(req: any, res: Response, next: NextFunction) { - const requestMetaData = new RequestMetadata({}); - - saveStore(requestMetaData, next); - } -} diff --git a/src/core/request/requestStore.ts b/src/core/request/requestStore.ts deleted file mode 100644 index dc6bdd9..0000000 --- a/src/core/request/requestStore.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { AsyncLocalStorage } from 'async_hooks'; -import { NextFunction } from 'express'; -import { nanoid } from 'nanoid'; - -// Class for storing request specific metadata -export class RequestMetadata { - requestId: string; - - constructor(params: { requestId?: string }) { - this.requestId = params.requestId ?? nanoid(11); - } -} - -// Create a AsyncLocalStorage of type RequestMetaData for storing request specific data -const asyncStorage = new AsyncLocalStorage(); - -// Gets the RequestMetadada object associated with the current request -export function getStore(): RequestMetadata { - let store = asyncStorage.getStore(); - if (store === undefined) { - store = new RequestMetadata({ - requestId: '', - }); - } - - return store; -} - -// For use in middleware -// Saves RequestMetadata for the current request -export function saveStore( - requestMetaData: RequestMetadata, - next: NextFunction, -) { - asyncStorage.run(requestMetaData, () => { - next(); - }); -} diff --git a/src/main.ts b/src/main.ts index c89e56d..5066589 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,10 +4,15 @@ import { Logger } from 'src/shared/global'; import { ENV_CONFIG } from './config'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule, { + logger: ['error', 'warn', 'log', 'debug'], + }); const logger = new Logger('bootstrap()'); + // Global prefix for all routes + app.setGlobalPrefix(ENV_CONFIG.API_BASE); + // Add an event handler to log uncaught promise rejections and prevent the server from crashing process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled Rejection at:', promise, 'reason:', reason); diff --git a/src/mcp/resources/resources.module.ts b/src/mcp/resources/resources.module.ts new file mode 100644 index 0000000..2b5c8ad --- /dev/null +++ b/src/mcp/resources/resources.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; +import { ChallengesApiSwaggerResource } from './swagger/challenges.resource'; +import { MemberApiSwaggerResource } from './swagger/member.resource'; +import { IdentityApiSwaggerResource } from './swagger/identity.resource'; +import { ReviewApiSwaggerResource } from './swagger/review.resource'; + +@Module({ + imports: [], + controllers: [], + providers: [ + ChallengesApiSwaggerResource, + MemberApiSwaggerResource, + IdentityApiSwaggerResource, + ReviewApiSwaggerResource, + ], +}) +export class ResourcesModule {} diff --git a/src/mcp/resources/swagger/challenges.resource.ts b/src/mcp/resources/swagger/challenges.resource.ts new file mode 100644 index 0000000..ee1642f --- /dev/null +++ b/src/mcp/resources/swagger/challenges.resource.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { Resource } from '@tc/mcp-nest'; +import axios from 'axios'; +import { Logger } from 'src/shared/global'; +import { LogTime } from 'src/shared/global/logTime.decorator'; + +const SPEC_URL = + 'https://raw.githubusercontent.com/topcoder-platform/challenge-api-v6/refs/heads/develop/docs/swagger.yaml'; + +@Injectable() +export class ChallengesApiSwaggerResource { + private readonly logger = new Logger(ChallengesApiSwaggerResource.name); + + @Resource({ + uri: SPEC_URL, + name: 'Challenges V6 API Swagger', + description: 'Swagger documentation for the Challenges V6 API', + mimeType: 'text/yaml', + }) + @LogTime('ChallengesApiSwaggerResource') + async getChallengesApiSwagger() { + this.logger.debug('Fetching Challenges V6 API Swagger'); + // Fetch the content from the URI and return it. + const rawContent = await axios.get(SPEC_URL); + return { + contents: [ + { + uri: SPEC_URL, + mimeType: 'text/yaml', + text: rawContent.data, + }, + ], + }; + } +} diff --git a/src/mcp/resources/swagger/identity.resource.ts b/src/mcp/resources/swagger/identity.resource.ts new file mode 100644 index 0000000..5b9523e --- /dev/null +++ b/src/mcp/resources/swagger/identity.resource.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { Resource } from '@tc/mcp-nest'; +import axios from 'axios'; +import { Logger } from 'src/shared/global'; +import { LogTime } from 'src/shared/global/logTime.decorator'; + +const SPEC_URL = + 'https://raw.githubusercontent.com/topcoder-platform/identity-api-v6/refs/heads/develop/doc/swagger.yaml'; + +@Injectable() +export class IdentityApiSwaggerResource { + private readonly logger = new Logger(IdentityApiSwaggerResource.name); + + @Resource({ + uri: SPEC_URL, + name: 'Identity V6 API Swagger', + description: 'Swagger documentation for the Identity V6 API', + mimeType: 'text/yaml', + }) + @LogTime('IdentityApiSwaggerResource') + async getIdentityApiSwagger() { + this.logger.debug('Fetching Identity V6 API Swagger'); + // Fetch the content from the URI and return it. + const rawContent = await axios.get(SPEC_URL); + return { + contents: [ + { + uri: SPEC_URL, + mimeType: 'text/yaml', + text: rawContent.data, + }, + ], + }; + } +} diff --git a/src/mcp/resources/swagger/member.resource.ts b/src/mcp/resources/swagger/member.resource.ts new file mode 100644 index 0000000..fb9fd6a --- /dev/null +++ b/src/mcp/resources/swagger/member.resource.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { Resource } from '@tc/mcp-nest'; +import axios from 'axios'; +import { Logger } from 'src/shared/global'; +import { LogTime } from 'src/shared/global/logTime.decorator'; + +const SPEC_URL = + 'https://raw.githubusercontent.com/topcoder-platform/member-api-v6/refs/heads/develop/docs/swagger.yaml'; + +@Injectable() +export class MemberApiSwaggerResource { + private readonly logger = new Logger(MemberApiSwaggerResource.name); + + @Resource({ + uri: SPEC_URL, + name: 'Member V6 API Swagger', + description: 'Swagger documentation for the Member V6 API', + mimeType: 'text/yaml', + }) + @LogTime('MemberApiSwaggerResource') + async getMemberApiSwagger() { + this.logger.debug('Fetching Member V6 API Swagger'); + // Fetch the content from the URI and return it. + const rawContent = await axios.get(SPEC_URL); + return { + contents: [ + { + uri: SPEC_URL, + mimeType: 'text/yaml', + text: rawContent.data, + }, + ], + }; + } +} diff --git a/src/mcp/resources/swagger/review.resource.ts b/src/mcp/resources/swagger/review.resource.ts new file mode 100644 index 0000000..73bcadd --- /dev/null +++ b/src/mcp/resources/swagger/review.resource.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@nestjs/common'; +import { Resource } from '@tc/mcp-nest'; +import axios from 'axios'; +import { Logger } from 'src/shared/global'; +import { LogTime } from 'src/shared/global/logTime.decorator'; + +const SPEC_URL = 'https://api.topcoder-dev.com/v6/review/api-docs-yaml'; + +@Injectable() +export class ReviewApiSwaggerResource { + private readonly logger = new Logger(ReviewApiSwaggerResource.name); + + @Resource({ + uri: SPEC_URL, + name: 'Review V6 API Swagger', + description: 'Swagger documentation for the Review V6 API', + mimeType: 'text/yaml', + }) + @LogTime('ReviewApiSwaggerResource') + async getReviewApiSwagger() { + this.logger.debug('Fetching Review V6 API Swagger'); + // Fetch the content from the URI and return it. + const rawContent = await axios.get(SPEC_URL); + return { + contents: [ + { + uri: SPEC_URL, + mimeType: 'text/yaml', + text: rawContent.data, + }, + ], + }; + } +} diff --git a/src/mcp/tools/challenges/queryChallenges.output.ts b/src/mcp/tools/challenges/queryChallenges.output.ts index 447d8ea..a7ee228 100644 --- a/src/mcp/tools/challenges/queryChallenges.output.ts +++ b/src/mcp/tools/challenges/queryChallenges.output.ts @@ -4,6 +4,7 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ page: z.number().describe('Current page number in the paginated response'), nextPage: z .number() + .nullable() .optional() .describe('Next page number, if available in the paginated response'), pageSize: z @@ -18,6 +19,50 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ name: z.string().describe('Challenge title'), typeId: z.string().describe('Type identifier for the challenge'), trackId: z.string().describe('Track identifier for the challenge'), + legacy: z + .object({ + track: z + .string() + .optional() + .describe('Legacy track identifier for the challenge'), + subTrack: z + .string() + .optional() + .describe('Legacy sub-track identifier for the challenge'), + forumId: z + .number() + .optional() + .describe('Legacy forum ID for the challenge'), + directProjectId: z + .number() + .optional() + .describe('Legacy direct project ID for the challenge'), + reviewType: z + .string() + .optional() + .describe('Legacy review type for the challenge'), + confidentialityType: z + .string() + .optional() + .describe('Legacy confidentiality type for the challenge'), + pureV5Task: z + .boolean() + .optional() + .describe('Legacy pure V5 task flag for the challenge'), + reviewScorecardId: z + .number() + .optional() + .describe('Legacy review scorecard ID for the challenge'), + screeningScorecardId: z + .number() + .optional() + .describe('Legacy screening scorecard ID for the challenge'), + selfService: z + .boolean() + .optional() + .describe('Legacy self-service flag for the challenge'), + }) + .optional(), description: z .string() .describe('Detailed description of the challenge'), @@ -25,10 +70,14 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ .string() .describe('Format of the description, e.g., markdown'), metadata: z - .object({ - // Additional metadata fields can be added here - // For example, you can include fields like 'clientId', 'prize', etc - }) + .array( + z.object({ + // Additional metadata fields can be added here + // For example, you can include fields like 'clientId', 'prize', etc + name: z.string().describe('Metadata name'), + value: z.string().describe('Metadata value'), + }), + ) .optional() .describe('Optional metadata associated with the challenge'), timelineTemplateId: z @@ -56,10 +105,30 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ .array( z.object({ name: z.string().describe('Constraint name'), - value: z.string().describe('Constraint value'), + value: z.number().describe('Constraint value'), }), ) .describe('Constraints for the challenge phase'), + actualStartDate: z + .string() + .optional() + .describe( + 'Actual start date of the phase (ISO format, optional)', + ), + description: z + .string() + .optional() + .describe('Description of the phase (optional)'), + predecessor: z + .string() + .optional() + .describe('Identifier of the predecessor phase (optional)'), + actualEndDate: z + .string() + .optional() + .describe( + 'Actual end date of the phase (ISO format, optional)', + ), }), ) .describe('Challenge phases (optional)'), @@ -114,6 +183,10 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ 'Cancelled - Zero Registrations', ]) .describe('Current status of the challenge'), + attachments: z + .array(z.object({}).optional()) + .optional() + .describe('Attachments associated with the challenge (optional)'), track: z .string() .describe('Challenge track (e.g., DEVELOPMENT, DESIGN)'), @@ -131,7 +204,11 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ overview: z .object({ totalPrizes: z.number().describe('Total prize amount'), - types: z.string().describe('Challenge prizes currency'), + type: z.string().optional().describe('Challenge prizes currency'), + totalPrizesInCents: z + .number() + .optional() + .describe('Total prize amount in cents'), }) .describe('Overview of the challenge'), skills: z @@ -168,12 +245,126 @@ export const QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA = z.object({ handle: z .string() .describe('Winner handle on Topcoder platform'), - userId: z.string().describe('Unique identifier for the user'), + userId: z.number().describe('Unique identifier for the user'), placement: z.number().describe('Placement of the winner'), }), ) .optional() .describe('Array of winners for the challenge (optional)'), + createdBy: z.string().describe('User handle of the creator'), + updatedBy: z + .string() + .optional() + .describe('User handle of the last updater'), + currentPhase: z + .object({ + id: z.string().describe('Current phase unique identifier'), + phaseId: z.string().describe('Current phase identifier'), + name: z.string().describe('Current phase name'), + duration: z + .number() + .describe('Current phase duration in seconds'), + scheduledStartDate: z + .string() + .describe( + 'Scheduled start date of the current phase (ISO format)', + ), + scheduledEndDate: z + .string() + .describe( + 'Scheduled end date of the current phase (ISO format)', + ), + isOpen: z + .boolean() + .describe('Indicates if the current phase is open'), + constraints: z + .array( + z.object({ + name: z.string().describe('Constraint name'), + value: z.number().describe('Constraint value'), + }), + ) + .describe('Constraints for the current phase'), + description: z + .string() + .optional() + .describe('Description of the current phase (optional)'), + actualStartDate: z + .string() + .optional() + .describe( + 'Actual start date of the current phase (ISO format)', + ), + predecessor: z + .string() + .optional() + .describe('Identifier of the predecessor phase (optional)'), + actualEndDate: z + .string() + .optional() + .describe( + 'Actual end date of the current phase (ISO format, optional)', + ), + }) + .optional() + .describe('Current phase of the challenge (optional)'), + currentPhaseNames: z + .array(z.string()) + .optional() + .describe( + 'Names of the current phases of the challenge (optional)', + ), + discussions: z + .array( + z.object({ + id: z + .string() + .optional() + .describe('Discussion unique identifier'), + name: z.string().optional().describe('Discussion name'), + type: z.string().optional().describe('Discussion type'), + provider: z.string().optional().describe('Discussion provider'), + url: z.string().optional().describe('URL of the discussion'), + }), + ) + .optional() + .describe('Discussions associated with the challenge (optional)'), + events: z + .array(z.object({})) + .optional() + .describe('Events associated with the challenge (optional)'), + groups: z + .array(z.object({})) + .optional() + .describe('Groups associated with the challenge (optional)'), + legacyId: z + .number() + .optional() + .describe('Legacy identifier for the challenge (optional)'), + projectId: z + .number() + .optional() + .describe('Project identifier for the challenge (optional)'), + numOfCheckpointSubmissions: z + .number() + .optional() + .describe( + 'Number of checkpoint submissions for the challenge (optional)', + ), + task: z + .object({ + isTask: z + .boolean() + .describe('Indicates if the challenge is a task'), + isAssigned: z + .boolean() + .describe('Indicates if the task is assigned'), + memberId: z + .number() + .describe('Member ID of the assigned user (optional)'), + }) + .optional() + .describe('Task information for the challenge (optional)'), }) .describe('Challenge object'), ) diff --git a/src/mcp/tools/challenges/queryChallenges.parameters.ts b/src/mcp/tools/challenges/queryChallenges.parameters.ts index c2ae895..cae0f65 100644 --- a/src/mcp/tools/challenges/queryChallenges.parameters.ts +++ b/src/mcp/tools/challenges/queryChallenges.parameters.ts @@ -36,6 +36,12 @@ export const QUERY_CHALLENGES_TOOL_PARAMETERS = z.object({ .describe( 'Filter by tag name, case-insensitive, partial matches are allowed.', ), + tags: z + .array(z.string()) + .optional() + .describe( + 'Filter by multiple tag names, case-insensitive, partial matches are allowed.', + ), search: z .string() .optional() diff --git a/src/mcp/tools/challenges/queryChallenges.tool.ts b/src/mcp/tools/challenges/queryChallenges.tool.ts index 345c9e6..9dd561d 100644 --- a/src/mcp/tools/challenges/queryChallenges.tool.ts +++ b/src/mcp/tools/challenges/queryChallenges.tool.ts @@ -1,11 +1,11 @@ -// greeting.tool.ts import { Injectable, Inject } from '@nestjs/common'; -import { Tool } from '@rekog/mcp-nest'; +import { Tool } from '@tc/mcp-nest'; import { REQUEST } from '@nestjs/core'; import { QUERY_CHALLENGES_TOOL_PARAMETERS } from './queryChallenges.parameters'; import { TopcoderChallengesService } from 'src/shared/topcoder/challenges.service'; import { Logger } from 'src/shared/global'; import { QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA } from './queryChallenges.output'; +import { LogTime } from 'src/shared/global/logTime.decorator'; @Injectable() export class QueryChallengesTool { @@ -16,18 +16,7 @@ export class QueryChallengesTool { @Inject(REQUEST) private readonly request: any, ) {} - @Tool({ - name: 'query-tc-challenges', - description: - 'Returns a list of public Topcoder challenges based on the query parameters.', - parameters: QUERY_CHALLENGES_TOOL_PARAMETERS, - outputSchema: QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA, - annotations: { - title: 'Query Public Topcoder Challenges', - readOnlyHint: true, - }, - }) - async queryChallenges(params) { + private async _queryChallenges(params) { // Validate the input parameters const validatedParams = QUERY_CHALLENGES_TOOL_PARAMETERS.safeParse(params); if (!validatedParams.success) { @@ -56,10 +45,15 @@ export class QueryChallengesTool { accessToken, ); - if (!challenges.ok) { + if (challenges.status < 200 || challenges.status >= 300) { this.logger.error( `Failed to fetch challenges from Topcoder API: ${challenges.statusText}`, ); + try { + this.logger.error(challenges.data); + } catch (e) { + this.logger.error('Failed to log challenge error', e); + } // Return an error response if the API call fails return { @@ -73,48 +67,48 @@ export class QueryChallengesTool { }; } - // Parse the response as JSON - const challengesData = await challenges.json(); + // Axios response: data is already parsed, headers are plain object + const challengesData = challenges.data; return { content: [ { type: 'text', text: JSON.stringify({ - page: Number(challenges.headers.get('x-page')) || 1, + page: Number(challenges.headers['x-page']) || 1, pageSize: - Number(challenges.headers.get('x-per-page')) || - challengesData.length || + Number(challenges.headers['x-per-page']) || + (Array.isArray(challengesData) ? challengesData.length : 0) || 0, total: - Number(challenges.headers.get('x-total')) || - challengesData.length || + Number(challenges.headers['x-total']) || + (Array.isArray(challengesData) ? challengesData.length : 0) || 0, - nextPage: challenges.headers.get('x-next-page') - ? Number(challenges.headers.get('x-next-page')) + nextPage: challenges.headers['x-next-page'] + ? Number(challenges.headers['x-next-page']) : null, data: challengesData, }), }, ], structuredContent: { - page: Number(challenges.headers.get('x-page')) || 1, + page: Number(challenges.headers['x-page']) || 1, pageSize: - Number(challenges.headers.get('x-per-page')) || - challengesData.length || + Number(challenges.headers['x-per-page']) || + (Array.isArray(challengesData) ? challengesData.length : 0) || 0, total: - Number(challenges.headers.get('x-total')) || - challengesData.length || + Number(challenges.headers['x-total']) || + (Array.isArray(challengesData) ? challengesData.length : 0) || 0, - nextPage: challenges.headers.get('x-next-page') - ? Number(challenges.headers.get('x-next-page')) + nextPage: challenges.headers['x-next-page'] + ? Number(challenges.headers['x-next-page']) : null, data: challengesData, }, }; } catch (error) { - this.logger.error(`Error fetching challenges: ${error.message}`); + this.logger.error(`Error fetching challenges: ${error.message}`, error); return { content: [ { @@ -126,4 +120,20 @@ export class QueryChallengesTool { }; } } + + @Tool({ + name: 'query-tc-challenges', + description: + 'Returns a list of Topcoder challenges based on the query parameters.', + parameters: QUERY_CHALLENGES_TOOL_PARAMETERS, + outputSchema: QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA, + annotations: { + title: 'Query Topcoder Challenges', + readOnlyHint: true, + }, + }) + @LogTime('ChallengesTool') + async queryChallenges(params) { + return this._queryChallenges(params); + } } diff --git a/src/mcp/tools/skills/querySkills.output.ts b/src/mcp/tools/skills/querySkills.output.ts new file mode 100644 index 0000000..5087276 --- /dev/null +++ b/src/mcp/tools/skills/querySkills.output.ts @@ -0,0 +1,37 @@ +import { z } from 'zod'; + +export const QUERY_SKILLS_TOOL_OUTPUT_SCHEMA = z.object({ + page: z.number().describe('Current page number in the paginated response'), + pageSize: z + .number() + .describe( + 'Number of standardized skills per page in the paginated response', + ), + total: z + .number() + .describe('Total number of standardized skills matching the query'), + data: z + .array( + z + .object({ + id: z.string().describe('Unique identifier for the skill'), + name: z.string().describe('Skill name'), + description: z + .string() + .describe('Detailed description of the standardized skill'), + category: z + .object({ + id: z.string().describe('Unique identifier for the category'), + name: z.string().describe('Category name'), + description: z + .string() + .nullable() + .optional() + .describe('Detailed description of the category'), + }) + .describe('Category to which the skill belongs'), + }) + .describe('Standardized skill object'), + ) + .describe("Array of Topcoder's standardized skills"), +}); diff --git a/src/mcp/tools/skills/querySkills.parameters.ts b/src/mcp/tools/skills/querySkills.parameters.ts new file mode 100644 index 0000000..ddafeae --- /dev/null +++ b/src/mcp/tools/skills/querySkills.parameters.ts @@ -0,0 +1,30 @@ +import { z } from 'zod'; + +export const QUERY_SKILLS_TOOL_PARAMETERS = z.object({ + name: z + .array(z.string()) + .optional() + .describe('Filter by skill names, exact match.'), + skillId: z + .array(z.string().uuid()) + .optional() + .describe('Filter by skill IDs, exact match.'), + sortBy: z + .enum(['name', 'description', 'created_at', 'updated_at']) + .optional() + .describe('Sort skills by a specific field'), + sortOrder: z.enum(['ASC', 'DESC']).optional().describe('Sort order'), + page: z + .number() + .gte(1) + .default(1) + .optional() + .describe('Page number for pagination, starting from 1'), + perPage: z + .number() + .gte(1) + .lte(100) + .default(20) + .optional() + .describe('Number of standardized skills per page, between 1 and 100'), +}); diff --git a/src/mcp/tools/skills/querySkills.tool.ts b/src/mcp/tools/skills/querySkills.tool.ts new file mode 100644 index 0000000..91a0db4 --- /dev/null +++ b/src/mcp/tools/skills/querySkills.tool.ts @@ -0,0 +1,133 @@ +import { Injectable, Inject } from '@nestjs/common'; +import { Tool } from '@tc/mcp-nest'; +import { REQUEST } from '@nestjs/core'; +import { Logger } from 'src/shared/global'; +import { QUERY_SKILLS_TOOL_PARAMETERS } from './querySkills.parameters'; +import { QUERY_SKILLS_TOOL_OUTPUT_SCHEMA } from './querySkills.output'; +import { TopcoderSkillsService } from 'src/shared/topcoder/skills.service'; +import { LogTime } from 'src/shared/global/logTime.decorator'; + +@Injectable() +export class QuerySkillsTool { + private readonly logger = new Logger(QuerySkillsTool.name); + + constructor( + private readonly topcoderSkillsService: TopcoderSkillsService, + @Inject(REQUEST) private readonly request: any, + ) {} + + private async _querySkills(params) { + // Validate the input parameters + const validatedParams = QUERY_SKILLS_TOOL_PARAMETERS.safeParse(params); + if (!validatedParams.success) { + this.logger.error( + `Invalid parameters provided: ${JSON.stringify(validatedParams.error.errors)}`, + ); + + // Return an error response with the validation errors + return { + content: [ + { + type: 'text', + text: `Invalid parameters: ${JSON.stringify(validatedParams.error.errors)}`, + }, + ], + isError: true, + }; + } + + // Get the challenges from the Topcoder challenges API + // and handle any errors that may occur + try { + const accessToken = this.request.headers['authorization']?.split(' ')[1]; + const skills = await this.topcoderSkillsService.fetchSkills( + validatedParams.data, + accessToken, + ); + + if (skills.status < 200 || skills.status >= 300) { + this.logger.error( + `Failed to fetch skills from Topcoder API: ${skills.statusText}`, + ); + try { + this.logger.error(skills.data); + } catch (e) { + this.logger.error('Failed to log skills error', e); + } + + // Return an error response if the API call fails + return { + content: [ + { + type: 'text', + text: `Error fetching skills: ${skills.statusText}`, + }, + ], + isError: true, + }; + } + + // Axios response: data is already parsed, headers are plain object + const skillsData = skills.data; + + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + page: Number(skills.headers['x-page']) || 1, + pageSize: + Number(skills.headers['x-per-page']) || + (Array.isArray(skillsData) ? skillsData.length : 0) || + 0, + total: + Number(skills.headers['x-total']) || + (Array.isArray(skillsData) ? skillsData.length : 0) || + 0, + data: skillsData, + }), + }, + ], + structuredContent: { + page: Number(skills.headers['x-page']) || 1, + pageSize: + Number(skills.headers['x-per-page']) || + (Array.isArray(skillsData) ? skillsData.length : 0) || + 0, + total: + Number(skills.headers['x-total']) || + (Array.isArray(skillsData) ? skillsData.length : 0) || + 0, + data: skillsData, + }, + }; + } catch (error) { + this.logger.error(`Error fetching skills: ${error.message}`, error); + return { + content: [ + { + type: 'text', + text: `Error fetching skills: ${error.message}`, + }, + ], + isError: true, + }; + } + } + + @Tool({ + name: 'query-tc-skills', + description: + 'Returns a list of standardized skills from Topcoder platform, filtered and sorted based on the provided parameters.', + parameters: QUERY_SKILLS_TOOL_PARAMETERS, + outputSchema: QUERY_SKILLS_TOOL_OUTPUT_SCHEMA, + annotations: { + title: 'Query Topcoder Standardized Skills', + readOnlyHint: true, + }, + }) + @LogTime('SkillsTool') + async querySkills(params) { + return this._querySkills(params); + } +} diff --git a/src/mcp/tools/tools.module.ts b/src/mcp/tools/tools.module.ts new file mode 100644 index 0000000..a5fc55e --- /dev/null +++ b/src/mcp/tools/tools.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { QueryChallengesTool } from './challenges/queryChallenges.tool'; +import { TopcoderModule } from 'src/shared/topcoder/topcoder.module'; +import { QuerySkillsTool } from './skills/querySkills.tool'; + +@Module({ + imports: [TopcoderModule], + controllers: [], + providers: [QueryChallengesTool, QuerySkillsTool], +}) +export class ToolsModule {} diff --git a/src/shared/global/logTime.decorator.ts b/src/shared/global/logTime.decorator.ts new file mode 100644 index 0000000..cb478fb --- /dev/null +++ b/src/shared/global/logTime.decorator.ts @@ -0,0 +1,32 @@ +import { Logger } from '@nestjs/common'; + +export function LogTime(label?: string) { + const logger = new Logger('ExecutionTime'); + + return function ( + target: any, + propertyKey: string, + descriptor: PropertyDescriptor, + ) { + const originalMethod = descriptor.value; + + descriptor.value = async function (...args: any[]) { + const start = Date.now(); + + try { + const result = await originalMethod.apply(this, args); + const ms = Date.now() - start; + logger.log(`${label || propertyKey} executed in ${ms}ms`); + return result; + } catch (error) { + const ms = Date.now() - start; + logger.error( + `${label || propertyKey} failed after ${ms}ms – ${error.message}`, + ); + throw error; + } + }; + + return descriptor; + }; +} diff --git a/src/shared/global/logger.ts b/src/shared/global/logger.ts index a6c6bb8..93142b7 100644 --- a/src/shared/global/logger.ts +++ b/src/shared/global/logger.ts @@ -1,12 +1,7 @@ import { Logger as NestLogger } from '@nestjs/common'; import * as stringify from 'json-stringify-safe'; -import { getStore } from 'src/core/request/requestStore'; export class Logger extends NestLogger { - private get store() { - return getStore(); - } - log(...messages: any[]): void { super.log(this.formatMessages(messages)); } @@ -24,10 +19,7 @@ export class Logger extends NestLogger { } private formatMessages(messages: any[]): string { - const requestIdPrefix = this.store.requestId - ? [`{${this.store.requestId}}`] - : []; - return [...requestIdPrefix, ...messages] + return [...messages] .map((msg) => // eslint-disable-next-line @typescript-eslint/no-unsafe-return typeof msg === 'object' ? stringify(msg, null, 2) : String(msg), diff --git a/src/shared/global/timingInterceptor.ts b/src/shared/global/timingInterceptor.ts new file mode 100644 index 0000000..a7756ae --- /dev/null +++ b/src/shared/global/timingInterceptor.ts @@ -0,0 +1,25 @@ +import { Injectable, NestMiddleware, Logger } from '@nestjs/common'; + +import { Request, Response, NextFunction } from 'express'; + +@Injectable() +export class TimingInterceptorMiddleware implements NestMiddleware { + private logger = new Logger('TimingInterceptor'); + + use(request: Request, response: Response, next: NextFunction): void { + const { method, originalUrl: url } = request; + const start = Date.now(); + const mcpMethod = request.body?.method; + + response.on('close', () => { + const { statusCode } = response; + const duration = Date.now() - start; + + this.logger.log( + `${method} ${mcpMethod ? `{${mcpMethod}} ` : ''}${url} ${statusCode} took ${duration}ms` + ); + }); + + next(); + } +} \ No newline at end of file diff --git a/src/shared/topcoder/challenges.service.ts b/src/shared/topcoder/challenges.service.ts index 3e30272..92489ab 100644 --- a/src/shared/topcoder/challenges.service.ts +++ b/src/shared/topcoder/challenges.service.ts @@ -3,6 +3,7 @@ import { ENV_CONFIG } from 'src/config'; import { Logger } from 'src/shared/global'; import { QUERY_CHALLENGES_TOOL_PARAMETERS } from 'src/mcp/tools/challenges/queryChallenges.parameters'; import { z } from 'zod'; +import axios from 'axios'; const { TOPCODER_API_BASE_URL } = ENV_CONFIG; @@ -20,11 +21,16 @@ export class TopcoderChallengesService { const url = new URL(`${TOPCODER_API_BASE_URL}/challenges`); Object.entries(queryParams).forEach(([key, value]) => { if (value !== undefined && value !== null) { - url.searchParams.append(key, value.toString()); + if (Array.isArray(value)) { + value.forEach((v) => url.searchParams.append(`${key}[]`, v)); + } else { + url.searchParams.append(key, value.toString()); + } } }); - this.logger.debug(`Fetching challenges from: ${url.toString()}`); + const stringUrl = url.toString(); + this.logger.log(`Fetching challenges from: "${stringUrl}"`); const headers: Record = { 'Content-Type': 'application/json', @@ -34,13 +40,19 @@ export class TopcoderChallengesService { headers['Authorization'] = `Bearer ${accessToken}`; } - this.logger.debug( - `Fetching challenges with headers: ${JSON.stringify(headers)}`, + this.logger.log( + `Fetching challenges with headers: "${JSON.stringify(headers)}"`, ); - return fetch(url.toString(), { - method: 'GET', - headers, - }); + try { + const response = await axios.get(stringUrl, { headers }); + return response; + } catch (error) { + this.logger.error( + `Error fetching challenges: ${JSON.stringify(error)}`, + error, + ); + throw error; + } } } diff --git a/src/shared/topcoder/skills.service.ts b/src/shared/topcoder/skills.service.ts new file mode 100644 index 0000000..16d464c --- /dev/null +++ b/src/shared/topcoder/skills.service.ts @@ -0,0 +1,57 @@ +import { Injectable } from '@nestjs/common'; +import { ENV_CONFIG } from 'src/config'; +import { Logger } from 'src/shared/global'; +import { z } from 'zod'; +import axios from 'axios'; +import { QUERY_SKILLS_TOOL_PARAMETERS } from 'src/mcp/tools/skills/querySkills.parameters'; + +const { TOPCODER_API_BASE_URL } = ENV_CONFIG; + +@Injectable() +export class TopcoderSkillsService { + private readonly logger = new Logger(TopcoderSkillsService.name); + + constructor() {} + + async fetchSkills( + queryParams: z.infer, + accessToken?: string, + ) { + // Format the input parameters + const url = new URL(`${TOPCODER_API_BASE_URL}/standardized-skills/skills`); + Object.entries(queryParams).forEach(([key, value]) => { + if (value !== undefined && value !== null) { + if (Array.isArray(value)) { + value.forEach((v) => url.searchParams.append(key, v)); + } else { + url.searchParams.append(key, value.toString()); + } + } + }); + + const stringUrl = url.toString(); + this.logger.log(`Fetching standardized skills from: "${stringUrl}"`); + + const headers: Record = { + 'Content-Type': 'application/json', + }; + if (accessToken) { + headers['Authorization'] = `Bearer ${accessToken}`; + } + + this.logger.log( + `Fetching standardized skills with headers: "${JSON.stringify(headers)}"`, + ); + + try { + const response = await axios.get(stringUrl, { headers }); + return response; + } catch (error) { + this.logger.error( + `Error fetching challenges: ${JSON.stringify(error)}`, + error, + ); + throw error; + } + } +} diff --git a/src/shared/topcoder/topcoder.module.ts b/src/shared/topcoder/topcoder.module.ts index 4facc65..997146c 100644 --- a/src/shared/topcoder/topcoder.module.ts +++ b/src/shared/topcoder/topcoder.module.ts @@ -1,8 +1,9 @@ import { Module } from '@nestjs/common'; import { TopcoderChallengesService } from './challenges.service'; +import { TopcoderSkillsService } from './skills.service'; @Module({ - providers: [TopcoderChallengesService], - exports: [TopcoderChallengesService], + providers: [TopcoderChallengesService, TopcoderSkillsService], + exports: [TopcoderChallengesService, TopcoderSkillsService], }) export class TopcoderModule {}