diff --git a/cspell/custom-dict.txt b/cspell/custom-dict.txt index 1c4e462d86..d99e317db2 100644 --- a/cspell/custom-dict.txt +++ b/cspell/custom-dict.txt @@ -77,6 +77,7 @@ owasppcitoolkit owtf pentest pentesting +pnpmrc psycopg pygithub pygoat @@ -95,6 +96,7 @@ speakerdeck superfences tiktok tsc +turbopack usefixtures winsrdf wsgi diff --git a/frontend/.pnpmrc b/frontend/.pnpmrc new file mode 100644 index 0000000000..3492a3cff4 --- /dev/null +++ b/frontend/.pnpmrc @@ -0,0 +1,4 @@ +legacy-peer-deps=true +public-hoist-pattern[]=*import-in-the-middle* +public-hoist-pattern[]=*require-in-the-middle* +save-exact=true diff --git a/frontend/docker/Dockerfile b/frontend/docker/Dockerfile index 46c67e5259..e594d3fc6f 100644 --- a/frontend/docker/Dockerfile +++ b/frontend/docker/Dockerfile @@ -11,7 +11,7 @@ RUN npm install --ignore-scripts -g pnpm COPY --chmod=444 package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --ignore-scripts -COPY --chmod=444 .env next.config.ts postcss.config.js tailwind.config.js tsconfig.json ./ +COPY --chmod=444 .env .pnpmrc next.config.ts postcss.config.js tailwind.config.js tsconfig.json ./ COPY --chmod=555 public public COPY --chmod=555 src src @@ -28,7 +28,7 @@ ENV NEXT_TELEMETRY_DISABLED=1 ENV NODE_ENV=production RUN addgroup --system --gid 1001 nodejs && \ -adduser --system --uid 1001 -G nodejs nextjs + adduser --system --uid 1001 -G nodejs nextjs # Copying files with root as owner, so that executing user cannot change the container. COPY --from=builder --chown=root:root --chmod=555 /app/public public diff --git a/frontend/docker/Dockerfile.e2e.test b/frontend/docker/Dockerfile.e2e.test index 2a233e260d..e0b18dfc2e 100644 --- a/frontend/docker/Dockerfile.e2e.test +++ b/frontend/docker/Dockerfile.e2e.test @@ -10,6 +10,6 @@ RUN npm install --ignore-scripts -g pnpm && \ COPY __tests__/e2e __tests__/e2e COPY __tests__/unit/data __tests__/unit/data -COPY next.config.ts postcss.config.js playwright.config.ts tailwind.config.js tsconfig.json ./ +COPY .pnpmrc next.config.ts postcss.config.js playwright.config.ts tailwind.config.js tsconfig.json ./ COPY public public COPY src src diff --git a/frontend/docker/Dockerfile.unit.test b/frontend/docker/Dockerfile.unit.test index ef0efbe54c..87e3eb534b 100644 --- a/frontend/docker/Dockerfile.unit.test +++ b/frontend/docker/Dockerfile.unit.test @@ -10,10 +10,8 @@ RUN npm install --ignore-scripts -g pnpm && \ chown node:node /app COPY __tests__/unit __tests__/unit -COPY jest.config.ts jest.config.ts -COPY jest.setup.ts jest.setup.ts +COPY .pnpmrc jest.config.ts jest.setup.ts tsconfig.json ./ COPY public public COPY src src -COPY tsconfig.json tsconfig.json USER node diff --git a/frontend/next.config.ts b/frontend/next.config.ts index 6b08215d8b..15f1b77ee9 100644 --- a/frontend/next.config.ts +++ b/frontend/next.config.ts @@ -4,6 +4,7 @@ import type { NextConfig } from 'next' const isLocal = process.env.NEXT_PUBLIC_ENVIRONMENT === 'local' const nextConfig: NextConfig = { + devIndicators: false, images: { // This is a list of remote patterns that Next.js will use to determine // if an image is allowed to be loaded from a remote source. @@ -26,7 +27,10 @@ const nextConfig: NextConfig = { }, ], }, - devIndicators: false, + serverExternalPackages: ['import-in-the-middle', 'require-in-the-middle'], + turbopack: { + resolveExtensions: ['.ts', '.tsx', '.mjs', '.json', '.yaml', '.js', '.jsx'], + }, ...(isLocal ? {} : { output: 'standalone' }), } diff --git a/frontend/package.json b/frontend/package.json index fcabf4c55a..02330549fd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,8 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev --port 3000", "build": "next build", + "build:turbo": "next build --turbo", + "dev": "next dev --port 3000", "format": "prettier --log-level warn --write .", "format:check": "prettier --check .", "lint": "eslint . --config eslint.config.mjs --fix --max-warnings=0", @@ -91,6 +92,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "globals": "^16.0.0", "identity-obj-proxy": "^3.0.0", + "import-in-the-middle": "^1.13.1", "jest": "^29.7.0", "jest-axe": "^10.0.0", "jest-environment-jsdom": "^29.7.0", @@ -98,6 +100,7 @@ "postcss": "^8.5.3", "prettier": "^3.5.3", "prettier-plugin-tailwindcss": "^0.6.11", + "require-in-the-middle": "^7.5.2", "tailwindcss": "^3.4.17", "ts-jest": "^29.3.2", "ts-node": "^10.9.2", diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index 25a0611502..03bd804b19 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -26,7 +26,7 @@ export default defineConfig({ trace: 'off', }, webServer: { - command: 'pnpm run build && pnpm run start', + command: 'pnpm run build:turbo && pnpm run start', timeout: 120_000, url: 'http://localhost:3000', }, diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 3259fa4171..11bb57f05a 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -58,7 +58,7 @@ importers: version: 15.3.1 '@sentry/nextjs': specifier: ^9.13.0 - version: 9.13.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(next@15.3.1(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17))) + version: 9.13.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(next@15.3.1(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17))) '@testing-library/user-event': specifier: ^14.6.1 version: 14.6.1(@testing-library/dom@10.4.0) @@ -158,7 +158,7 @@ importers: version: 1.11.21(@swc/helpers@0.5.17) '@swc/jest': specifier: ^0.2.37 - version: 0.2.37(@swc/core@1.11.21(@swc/helpers@0.5.17)) + version: 0.2.38(@swc/core@1.11.21(@swc/helpers@0.5.17)) '@tailwindcss/postcss': specifier: ^4.1.4 version: 4.1.4 @@ -231,6 +231,9 @@ importers: identity-obj-proxy: specifier: ^3.0.0 version: 3.0.0 + import-in-the-middle: + specifier: ^1.13.1 + version: 1.13.1 jest: specifier: ^29.7.0 version: 29.7.0(@types/node@22.14.1)(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@22.14.1)(typescript@5.8.3)) @@ -252,6 +255,9 @@ importers: prettier-plugin-tailwindcss: specifier: ^0.6.11 version: 0.6.11(prettier@3.5.3) + require-in-the-middle: + specifier: ^7.5.2 + version: 7.5.2 tailwindcss: specifier: ^3.4.17 version: 3.4.17(ts-node@10.9.2(@swc/core@1.11.21(@swc/helpers@0.5.17))(@types/node@22.14.1)(typescript@5.8.3)) @@ -2592,8 +2598,8 @@ packages: '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} - '@swc/jest@0.2.37': - resolution: {integrity: sha512-CR2BHhmXKGxTiFr21DYPRHQunLkX3mNIFGFkxBGji6r9uyIR5zftTOVYj1e0sFNMV2H7mf/+vpaglqaryBtqfQ==} + '@swc/jest@0.2.38': + resolution: {integrity: sha512-HMoZgXWMqChJwffdDjvplH53g9G2ALQes3HKXDEdliB/b85OQ0CTSbxG8VSeCwiAn7cOaDVEt4mwmZvbHcS52w==} engines: {npm: '>= 7.0.0'} peerDependencies: '@swc/core': '*' @@ -5918,8 +5924,8 @@ packages: webpack-virtual-modules@0.5.0: resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - webpack@5.99.5: - resolution: {integrity: sha512-q+vHBa6H9qwBLUlHL4Y7L0L1/LlyBKZtS9FHNCQmtayxjI5RKC9yD8gpvLeqGv5lCQp1Re04yi0MF40pf30Pvg==} + webpack@5.99.6: + resolution: {integrity: sha512-TJOLrJ6oeccsGWPl7ujCYuc0pIq2cNsuD6GZDma8i5o5Npvcco/z+NKvZSFsP0/x6SShVb0+X2JK/JHUjKY9dQ==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -8374,8 +8380,8 @@ snapshots: '@react-aria/listbox@3.14.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@react-aria/interactions': 3.24.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/label': 3.7.17(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.24.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/label': 3.7.16(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/selection': 3.23.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-aria/utils': 3.28.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-stately/collections': 3.12.3(react@19.1.0) '@react-stately/list': 3.12.0(react@19.1.0) @@ -8406,17 +8412,17 @@ snapshots: '@react-aria/menu@3.18.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@react-aria/focus': 3.20.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/i18n': 3.12.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/i18n': 3.12.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-aria/interactions': 3.24.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/overlays': 3.27.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-aria/selection': 3.24.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/overlays': 3.26.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-aria/selection': 3.23.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-aria/utils': 3.28.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-stately/collections': 3.12.3(react@19.1.0) '@react-stately/menu': 3.9.2(react@19.1.0) '@react-stately/selection': 3.20.1(react@19.1.0) - '@react-stately/tree': 3.8.8(react@19.1.0) - '@react-types/button': 3.12.0(react@19.1.0) - '@react-types/menu': 3.9.15(react@19.1.0) + '@react-stately/tree': 3.8.9(react@19.1.0) + '@react-types/button': 3.11.0(react@19.1.0) + '@react-types/menu': 3.10.0(react@19.1.0) '@react-types/shared': 3.28.0(react@19.1.0) '@swc/helpers': 0.5.17 react: 19.1.0 @@ -8830,7 +8836,7 @@ snapshots: '@react-stately/menu@3.9.2(react@19.1.0)': dependencies: '@react-stately/overlays': 3.6.15(react@19.1.0) - '@react-types/menu': 3.9.15(react@19.1.0) + '@react-types/menu': 3.10.0(react@19.1.0) '@react-types/shared': 3.28.0(react@19.1.0) '@swc/helpers': 0.5.17 react: 19.1.0 @@ -8930,9 +8936,9 @@ snapshots: '@react-stately/toggle@3.8.2(react@19.1.0)': dependencies: - '@react-stately/utils': 3.10.5(react@19.1.0) + '@react-stately/utils': 3.10.6(react@19.1.0) '@react-types/checkbox': 3.9.3(react@19.1.0) - '@react-types/shared': 3.29.0(react@19.1.0) + '@react-types/shared': 3.28.0(react@19.1.0) '@swc/helpers': 0.5.17 react: 19.1.0 @@ -9157,7 +9163,7 @@ snapshots: '@react-types/textfield@3.12.0(react@19.1.0)': dependencies: - '@react-types/shared': 3.28.0(react@19.1.0) + '@react-types/shared': 3.29.0(react@19.1.0) react: 19.1.0 '@react-types/textfield@3.12.1(react@19.1.0)': @@ -9336,7 +9342,7 @@ snapshots: '@sentry/core@9.13.0': {} - '@sentry/nextjs@9.13.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(next@15.3.1(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17)))': + '@sentry/nextjs@9.13.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(next@15.3.1(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17)))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.32.0 @@ -9347,7 +9353,7 @@ snapshots: '@sentry/opentelemetry': 9.13.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.32.0) '@sentry/react': 9.13.0(react@19.1.0) '@sentry/vercel-edge': 9.13.0 - '@sentry/webpack-plugin': 3.3.1(webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17))) + '@sentry/webpack-plugin': 3.3.1(webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17))) chalk: 3.0.0 next: 15.3.1(@babel/core@7.26.10)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) resolve: 1.22.8 @@ -9424,12 +9430,12 @@ snapshots: '@opentelemetry/api': 1.9.0 '@sentry/core': 9.13.0 - '@sentry/webpack-plugin@3.3.1(webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17)))': + '@sentry/webpack-plugin@3.3.1(webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17)))': dependencies: '@sentry/bundler-plugin-core': 3.3.1 unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17)) + webpack: 5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17)) transitivePeerDependencies: - encoding - supports-color @@ -9501,7 +9507,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@swc/jest@0.2.37(@swc/core@1.11.21(@swc/helpers@0.5.17))': + '@swc/jest@0.2.38(@swc/core@1.11.21(@swc/helpers@0.5.17))': dependencies: '@jest/create-cache-key-function': 29.7.0 '@swc/core': 1.11.21(@swc/helpers@0.5.17) @@ -12517,7 +12523,7 @@ snapshots: dependencies: debug: 4.4.0 module-details-from-path: 1.0.3 - resolve: 1.22.8 + resolve: 1.22.10 transitivePeerDependencies: - supports-color @@ -12929,14 +12935,14 @@ snapshots: tapable@2.2.1: {} - terser-webpack-plugin@5.3.14(@swc/core@1.11.21(@swc/helpers@0.5.17))(webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17))): + terser-webpack-plugin@5.3.14(@swc/core@1.11.21(@swc/helpers@0.5.17))(webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.2 serialize-javascript: 6.0.2 terser: 5.39.0 - webpack: 5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17)) + webpack: 5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17)) optionalDependencies: '@swc/core': 1.11.21(@swc/helpers@0.5.17) @@ -13223,7 +13229,7 @@ snapshots: webpack-virtual-modules@0.5.0: {} - webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17)): + webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.7 @@ -13245,7 +13251,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.2 tapable: 2.2.1 - terser-webpack-plugin: 5.3.14(@swc/core@1.11.21(@swc/helpers@0.5.17))(webpack@5.99.5(@swc/core@1.11.21(@swc/helpers@0.5.17))) + terser-webpack-plugin: 5.3.14(@swc/core@1.11.21(@swc/helpers@0.5.17))(webpack@5.99.6(@swc/core@1.11.21(@swc/helpers@0.5.17))) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: