]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Chore: Add codecov bundle analysis (#7673)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Wed, 11 Sep 2024 00:41:31 +0000 (17:41 -0700)
committershamoon <4887959+shamoon@users.noreply.github.com>
Wed, 11 Sep 2024 00:55:12 +0000 (17:55 -0700)
.codecov.yml
.github/workflows/ci.yml
src-ui/angular.json
src-ui/extra-webpack.config.ts [new file with mode: 0644]
src-ui/package-lock.json
src-ui/package.json

index d3d07003c624ff789cc6557df01d37b35bbe2eee..331e3a2834b43b22331e2dde7c568034b1bfd4cd 100644 (file)
@@ -14,6 +14,8 @@ flag_management:
 # codecov will only comment if coverage changes
 comment:
   require_changes: true
+  require_bundle_changes: true
+  bundle_change_threshold: "1Kb"
 coverage:
   status:
     project:
index b0092cb1c0b4cc6074a88273683cd38a850f60bd..a7228ed8be1bb73d5d61baeb541cc91f11dc042d 100644 (file)
@@ -260,7 +260,7 @@ jobs:
           retention-days: 7
 
   tests-coverage-upload:
-    name: "Upload Coverage"
+    name: "Upload to Codecov"
     runs-on: ubuntu-22.04
     needs:
       - tests-backend
@@ -306,6 +306,30 @@ jobs:
           # future expansion
           flags: backend
           directory: src/
+      -
+        name: Use Node.js 20
+        uses: actions/setup-node@v4
+        with:
+          node-version: 20.x
+          cache: 'npm'
+          cache-dependency-path: 'src-ui/package-lock.json'
+      -
+        name: Cache frontend dependencies
+        id: cache-frontend-deps
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/.npm
+            ~/.cache
+          key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
+      -
+        name: Re-link Angular cli
+        run: cd src-ui && npm link @angular/cli
+      -
+        name: Build frontend and upload analysis
+        env:
+          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+        run: cd src-ui && ng build --configuration=production
 
   build-docker-image:
     name: Build Docker image for ${{ github.ref_name }}
index 7e8b38c872a0c7ada4e8a64d53d6859f45aaa389..f15d3a096be3c0385a5721ac8598066ac0f14424 100644 (file)
       },
       "architect": {
         "build": {
-          "builder": "@angular-devkit/build-angular:browser",
+          "builder": "@angular-builders/custom-webpack:browser",
           "options": {
+            "customWebpackConfig": {
+                "path": "./extra-webpack.config.ts"
+            },
             "outputPath": "dist/paperless-ui",
             "outputHashing": "none",
             "index": "src/index.html",
           "defaultConfiguration": ""
         },
         "serve": {
-          "builder": "@angular-devkit/build-angular:dev-server",
+          "builder": "@angular-builders/custom-webpack:dev-server",
           "options": {
             "buildTarget": "paperless-ui:build:en-US"
           },
           }
         },
         "extract-i18n": {
-          "builder": "@angular-devkit/build-angular:extract-i18n",
+          "builder": "@angular-builders/custom-webpack:extract-i18n",
           "options": {
             "buildTarget": "paperless-ui:build"
           }
diff --git a/src-ui/extra-webpack.config.ts b/src-ui/extra-webpack.config.ts
new file mode 100644 (file)
index 0000000..b53892f
--- /dev/null
@@ -0,0 +1,24 @@
+import * as webpack from 'webpack'
+import {
+  CustomWebpackBrowserSchema,
+  TargetOptions,
+} from '@angular-builders/custom-webpack'
+const { codecovWebpackPlugin } = require('@codecov/webpack-plugin')
+
+export default (
+  config: webpack.Configuration,
+  options: CustomWebpackBrowserSchema,
+  targetOptions: TargetOptions
+) => {
+  if (config.plugins) {
+    config.plugins.push(
+      codecovWebpackPlugin({
+        enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined,
+        bundleName: 'paperless-ngx',
+        uploadToken: process.env.CODECOV_TOKEN,
+      })
+    )
+  }
+
+  return config
+}
index a913dfcb367f6fe09d71a50b48d178a7a59fb986..21251cca38be3dee1e7e6f2dd6ee6664883eb8f1 100644 (file)
@@ -37,6 +37,7 @@
         "zone.js": "^0.14.8"
       },
       "devDependencies": {
+        "@angular-builders/custom-webpack": "^18.0.0",
         "@angular-builders/jest": "^18.0.0",
         "@angular-devkit/build-angular": "^18.2.2",
         "@angular-devkit/core": "^18.2.2",
@@ -48,6 +49,7 @@
         "@angular-eslint/template-parser": "18.3.0",
         "@angular/cli": "~18.2.2",
         "@angular/compiler-cli": "~18.2.2",
+        "@codecov/webpack-plugin": "^1.0.1",
         "@playwright/test": "^1.46.1",
         "@types/jest": "^29.5.12",
         "@types/node": "^22.0.2",
         "node": ">=0.10.0"
       }
     },
+    "node_modules/@actions/core": {
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
+      "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@actions/http-client": "^2.0.1",
+        "uuid": "^8.3.2"
+      }
+    },
+    "node_modules/@actions/core/node_modules/uuid": {
+      "version": "8.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/@actions/github": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz",
+      "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@actions/http-client": "^2.2.0",
+        "@octokit/core": "^5.0.1",
+        "@octokit/plugin-paginate-rest": "^9.0.0",
+        "@octokit/plugin-rest-endpoint-methods": "^10.0.0"
+      }
+    },
+    "node_modules/@actions/http-client": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
+      "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "tunnel": "^0.0.6",
+        "undici": "^5.25.4"
+      }
+    },
     "node_modules/@ampproject/remapping": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
         "node": "^14.20.0 || ^16.13.0 || >=18.10.0"
       }
     },
+    "node_modules/@angular-builders/custom-webpack": {
+      "version": "18.0.0",
+      "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-18.0.0.tgz",
+      "integrity": "sha512-XSynPSXHq5+nrh7J2snfrcbvm6YGwUGQRzr7OuO3wURJ6CHOD9C+xEAmvEUWW8c1YjEslVNG7aLtCGz7LA4ymw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@angular-builders/common": "2.0.0",
+        "@angular-devkit/architect": ">=0.1800.0 < 0.1900.0",
+        "@angular-devkit/build-angular": "^18.0.0",
+        "@angular-devkit/core": "^18.0.0",
+        "lodash": "^4.17.15",
+        "webpack-merge": "^5.7.3"
+      },
+      "engines": {
+        "node": "^14.20.0 || ^16.13.0 || >=18.10.0"
+      },
+      "peerDependencies": {
+        "@angular/compiler-cli": "^18.0.0"
+      }
+    },
+    "node_modules/@angular-builders/custom-webpack/node_modules/webpack-merge": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
+      "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "clone-deep": "^4.0.1",
+        "flat": "^5.0.2",
+        "wildcard": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
     "node_modules/@angular-builders/jest": {
       "version": "18.0.0",
       "resolved": "https://registry.npmjs.org/@angular-builders/jest/-/jest-18.0.0.tgz",
       "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
       "dev": true
     },
+    "node_modules/@codecov/bundler-plugin-core": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@codecov/bundler-plugin-core/-/bundler-plugin-core-1.0.1.tgz",
+      "integrity": "sha512-Uo150Qb2s/mMqqfZMdh6rC1+Cp+bCij5DAB6LqWNI6J9dGbimeNvpU1+jdQ6vlMJOiz5w5jAOhtgZvFNrc8jUw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@actions/core": "^1.10.1",
+        "@actions/github": "^6.0.0",
+        "chalk": "4.1.2",
+        "semver": "^7.5.4",
+        "unplugin": "^1.10.1",
+        "zod": "^3.22.4"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@codecov/bundler-plugin-core/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/@codecov/bundler-plugin-core/node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/@codecov/bundler-plugin-core/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/@codecov/bundler-plugin-core/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@codecov/bundler-plugin-core/node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@codecov/bundler-plugin-core/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@codecov/webpack-plugin": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@codecov/webpack-plugin/-/webpack-plugin-1.0.1.tgz",
+      "integrity": "sha512-e6VpcP3adF5ig2OXjb/mrdZ4o8gluKc/IvTAAZfhjX4CWIsnuyRQqFobKyC9nKMRWpIGCsuxdmamyQSrfwXIUw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@codecov/bundler-plugin-core": "^1.0.1",
+        "unplugin": "^1.10.1"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "peerDependencies": {
+        "webpack": "5.x"
+      }
+    },
     "node_modules/@cspotcode/source-map-support": {
       "version": "0.8.1",
       "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
+    "node_modules/@fastify/busboy": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
+      "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/@humanwhocodes/module-importer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
         "node": "^16.13.0 || >=18.0.0"
       }
     },
