diff --git a/.dockerignore b/.dockerignore index cd72327409..75451b0cdf 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ # Except the following. !.env +!.npmrc !.parcelrc !dev-requirements.txt !docs/user_guide diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 6e6a7d95b9..5442bcd6f1 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -19,6 +19,8 @@ permissions: # added using https://github.com/step-security/secure-workflows jobs: lint_build: runs-on: ubuntu-latest + env: + npm_config_ignore_scripts: true strategy: matrix: node-version: [22] @@ -41,13 +43,19 @@ jobs: uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: ${{ matrix.node-version }} - - run: npm ci - - run: npm run fmt-frontend-check - - run: npm run lint - - run: npm run build + - name: Install dependencies + run: npm ci --ignore-scripts + - name: Format-check frontend + run: npm run fmt-frontend-check + - name: Lint frontend + run: npm run lint + - name: Build frontend + run: npm run build test_coverage: runs-on: ubuntu-latest + env: + npm_config_ignore_scripts: true strategy: matrix: node-version: [22] @@ -70,7 +78,8 @@ jobs: uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: ${{ matrix.node-version }} - - run: npm ci + - name: Install dependencies + run: npm ci --ignore-scripts - name: Run tests and generate coverage run: npm run test-frontend:coverage env: diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000000..97b895e2f9 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +ignore-scripts=true diff --git a/Dockerfile b/Dockerfile index 7ac2715275..382bfdc04a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,8 +28,9 @@ FROM node:22.21.1-bookworm-slim@sha256:4de72fb3998934a953f1bee37f0e0254b27c53520 WORKDIR /app # Install app dependencies. +COPY .npmrc ./ COPY package*.json ./ -RUN npm ci +RUN npm ci --ignore-scripts # Build application. COPY . ./ diff --git a/package-lock.json b/package-lock.json index a7e39efa07..66cfa40526 100644 --- a/package-lock.json +++ b/package-lock.json @@ -98,7 +98,6 @@ "jest-environment-jsdom": "~30.2.0", "jest-resolve": "~30.2.0", "jest-watch-typeahead": "~3.0.1", - "license-checker-rseidelsohn": "~4.4.2", "npm-run-all": "~4.1.5", "parcel": "~2.16.0", "parcel-reporter-static-files-copy": "~1.5.3", @@ -3711,32 +3710,6 @@ "node": ">= 8" } }, - "node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", - "dev": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@parcel/bundler-default": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.16.0.tgz", @@ -7016,16 +6989,6 @@ "win32" ] }, - "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -7181,16 +7144,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-includes": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", @@ -10097,29 +10050,6 @@ "react-is": "^16.7.0" } }, - "node_modules/hosted-git-info": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", - "integrity": "sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -12295,46 +12225,6 @@ "node": ">= 0.8.0" } }, - "node_modules/license-checker-rseidelsohn": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/license-checker-rseidelsohn/-/license-checker-rseidelsohn-4.4.2.tgz", - "integrity": "sha512-Sf8WaJhd2vELvCne+frS9AXqnY/vv591s2/nZcJDwTnoNgltG4mAmoenffVb8L2YPRYbxARLyrHJBC38AVfpuA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "chalk": "4.1.2", - "debug": "^4.3.4", - "lodash.clonedeep": "^4.5.0", - "mkdirp": "^1.0.4", - "nopt": "^7.2.0", - "read-installed-packages": "^2.0.1", - "semver": "^7.3.5", - "spdx-correct": "^3.1.1", - "spdx-expression-parse": "^3.0.1", - "spdx-satisfies": "^5.0.1", - "treeify": "^1.1.0" - }, - "bin": { - "license-checker-rseidelsohn": "bin/license-checker-rseidelsohn.js" - }, - "engines": { - "node": ">=18", - "npm": ">=8" - } - }, - "node_modules/license-checker-rseidelsohn/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/lightningcss": { "version": "1.30.2", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", @@ -12704,13 +12594,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -12962,19 +12845,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/moo-color": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", @@ -13219,51 +13089,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -13305,16 +13130,6 @@ "node": ">=6" } }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -14434,53 +14249,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/read-installed-packages": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/read-installed-packages/-/read-installed-packages-2.0.1.tgz", - "integrity": "sha512-t+fJOFOYaZIjBpTVxiV8Mkt7yQyy4E6MSrrnt5FmPd4enYvpU/9DYGirDmN1XQwkfeuWIhM/iu0t2rm6iSr0CA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "debug": "^4.3.4", - "read-package-json": "^6.0.0", - "semver": "2 || 3 || 4 || 5 || 6 || 7", - "slide": "~1.1.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.2" - } - }, - "node_modules/read-package-json": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", - "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", - "deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -15133,16 +14901,6 @@ "node": ">=8" } }, - "node_modules/slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "*" - } - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -15183,18 +14941,6 @@ "node": ">=0.10.0" } }, - "node_modules/spdx-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", - "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-find-index": "^1.0.2", - "spdx-expression-parse": "^3.0.0", - "spdx-ranges": "^2.0.0" - } - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -15231,25 +14977,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/spdx-ranges": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", - "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", - "dev": true, - "license": "(MIT AND CC-BY-3.0)" - }, - "node_modules/spdx-satisfies": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-5.0.1.tgz", - "integrity": "sha512-Nwor6W6gzFp8XX4neaKQ7ChV4wmpSh2sSDemMFSzHxpTw460jxFYeOn+jq4ybnSSw/5sc3pjka9MQPouksQNpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-compare": "^1.0.0", - "spdx-expression-parse": "^3.0.0", - "spdx-ranges": "^2.0.0" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -15862,16 +15589,6 @@ "node": ">=18" } }, - "node_modules/treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", diff --git a/package.json b/package.json index 1ad63c69d5..d534e44bf6 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "predatabase": "node scripts/setupMongo.js", "database": "mongod --dbpath=./mongo_database", "drop-database": "tsc scripts/dropDB.ts && node scripts/dropDB.js", - "find-circular-deps": "npx -y madge -c src/index.tsx --ts-config tsconfig.json", + "find-circular-deps": "npx --ignore-scripts -y madge -c src/index.tsx --ts-config tsconfig.json", "fmt-backend": " dotnet format && dotnet format Backend.Tests", "fmt-backend-check": "dotnet format --verify-no-changes && dotnet format --verify-no-changes Backend.Tests", "fmt-frontend": " prettier --write \"./{.github,.vscode,deploy,docs,maintenance,public,scripts,src}/**/*.{js,jsx,ts,tsx,json,md,yml,yaml}\"", @@ -22,19 +22,20 @@ "license-report-backend": "nuget-license --include-transitive --input ./Backend/BackendFramework.csproj --output JsonPretty > docs/user_guide/assets/licenses/backend_licenses.json | exit 0", "postlicense-report-backend": "tsc scripts/createBackendLicenses.ts && node scripts/createBackendLicenses.js", "license-summary-backend": "nuget-license --include-transitive --input ./Backend/BackendFramework.csproj", - "license-report-frontend": " npm i && license-checker-rseidelsohn --production --excludePrivatePackages --plainVertical --out docs/user_guide/assets/licenses/frontend_licenses.txt", - "license-summary-frontend": "npm i && license-checker-rseidelsohn --production --excludePrivatePackages --summary", + "license-frontend": "npx --ignore-scripts -y license-checker-rseidelsohn --production --excludePrivatePackages", + "license-report-frontend": " npm run license-frontend -- --plainVertical --out docs/user_guide/assets/licenses/frontend_licenses.txt", + "license-summary-frontend": "npm run license-frontend -- --summary", "lint": " eslint --max-warnings=0 --ext js,ts,tsx,jsx src", "lint:fix-layout": "eslint --max-warnings=0 --ext js,ts,tsx,jsx src --fix --fix-type layout,suggestion", "set-admin-user": "tsc scripts/setAdminUser.ts && node scripts/setAdminUser.js", - "start": "npm i && run-p backend database frontend", + "start": "npm i --ignore-scripts && run-p backend database frontend", "test": "run-s test-backend test-frontend", "test-backend": " dotnet test Backend.Tests/Backend.Tests.csproj", "test-backend:coverage": "dotnet test Backend.Tests/Backend.Tests.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:Threshold=77", "test-frontend": " node scripts/jestTest.js", "test-frontend:coverage": "node scripts/jestTest.js --coverage --watchAll=false", "test-frontend:debug": " node --inspect-brk scripts/jestTest.js --runInBand --no-cache", - "wordlist": "npx -y hunspell-reader words" + "wordlist": "npx --ignore-scripts -y hunspell-reader words" }, "dependencies": { "@emotion/react": "~11.14.0", @@ -126,7 +127,6 @@ "jest-environment-jsdom": "~30.2.0", "jest-resolve": "~30.2.0", "jest-watch-typeahead": "~3.0.1", - "license-checker-rseidelsohn": "~4.4.2", "npm-run-all": "~4.1.5", "parcel": "~2.16.0", "parcel-reporter-static-files-copy": "~1.5.3",