From 42cbb6c59ed584d7997e838c5d00d621db031b21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 13:01:40 +0000 Subject: [PATCH 1/4] chore(deps): bump react-dom and @types/react-dom in /frontend Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) and [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom). These dependencies needed to be updated together. Updates `react-dom` from 18.3.1 to 19.2.4 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.4/packages/react-dom) Updates `@types/react-dom` from 18.3.1 to 19.2.3 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) --- updated-dependencies: - dependency-name: react-dom dependency-version: 19.2.4 dependency-type: direct:production update-type: version-update:semver-major - dependency-name: "@types/react-dom" dependency-version: 19.2.3 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- frontend/package-lock.json | 36 ++++++++++++++++-------------------- frontend/package.json | 4 ++-- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c7b9a4a..c32d187 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,13 +9,13 @@ "version": "0.1.0", "dependencies": { "react": "18.3.1", - "react-dom": "18.3.1", + "react-dom": "19.2.4", "react-router-dom": "6.28.0" }, "devDependencies": { "@eslint/js": "9.17.0", "@types/react": "18.3.12", - "@types/react-dom": "18.3.1", + "@types/react-dom": "19.2.3", "@vitejs/plugin-react": "4.3.4", "autoprefixer": "10.4.20", "eslint": "9.17.0", @@ -1623,13 +1623,13 @@ } }, "node_modules/@types/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/react": "*" + "peerDependencies": { + "@types/react": "^19.2.0" } }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -4208,16 +4208,15 @@ } }, "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.2.4" } }, "node_modules/react-refresh": { @@ -4424,13 +4423,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", diff --git a/frontend/package.json b/frontend/package.json index 4897938..c9203e2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,13 +14,13 @@ }, "dependencies": { "react": "18.3.1", - "react-dom": "18.3.1", + "react-dom": "19.2.4", "react-router-dom": "6.28.0" }, "devDependencies": { "@eslint/js": "9.17.0", "@types/react": "18.3.12", - "@types/react-dom": "18.3.1", + "@types/react-dom": "19.2.3", "@vitejs/plugin-react": "4.3.4", "autoprefixer": "10.4.20", "eslint": "9.17.0", From 38829b017930acdbd30b7d82149eb057f6391838 Mon Sep 17 00:00:00 2001 From: Karthik Date: Tue, 7 Apr 2026 21:34:28 +0530 Subject: [PATCH 2/4] fix(frontend): align React 19 bump React DOM 19 types require React 19 types; update react and @types/react accordingly and make tests pass when no specs exist. Made-with: Cursor --- frontend/package-lock.json | 308 +++++++++++++++++++++---------------- frontend/package.json | 8 +- 2 files changed, 182 insertions(+), 134 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c32d187..b555cbe 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,13 +8,13 @@ "name": "@pipeline-os/frontend", "version": "0.1.0", "dependencies": { - "react": "18.3.1", + "react": "19.2.4", "react-dom": "19.2.4", "react-router-dom": "6.28.0" }, "devDependencies": { "@eslint/js": "9.17.0", - "@types/react": "18.3.12", + "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@vitejs/plugin-react": "4.3.4", "autoprefixer": "10.4.20", @@ -28,7 +28,7 @@ "prettier": "3.4.2", "tailwindcss": "3.4.16", "typescript": "5.7.2", - "typescript-eslint": "8.19.0", + "typescript-eslint": "8.58.0", "vite": "6.0.6", "vitest": "2.1.8" }, @@ -1604,22 +1604,14 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { @@ -1633,21 +1625,20 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz", - "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz", + "integrity": "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/type-utils": "8.19.0", - "@typescript-eslint/utils": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/type-utils": "8.58.0", + "@typescript-eslint/utils": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1657,23 +1648,33 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "@typescript-eslint/parser": "^8.58.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz", - "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.0.tgz", + "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1683,19 +1684,41 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.0.tgz", + "integrity": "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.58.0", + "@typescript-eslint/types": "^8.58.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", - "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.0.tgz", + "integrity": "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0" + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1705,17 +1728,35 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.0.tgz", + "integrity": "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", - "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.0.tgz", + "integrity": "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/utils": "8.19.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0", + "@typescript-eslint/utils": "8.58.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1725,14 +1766,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", - "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz", + "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==", "dev": true, "license": "MIT", "engines": { @@ -1744,20 +1785,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz", - "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.0.tgz", + "integrity": "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/project-service": "8.58.0", + "@typescript-eslint/tsconfig-utils": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1767,30 +1809,43 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -1810,16 +1865,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", - "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz", + "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/typescript-estree": "8.19.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1829,19 +1884,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", - "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.0.tgz", + "integrity": "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.58.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1851,6 +1906,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitejs/plugin-react": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", @@ -3204,13 +3272,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3444,6 +3505,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3614,18 +3676,6 @@ "dev": true, "license": "MIT" }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, "node_modules/loupe": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", @@ -4196,13 +4246,10 @@ "license": "MIT" }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } @@ -4774,16 +4821,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-interface-checker": { @@ -4821,15 +4868,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.0.tgz", - "integrity": "sha512-Ni8sUkVWYK4KAcTtPjQ/UTiRk6jcsuDhPpxULapUDi8A/l8TSBk+t1GtJA1RsCzIJg0q6+J7bf35AwQigENWRQ==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.0.tgz", + "integrity": "sha512-e2TQzKfaI85fO+F3QywtX+tCTsu/D3WW5LVU6nz8hTFKFZ8yBJ6mSYRpXqdR3mFjPWmO0eWsTa5f+UpAOe/FMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.19.0", - "@typescript-eslint/parser": "8.19.0", - "@typescript-eslint/utils": "8.19.0" + "@typescript-eslint/eslint-plugin": "8.58.0", + "@typescript-eslint/parser": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0", + "@typescript-eslint/utils": "8.58.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4839,8 +4887,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/update-browserslist-db": { diff --git a/frontend/package.json b/frontend/package.json index c9203e2..d0f577f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,16 +10,16 @@ "lint": "eslint . --max-warnings 0", "lint:fix": "eslint . --fix", "format": "prettier --write .", - "test": "vitest run" + "test": "vitest run --passWithNoTests" }, "dependencies": { - "react": "18.3.1", + "react": "19.2.4", "react-dom": "19.2.4", "react-router-dom": "6.28.0" }, "devDependencies": { "@eslint/js": "9.17.0", - "@types/react": "18.3.12", + "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "@vitejs/plugin-react": "4.3.4", "autoprefixer": "10.4.20", @@ -33,7 +33,7 @@ "prettier": "3.4.2", "tailwindcss": "3.4.16", "typescript": "5.7.2", - "typescript-eslint": "8.19.0", + "typescript-eslint": "8.58.0", "vite": "6.0.6", "vitest": "2.1.8" }, From 72dbb14ce905f61fbc5172dc2dcdab51ecc1cf95 Mon Sep 17 00:00:00 2001 From: Karthik Date: Tue, 7 Apr 2026 21:44:14 +0530 Subject: [PATCH 3/4] fix(frontend): restore internal admin client Add missing internal admin API client typings and adjust rule parsing to satisfy updated lint rules. Made-with: Cursor --- frontend/src/api/internalClient.ts | 56 +++++ frontend/src/pages/RemediationRules.tsx | 263 ++++++++++++++++++++++++ frontend/src/vite-env.d.ts | 1 + 3 files changed, 320 insertions(+) create mode 100644 frontend/src/api/internalClient.ts create mode 100644 frontend/src/pages/RemediationRules.tsx diff --git a/frontend/src/api/internalClient.ts b/frontend/src/api/internalClient.ts new file mode 100644 index 0000000..5867e04 --- /dev/null +++ b/frontend/src/api/internalClient.ts @@ -0,0 +1,56 @@ +function internalBaseUrl(): string { + return import.meta.env.VITE_API_URL; +} + +function internalApiKey(): string { + const key = import.meta.env.VITE_INTERNAL_API_KEY; + if (typeof key !== "string" || key.trim() === "") { + throw new Error("VITE_INTERNAL_API_KEY is required for internal admin requests"); + } + return key.trim(); +} + +async function readErrorBody(response: Response): Promise { + try { + return await response.text(); + } catch { + return ""; + } +} + +export async function internalGetJson(path: string): Promise { + const url = `${internalBaseUrl()}${path}`; + const response = await fetch(url, { headers: { "x-internal-api-key": internalApiKey() } }); + if (!response.ok) { + const text = await readErrorBody(response); + throw new Error(`request failed: ${String(response.status)} ${response.statusText} ${text}`); + } + return (await response.json()) as unknown; +} + +export async function internalPostJson(path: string, body: unknown): Promise { + const url = `${internalBaseUrl()}${path}`; + const response = await fetch(url, { + method: "POST", + headers: { + "x-internal-api-key": internalApiKey(), + "content-type": "application/json", + }, + body: JSON.stringify(body), + }); + if (!response.ok) { + const text = await readErrorBody(response); + throw new Error(`request failed: ${String(response.status)} ${response.statusText} ${text}`); + } + return (await response.json()) as unknown; +} + +export async function internalDelete(path: string): Promise { + const url = `${internalBaseUrl()}${path}`; + const response = await fetch(url, { method: "DELETE", headers: { "x-internal-api-key": internalApiKey() } }); + if (!response.ok && response.status !== 204) { + const text = await readErrorBody(response); + throw new Error(`request failed: ${String(response.status)} ${response.statusText} ${text}`); + } +} + diff --git a/frontend/src/pages/RemediationRules.tsx b/frontend/src/pages/RemediationRules.tsx new file mode 100644 index 0000000..eb850f6 --- /dev/null +++ b/frontend/src/pages/RemediationRules.tsx @@ -0,0 +1,263 @@ +import type { ReactElement } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { Link, useSearchParams } from "react-router-dom"; +import { internalDelete, internalGetJson, internalPostJson } from "../api/internalClient"; + +interface Rule { + id: string; + enabled: boolean; + name: string; + match: { pipelineId: string | null; stageName: string | null; anyPatterns: string[]; anyHintSubstrings: string[] }; + action: { type: "retry_stage"; maxAttempts: number; backoffSeconds: number }; + auto: { enabled: boolean; minAttempts: number; disableBelowSuccessRate: number }; + stats: { attempts: number; saves: number; failures: number; successRate: number }; +} + +function asString(value: unknown): string | null { + return typeof value === "string" && value.trim() !== "" ? value : null; +} + +function asNumber(value: unknown): number | null { + return typeof value === "number" && Number.isFinite(value) ? value : null; +} + +function asBool(value: unknown): boolean | null { + return typeof value === "boolean" ? value : null; +} + +function asStringArray(value: unknown): string[] { + if (!Array.isArray(value)) return []; + return value.filter((v): v is string => typeof v === "string"); +} + +function parseRules(payload: unknown): Rule[] { + if (typeof payload !== "object" || payload === null) return []; + const raw = (payload as Record).rules; + if (!Array.isArray(raw)) return []; + const out: Rule[] = []; + for (const r of raw) { + if (typeof r !== "object" || r === null) continue; + const o = r as Record; + const id = asString(o.id); + const name = asString(o.name); + if (!id || !name) continue; + const enabled = o.enabled !== false; + const matchRaw = typeof o.match === "object" && o.match !== null ? (o.match as Record) : {}; + const actionRaw = typeof o.action === "object" && o.action !== null ? (o.action as Record) : null; + const autoRaw = typeof o.auto === "object" && o.auto !== null ? (o.auto as Record) : {}; + const statsRaw = typeof o.stats === "object" && o.stats !== null ? (o.stats as Record) : {}; + if ((actionRaw?.type ?? null) !== "retry_stage") continue; + const maxAttempts = asNumber(actionRaw.maxAttempts) ?? 1; + const backoffSeconds = asNumber(actionRaw.backoffSeconds) ?? 0; + out.push({ + id, + enabled, + name, + match: { + pipelineId: asString(matchRaw.pipelineId), + stageName: asString(matchRaw.stageName), + anyPatterns: asStringArray(matchRaw.anyPatterns), + anyHintSubstrings: asStringArray(matchRaw.anyHintSubstrings), + }, + action: { + type: "retry_stage", + maxAttempts, + backoffSeconds, + }, + auto: { + enabled: asBool(autoRaw.enabled) ?? false, + minAttempts: asNumber(autoRaw.minAttempts) ?? 10, + disableBelowSuccessRate: asNumber(autoRaw.disableBelowSuccessRate) ?? 0.2, + }, + stats: { + attempts: asNumber(statsRaw.attempts) ?? 0, + saves: asNumber(statsRaw.saves) ?? 0, + failures: asNumber(statsRaw.failures) ?? 0, + successRate: asNumber(statsRaw.successRate) ?? 0, + }, + }); + } + return out; +} + +export default function RemediationRules(): ReactElement { + const [params, setParams] = useSearchParams(); + const pipelineId = params.get("pipelineId") ?? ""; + + const [rules, setRules] = useState(undefined); + const [error, setError] = useState(undefined); + const [creating, setCreating] = useState(false); + + const load = useCallback(async (): Promise => { + setError(undefined); + try { + const q = pipelineId ? `?pipelineId=${encodeURIComponent(pipelineId)}` : ""; + const raw = await internalGetJson(`/internal/remediation/rules${q}`); + setRules(parseRules(raw)); + } catch (err) { + setError(err instanceof Error ? err.message : "unknown error"); + setRules(undefined); + } + }, [pipelineId]); + + useEffect(() => { + void load(); + }, [load]); + + const sorted = useMemo(() => { + if (!rules) return []; + return [...rules].sort((a, b) => (b.stats.successRate - a.stats.successRate) || (b.stats.attempts - a.stats.attempts)); + }, [rules]); + + return ( +
+
+
+

Remediation rules

+

Internal admin view (requires `VITE_INTERNAL_API_KEY`).

+
+ + Dashboard + +
+ +
+ +
+ { + if (e.key === "Enter") { + const v = (e.target as HTMLInputElement).value.trim(); + setParams(v ? { pipelineId: v } : {}); + } + }} + /> + + +
+
+ + {error !== undefined ? ( +
{error}
+ ) : null} + +
+
+

Create retry rule

+ +
+

+ This page is intentionally internal-only until user auth exists. Use a separate admin deployment if needed. +

+
+ + {rules === undefined ? ( +

Loading…

+ ) : sorted.length === 0 ? ( +

No rules yet.

+ ) : ( +
+ + + + + + + + + + + + + {sorted.map((r) => ( + + + + + + + + + ))} + +
NameEnabledMatchActionStats
{r.name}{r.enabled ? "true" : "false"} +
pipeline: {r.match.pipelineId ?? "any"}
+
stage: {r.match.stageName ?? "any"}
+
patterns: {r.match.anyPatterns.join(", ") || "—"}
+
+ retry x{String(r.action.maxAttempts)} (backoff {String(r.action.backoffSeconds)}s) + + attempts {String(r.stats.attempts)} · saves {String(r.stats.saves)} · failures {String(r.stats.failures)} ·{" "} + {(r.stats.successRate * 100).toFixed(1)}% + {r.auto.enabled ? auto : null} + + +
+
+ )} +
+ ); +} + diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts index 4ac6adf..3e9ef8a 100644 --- a/frontend/src/vite-env.d.ts +++ b/frontend/src/vite-env.d.ts @@ -3,6 +3,7 @@ interface ImportMetaEnv { readonly VITE_API_URL: string; readonly VITE_WS_URL: string; + readonly VITE_INTERNAL_API_KEY?: string; } interface ImportMeta { From f23f91220580ef534e68afa6efa7abfc2cbc2626 Mon Sep 17 00:00:00 2001 From: Karthik Date: Tue, 7 Apr 2026 21:47:59 +0530 Subject: [PATCH 4/4] fix(frontend): resolve PR6 merge + lint Reset admin client files to match master to avoid merge conflicts, and apply optional chaining to satisfy updated lint rules. Made-with: Cursor --- frontend/src/api/internalClient.ts | 16 +++------------- frontend/src/pages/RemediationRules.tsx | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/frontend/src/api/internalClient.ts b/frontend/src/api/internalClient.ts index 5867e04..5cc0dcf 100644 --- a/frontend/src/api/internalClient.ts +++ b/frontend/src/api/internalClient.ts @@ -10,20 +10,11 @@ function internalApiKey(): string { return key.trim(); } -async function readErrorBody(response: Response): Promise { - try { - return await response.text(); - } catch { - return ""; - } -} - export async function internalGetJson(path: string): Promise { const url = `${internalBaseUrl()}${path}`; const response = await fetch(url, { headers: { "x-internal-api-key": internalApiKey() } }); if (!response.ok) { - const text = await readErrorBody(response); - throw new Error(`request failed: ${String(response.status)} ${response.statusText} ${text}`); + throw new Error(`request failed: ${String(response.status)} ${response.statusText}`); } return (await response.json()) as unknown; } @@ -39,7 +30,7 @@ export async function internalPostJson(path: string, body: unknown): Promise ""); throw new Error(`request failed: ${String(response.status)} ${response.statusText} ${text}`); } return (await response.json()) as unknown; @@ -49,8 +40,7 @@ export async function internalDelete(path: string): Promise { const url = `${internalBaseUrl()}${path}`; const response = await fetch(url, { method: "DELETE", headers: { "x-internal-api-key": internalApiKey() } }); if (!response.ok && response.status !== 204) { - const text = await readErrorBody(response); - throw new Error(`request failed: ${String(response.status)} ${response.statusText} ${text}`); + throw new Error(`request failed: ${String(response.status)} ${response.statusText}`); } } diff --git a/frontend/src/pages/RemediationRules.tsx b/frontend/src/pages/RemediationRules.tsx index eb850f6..28ba736 100644 --- a/frontend/src/pages/RemediationRules.tsx +++ b/frontend/src/pages/RemediationRules.tsx @@ -46,7 +46,7 @@ function parseRules(payload: unknown): Rule[] { const actionRaw = typeof o.action === "object" && o.action !== null ? (o.action as Record) : null; const autoRaw = typeof o.auto === "object" && o.auto !== null ? (o.auto as Record) : {}; const statsRaw = typeof o.stats === "object" && o.stats !== null ? (o.stats as Record) : {}; - if ((actionRaw?.type ?? null) !== "retry_stage") continue; + if (actionRaw?.type !== "retry_stage") continue; const maxAttempts = asNumber(actionRaw.maxAttempts) ?? 1; const backoffSeconds = asNumber(actionRaw.backoffSeconds) ?? 0; out.push({