+    "node_modules/@octokit/auth-token": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
+      "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/@octokit/core": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz",
+      "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/auth-token": "^4.0.0",
+        "@octokit/graphql": "^7.1.0",
+        "@octokit/request": "^8.3.1",
+        "@octokit/request-error": "^5.1.0",
+        "@octokit/types": "^13.0.0",
+        "before-after-hook": "^2.2.0",
+        "universal-user-agent": "^6.0.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/@octokit/endpoint": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz",
+      "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/types": "^13.1.0",
+        "universal-user-agent": "^6.0.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/@octokit/graphql": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz",
+      "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/request": "^8.3.0",
+        "@octokit/types": "^13.0.0",
+        "universal-user-agent": "^6.0.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/@octokit/openapi-types": {
+      "version": "22.2.0",
+      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz",
+      "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/plugin-paginate-rest": {
+      "version": "9.2.1",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz",
+      "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/types": "^12.6.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      },
+      "peerDependencies": {
+        "@octokit/core": "5"
+      }
+    },
+    "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
+      "version": "20.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+      "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
+      "version": "12.6.0",
+      "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+      "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^20.0.0"
+      }
+    },
+    "node_modules/@octokit/plugin-rest-endpoint-methods": {
+      "version": "10.4.1",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
+      "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/types": "^12.6.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      },
+      "peerDependencies": {
+        "@octokit/core": "5"
+      }
+    },
+    "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
+      "version": "20.0.0",
+      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
+      "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
+      "version": "12.6.0",
+      "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
+      "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^20.0.0"
+      }
+    },
+    "node_modules/@octokit/request": {
+      "version": "8.4.0",
+      "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz",
+      "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/endpoint": "^9.0.1",
+        "@octokit/request-error": "^5.1.0",
+        "@octokit/types": "^13.1.0",
+        "universal-user-agent": "^6.0.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/@octokit/request-error": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz",
+      "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/types": "^13.1.0",
+        "deprecation": "^2.0.0",
+        "once": "^1.4.0"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/@octokit/types": {
+      "version": "13.5.0",
+      "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz",
+      "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@octokit/openapi-types": "^22.2.0"
+      }
+    },
     "node_modules/@pkgjs/parseargs": {
       "version": "0.11.0",
       "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
       "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
       "dev": true,
+      "license": "MIT",
       "bin": {
         "acorn": "bin/acorn"
       },
       "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
       "dev": true
     },
+    "node_modules/before-after-hook": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
+      "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
+      "dev": true,
+      "license": "Apache-2.0"
+    },
     "node_modules/big.js": {
       "version": "5.2.2",
       "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
         "node": ">= 0.8"
       }
     },
+    "node_modules/deprecation": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+      "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
+      "dev": true,
+      "license": "ISC"
+    },
     "node_modules/dequal": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
         "node": "^16.14.0 || >=18.0.0"
       }
     },
+    "node_modules/tunnel": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+      }
+    },
     "node_modules/type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
         "node": ">=14.17"
       }
     },
+    "node_modules/undici": {
+      "version": "5.28.4",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
+      "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@fastify/busboy": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=14.0"
+      }
+    },
     "node_modules/undici-types": {
       "version": "6.19.8",
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
         "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
       }
     },
+    "node_modules/universal-user-agent": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
+      "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==",
+      "dev": true,
+      "license": "ISC"
+    },
     "node_modules/universalify": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
         "node": ">= 0.8"
       }
     },
+    "node_modules/unplugin": {
+      "version": "1.14.0",
+      "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.0.tgz",
+      "integrity": "sha512-cfkZeALGyW7tKYjZbi0G+pn0XnUFa0QvLIeLJEUUlnU0R8YYsBQnt5+h9Eu1B7AB7KETld+UBFI5lOeBL+msoQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "acorn": "^8.12.1",
+        "webpack-virtual-modules": "^0.6.2"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "webpack-sources": "^3"
+      },
+      "peerDependenciesMeta": {
+        "webpack-sources": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/update-browserslist-db": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
         }
       }
     },
+    "node_modules/webpack-virtual-modules": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+      "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/webpack/node_modules/ajv": {
       "version": "6.12.6",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
       "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz",
       "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==",
       "dev": true,
+      "license": "MIT",
       "engines": {
         "node": ">=18"
       },
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/zod": {
+      "version": "3.23.8",
+      "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+      "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/colinhacks"
+      }
+    },
     "node_modules/zone.js": {
       "version": "0.14.10",
       "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz",
index e627aef4da11e1f5f0a6a818b1778dfef3c226d7..ef0bf17bc2947728f075ee41b4a42e2fd5215731 100644 (file)
@@ -39,6 +39,7 @@
     "zone.js": "^0.14.8"
   },
   "devDependencies": {
+    "@angular-builders/custom-webpack": "^18.0.0",
     "@angular-builders/jest": "^18.0.0",
     "@angular-devkit/build-angular": "^18.2.2",
     "@angular-devkit/core": "^18.2.2",
@@ -50,6 +51,7 @@
     "@angular-eslint/template-parser": "18.3.0",
     "@angular/cli": "~18.2.2",
     "@angular/compiler-cli": "~18.2.2",
+    "@codecov/webpack-plugin": "^1.0.1",
     "@playwright/test": "^1.46.1",
     "@types/jest": "^29.5.12",
     "@types/node": "^22.0.2",