From cd303b529671abdf0247c6d6c5cbb66dc9469d6a Mon Sep 17 00:00:00 2001 From: Guillaume Vincent Date: Mon, 28 Sep 2026 10:34:05 +0200 Subject: [PATCH] refactor(console): enable TypeScript strict mode Set "strict": true in tsconfig.json and fix the resulting type errors: narrow caught errors via `err instanceof Error`, type the router compat hooks and API response shapes, and add ambient declarations for CSS imports. Signed-off-by: Guillaume Vincent --- .../tests/install-pattern-page.cy.ts | 6 +- console/package.json | 10 +-- console/src/api.ts | 63 ++++++++++----- console/src/components/InstallPatternPage.tsx | 5 +- console/src/components/ManageSecretsPage.tsx | 3 +- console/src/components/PatternCard.tsx | 12 ++- .../src/components/UninstallPatternPage.tsx | 6 +- console/src/declarations.d.ts | 2 + console/src/hooks/useLocalStorage.ts | 8 +- console/src/hooks/useNavigateCompat.ts | 12 ++- console/src/hooks/useParamsCompat.ts | 15 +++- console/tsconfig.json | 2 +- console/yarn.lock | 78 +++++++++++++++++-- 13 files changed, 164 insertions(+), 58 deletions(-) create mode 100644 console/src/declarations.d.ts diff --git a/console/integration-tests/tests/install-pattern-page.cy.ts b/console/integration-tests/tests/install-pattern-page.cy.ts index 21c47ce9f..609c315e6 100644 --- a/console/integration-tests/tests/install-pattern-page.cy.ts +++ b/console/integration-tests/tests/install-pattern-page.cy.ts @@ -58,8 +58,10 @@ describe('Install Pattern Page', () => { it('has Install and Cancel buttons', () => { navigateToInstallPage(); - cy.contains('button', 'Install').scrollIntoView().should('be.visible'); - cy.contains('button', 'Cancel').scrollIntoView().should('be.visible'); + cy.contains('button', 'Install').scrollIntoView(); + cy.contains('button', 'Install').should('be.visible'); + cy.contains('button', 'Cancel').scrollIntoView(); + cy.contains('button', 'Cancel').should('be.visible'); }); it('Cancel button returns to the catalog', () => { diff --git a/console/package.json b/console/package.json index b5d158709..ab19a5058 100644 --- a/console/package.json +++ b/console/package.json @@ -14,7 +14,7 @@ "build-dev": "yarn clean && yarn webpack", "start": "concurrently --kill-others -c auto -n \"console,wds,ui-catalog\" -p \"{name}:{pid}\" \"yarn run start:console\" \"yarn run start:wds\" \"yarn run start:ui-catalog\"", "start:wds": "PATTERN_UI_CATALOG_BASE_URL=http://localhost:8080 yarn run webpack -- serve --progress", - "start:console": "CONSOLE_VERSION=4.20.0 scripts/console.sh", + "start:console": "CONSOLE_VERSION=4.19.0 scripts/console.sh", "start:ui-catalog": "scripts/catalog.sh", "i18n": "./i18n-scripts/build-i18n.sh && node ./i18n-scripts/set-english-defaults.js", "lint": "yarn eslint src integration-tests --fix && stylelint 'src/**/*.css' --allow-empty-input --fix", @@ -61,15 +61,15 @@ "react-dom": "^17.0.1", "react-helmet": "^6.1.0", "react-i18next": "^11.7.3", - "react-router": "5.3.x", - "react-router-dom": "5.3.x", + "react-router": "~5.3.4", + "react-router-dom": "~5.3.4", "style-loader": "^3.3.1", "stylelint": "^15.3.0", "stylelint-config-standard": "^31.0.0", "ts-loader": "^9.3.1", "ts-node": "^10.8.1", - "typescript": "^5.7.2", - "webpack": "^5.75.0", + "typescript": "^5.9.3", + "webpack": "^5.107.2", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.2.1" }, diff --git a/console/src/api.ts b/console/src/api.ts index 94d53c794..1ebcb0342 100644 --- a/console/src/api.ts +++ b/console/src/api.ts @@ -41,7 +41,7 @@ export async function fetchCatalogImage(): Promise { const data = await response.json(); const containers = data.spec?.template?.spec?.containers || []; const catalogContainer = containers.find( - (c: any) => c.name === 'patterns-operator-pattern-ui-catalog', + (c: { name?: string }) => c.name === 'patterns-operator-pattern-ui-catalog', ); return catalogContainer?.image || 'unknown'; } catch (error) { @@ -77,11 +77,19 @@ export async function fetchAllPatterns(): Promise<{ }; } +export interface ResourceCondition { + type?: string; + status?: string; + reason?: string; + message?: string; + lastTransitionTime?: string; +} + export interface VaultJobStatus { jobName?: string; status: 'not-found' | 'pending' | 'running' | 'succeeded' | 'failed'; message: string; - conditions?: any[]; + conditions?: ResourceCondition[]; } export interface VaultInjectionRequest { @@ -426,15 +434,16 @@ PLAYBOOK_EOF secretName, }; } catch (error) { + const err = error as { name?: string; message?: string; stack?: string }; console.error('🔴 [API] Error triggering vault injection:', error); console.error('🔴 [API] Error details:', { - name: error.name, - message: error.message, - stack: error.stack, + name: err.name, + message: err.message, + stack: err.stack, }); return { success: false, - message: `Error triggering vault injection: ${error.message || error}`, + message: `Error triggering vault injection: ${err.message || error}`, }; } } @@ -457,11 +466,16 @@ export async function fetchVaultJobStatus(patternName: string): Promise ({ - name: job.metadata?.name, - creationTimestamp: job.metadata?.creationTimestamp, - status: job.status, - })) || [], + data.items?.map( + (job: { + metadata?: { name?: string; creationTimestamp?: string }; + status?: unknown; + }) => ({ + name: job.metadata?.name, + creationTimestamp: job.metadata?.creationTimestamp, + status: job.status, + }), + ) || [], }); if (!data.items || data.items.length === 0) { @@ -481,8 +495,11 @@ export async function fetchVaultJobStatus(patternName: string): Promise ({ type: c.type, status: c.status, reason: c.reason })) || - [], + jobStatus.conditions?.map((c: ResourceCondition) => ({ + type: c.type, + status: c.status, + reason: c.reason, + })) || [], }); let status: VaultJobStatus['status'] = 'pending'; @@ -514,15 +531,16 @@ export async function fetchVaultJobStatus(patternName: string): Promise { throw new Error(`Failed to fetch installed patterns: ${response.status}`); } const data = await response.json(); - return (data.items || []).map((item: any) => item.metadata.name as string); + return (data.items || []).map( + (item: { metadata: { name: string } }) => item.metadata.name as string, + ); } export interface PatternApplicationInfo { @@ -551,7 +571,7 @@ export interface PatternCRStatus { lastStep?: string; lastError?: string; deletionPhase?: string; - conditions?: any[]; + conditions?: ResourceCondition[]; applications?: PatternApplicationInfo[]; version?: number; } @@ -578,8 +598,9 @@ export async function fetchPatternCR(name: string): Promise { applications: status.applications, version: status.version, }; - } catch (err) { + } catch (error) { // consoleFetch may throw on 404 instead of returning a response + const err = error as { response?: { status?: number }; status?: number; message?: string }; if ( err?.response?.status === 404 || err?.status === 404 || @@ -587,7 +608,7 @@ export async function fetchPatternCR(name: string): Promise { ) { return { exists: false }; } - throw err; + throw error; } } diff --git a/console/src/components/InstallPatternPage.tsx b/console/src/components/InstallPatternPage.tsx index 36ca5ebcd..a0027bf28 100644 --- a/console/src/components/InstallPatternPage.tsx +++ b/console/src/components/InstallPatternPage.tsx @@ -202,7 +202,7 @@ export default function InstallPatternPage() { } } catch (err) { console.error('🔴 [InstallPatternPage] Error triggering vault injection:', err); - const errorMessage = err.message || err.toString(); + const errorMessage = err instanceof Error ? err.message : String(err); setVaultJobStatus({ status: 'not-found', message: `Failed to trigger vault injection: ${errorMessage}`, @@ -347,7 +347,8 @@ export default function InstallPatternPage() { } } catch (err) { console.error('🔴 [InstallPatternPage] Pattern installation failed:', err); - setSubmitError(err?.message || String(err)); + const errorMessage = err instanceof Error ? err.message : String(err); + setSubmitError(errorMessage); } finally { setSubmitting(false); console.log('🏁 [InstallPatternPage] Pattern installation process finished'); diff --git a/console/src/components/ManageSecretsPage.tsx b/console/src/components/ManageSecretsPage.tsx index 83b6dc507..839a87f77 100644 --- a/console/src/components/ManageSecretsPage.tsx +++ b/console/src/components/ManageSecretsPage.tsx @@ -125,7 +125,8 @@ export default function ManageSecretsPage() { setSubmitError(result.message); } } catch (err) { - setSubmitError(err?.message || String(err)); + const errorMessage = err instanceof Error ? err.message : String(err); + setSubmitError(errorMessage); } finally { setSubmitting(false); } diff --git a/console/src/components/PatternCard.tsx b/console/src/components/PatternCard.tsx index 7b7404321..700969cc4 100644 --- a/console/src/components/PatternCard.tsx +++ b/console/src/components/PatternCard.tsx @@ -114,7 +114,7 @@ function RequirementsPopoverBody({ pattern, clouds }: { pattern: Pattern; clouds {clouds.map((cloud) => ( @@ -164,9 +164,7 @@ export default function PatternCard({ const clouds = getCloudProviders(pattern); return ( - + setIsVisible(true)} - shouldClose={(_event, _fn) => setIsVisible(false)} + shouldOpen={() => setIsVisible(true)} + shouldClose={() => setIsVisible(false)} headerContent={t('Tested requirements')} bodyContent={} > @@ -235,7 +233,7 @@ export default function PatternCard({ {clouds.map((cloud) => ( ))} diff --git a/console/src/components/UninstallPatternPage.tsx b/console/src/components/UninstallPatternPage.tsx index d5028b807..1c3657a37 100644 --- a/console/src/components/UninstallPatternPage.tsx +++ b/console/src/components/UninstallPatternPage.tsx @@ -68,7 +68,8 @@ export default function UninstallPatternPage() { } } catch (err) { // If the fetch fails with a 404-like error, treat as deleted - if (err?.message && /404|not found/i.test(err.message)) { + const errorMessage = err instanceof Error ? err.message : String(err); + if (errorMessage && /404|not found/i.test(errorMessage)) { setDeleted(true); setDeleting(false); clearInterval(interval); @@ -95,7 +96,8 @@ export default function UninstallPatternPage() { setConfirmed(true); } } catch (err) { - setError(err?.message || String(err)); + const message = err instanceof Error ? err.message : String(err); + setError(message); setDeleting(false); } }; diff --git a/console/src/declarations.d.ts b/console/src/declarations.d.ts new file mode 100644 index 000000000..7fdd5ad60 --- /dev/null +++ b/console/src/declarations.d.ts @@ -0,0 +1,2 @@ +// Ambient module declarations for non-code imports handled by webpack loaders. +declare module '*.css'; diff --git a/console/src/hooks/useLocalStorage.ts b/console/src/hooks/useLocalStorage.ts index d77731ce0..8811f74d1 100644 --- a/console/src/hooks/useLocalStorage.ts +++ b/console/src/hooks/useLocalStorage.ts @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback, useState } from 'react'; interface StoredValue { version: number; @@ -33,9 +33,7 @@ export default function useLocalStorage( initialValue: T, version = 1, ): [T, (value: T | ((prev: T) => T)) => void] { - const [storedValue, setStoredValue] = useState(() => - readValue(key, initialValue, version), - ); + const [storedValue, setStoredValue] = useState(() => readValue(key, initialValue, version)); const setValue = useCallback( (value: T | ((prev: T) => T)) => { @@ -49,4 +47,4 @@ export default function useLocalStorage( ); return [storedValue, setValue]; -} \ No newline at end of file +} diff --git a/console/src/hooks/useNavigateCompat.ts b/console/src/hooks/useNavigateCompat.ts index 4b26bdc34..29c19bf8c 100644 --- a/console/src/hooks/useNavigateCompat.ts +++ b/console/src/hooks/useNavigateCompat.ts @@ -1,16 +1,22 @@ import * as React from 'react'; import * as ReactRouterDom from 'react-router-dom'; -const hasUseNavigate = typeof (ReactRouterDom as any).useNavigate === 'function'; +type RouterCompat = { + useNavigate: () => (path: string) => void; + useHistory: () => { push: (path: string) => void }; +}; + +const router = ReactRouterDom as unknown as RouterCompat; +const hasUseNavigate = typeof router.useNavigate === 'function'; // React Router v6 removed useHistory in favor of useNavigate. // OCP 4.22+ ships v6; OCP 4.21 and earlier ship v5. export const useNavigateCompat: () => (path: string) => void = hasUseNavigate ? () => { - const navigate = (ReactRouterDom as any).useNavigate(); + const navigate = router.useNavigate(); return React.useCallback((path: string) => navigate(path), [navigate]); } : () => { - const history = (ReactRouterDom as any).useHistory(); + const history = router.useHistory(); return React.useCallback((path: string) => history.push(path), [history]); }; diff --git a/console/src/hooks/useParamsCompat.ts b/console/src/hooks/useParamsCompat.ts index 87d624fe9..6a21df902 100644 --- a/console/src/hooks/useParamsCompat.ts +++ b/console/src/hooks/useParamsCompat.ts @@ -1,14 +1,21 @@ import * as ReactRouterDom from 'react-router-dom'; -const isV6 = typeof (ReactRouterDom as any).useNavigate === 'function'; +type RouterCompat = { + useNavigate: () => unknown; + useParams: () => Record; + useRouteMatch: (pattern: string) => { params?: Record } | null; +}; + +const router = ReactRouterDom as unknown as RouterCompat; +const hasUseNavigate = typeof router.useNavigate === 'function'; // React Router v5 (OCP < 4.22): useParams may not work if the console // framework doesn't expose route params through the standard context. // useRouteMatch explicitly matches the current URL against the given pattern. // React Router v6 (OCP 4.22+): useParams is the standard API. -export const useParamsCompat: (pattern: string) => Record = isV6 - ? () => (ReactRouterDom as any).useParams() +export const useParamsCompat: (pattern: string) => Record = hasUseNavigate + ? () => router.useParams() : (pattern: string) => { - const match = (ReactRouterDom as any).useRouteMatch(pattern); + const match = router.useRouteMatch(pattern); return match?.params || {}; }; diff --git a/console/tsconfig.json b/console/tsconfig.json index 7a64feeee..475f0b355 100644 --- a/console/tsconfig.json +++ b/console/tsconfig.json @@ -7,7 +7,7 @@ "sourceMap": true, "jsx": "react", "allowJs": true, - "strict": false, + "strict": true, "noUnusedLocals": true, "skipLibCheck": true }, diff --git a/console/yarn.lock b/console/yarn.lock index a01226285..428aaea59 100644 --- a/console/yarn.lock +++ b/console/yarn.lock @@ -350,7 +350,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.31": version "0.3.31" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== @@ -1621,6 +1621,13 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" @@ -1638,7 +1645,7 @@ ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.9.0: +ajv@^8.0.0, ajv@^8.20.0, ajv@^8.9.0: version "8.20.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.20.0.tgz#304b3636add88ba7d936760dd50ece006dea95f9" integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA== @@ -3267,6 +3274,14 @@ enhanced-resolve@^5.24.4: graceful-fs "^4.2.4" tapable "^2.3.3" +enhanced-resolve@^5.25.0: + version "5.25.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.25.1.tgz#9d919bfa898b116e58f20e95127c047693158771" + integrity sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.3.3" + enquirer@^2.3.6: version "2.4.1" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" @@ -5469,6 +5484,16 @@ minimizer-webpack-plugin@^5.6.1: schema-utils "^4.3.0" terser "^5.31.1" +minimizer-webpack-plugin@^5.7.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.12.0.tgz#acef4a0bd3c5ee405f767a9d90e0173b55b16458" + integrity sha512-PCN1x1OzFeFB2GlP91s46q7Gz8Jf16Z7M45bzpoqrYZlh12QeY6tYVM5h299wbwy1DxnQ69VFmmh8Hb2Ff8mbw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.31" + jest-worker "^27.4.5" + schema-utils "^4.3.3" + terser "^5.51.0" + "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" @@ -6309,7 +6334,7 @@ react-router-dom-v5-compat@6.30.6, react-router-dom-v5-compat@^6.11.2: history "^5.3.0" react-router "6.30.6" -react-router-dom@5.3.x: +react-router-dom@5.3.x, react-router-dom@~5.3.4: version "5.3.4" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== @@ -6322,7 +6347,7 @@ react-router-dom@5.3.x: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.3.4, react-router@5.3.x: +react-router@5.3.4, react-router@5.3.x, react-router@~5.3.4: version "5.3.4" resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== @@ -6733,6 +6758,16 @@ schema-utils@^4.0.0, schema-utils@^4.2.0, schema-utils@^4.3.0, schema-utils@^4.3 ajv-formats "^2.1.1" ajv-keywords "^5.1.0" +schema-utils@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.5.0.tgz#aaf8d588bd2b19511175175a5222baef648c009c" + integrity sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA== + dependencies: + "@types/json-schema" "^7.0.15" + ajv "^8.20.0" + ajv-formats "^3.0.1" + ajv-keywords "^5.1.0" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -7410,6 +7445,16 @@ terser@^5.31.1: commander "^2.20.0" source-map-support "~0.5.20" +terser@^5.51.0: + version "5.51.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.51.2.tgz#555912425a7f2ff7737425c3718fa76c7069f6ef" + integrity sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.15.0" + commander "^2.20.0" + source-map-support "~0.5.20" + text-decoder@^1.1.0: version "1.2.7" resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.7.tgz#5d073a9a74b9c0a9d28dfadcab96b604af57d8ba" @@ -7680,7 +7725,7 @@ typesafe-actions@^4.2.1: resolved "https://registry.yarnpkg.com/typesafe-actions/-/typesafe-actions-4.4.2.tgz#8f817c479d12130b5ebb442032968b2a18929e1a" integrity sha512-QW61P4cOX8dCNmrfpcUMjvU/MF/sFTC8/PlG9215W1gKDzZUBjRGdyYSO6ZcEUNsn491S2VpryJOHSIVSDqJrg== -typescript@^5.0.4, typescript@^5.7.2: +typescript@^5.0.4, typescript@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== @@ -7973,6 +8018,29 @@ webpack-sources@^3.5.1: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.5.1.tgz#76c2418486dcc02b2aa0694c104176c2858fe84a" integrity sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw== +webpack@^5.107.2: + version "5.111.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.111.1.tgz#7c12cd014fbb9bfd8509a6cfc6f1c79f4e06cade" + integrity sha512-cNypaz0RP+S4cvQVi1M/3bRUkvNP0xZpL0TjFx+c6jg64VbxD+2weWDgY9UnjRI6dhZgtaj8DU76GGFcJ79xPQ== + dependencies: + "@types/estree" "^1.0.8" + "@types/json-schema" "^7.0.15" + "@webassemblyjs/ast" "^1.14.1" + "@webassemblyjs/wasm-edit" "^1.14.1" + "@webassemblyjs/wasm-parser" "^1.14.1" + browserslist "^4.28.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.25.0" + es-module-lexer "^2.1.0" + events "^3.2.0" + graceful-fs "^4.2.11" + mime-db "^1.54.0" + minimizer-webpack-plugin "^5.7.0" + schema-utils "^4.5.0" + tapable "^2.3.0" + watchpack "^2.5.2" + webpack-sources "^3.5.1" + webpack@^5.75.0: version "5.109.2" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.109.2.tgz#b58dc289561c3282db35c210a99379a836a4c28d"