diff --git a/package.json b/package.json index 13ba2e62..4aee626f 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "packageManager": "yarn@3.6.1", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" }, "dependencies": { "jasmine": "^5.1.0" diff --git a/packages/kubernetes-api-app/package.json b/packages/kubernetes-api-app/package.json index ebc943ef..2a4bbc3f 100644 --- a/packages/kubernetes-api-app/package.json +++ b/packages/kubernetes-api-app/package.json @@ -16,7 +16,7 @@ "@patternfly/react-styles": "^4.92.6", "@patternfly/react-table": "^4.113.0", "@patternfly/react-tokens": "^4.94.6", - "@types/node": "^18.17.18", + "@types/node": "^18.18.9", "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", "mini-css-extract-plugin": "2.7.6", @@ -59,6 +59,6 @@ "packageManager": "yarn@3.6.0", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" } } diff --git a/packages/kubernetes-api-app/webpack.config.js b/packages/kubernetes-api-app/webpack.config.js index 957c60d3..73ee4b6e 100644 --- a/packages/kubernetes-api-app/webpack.config.js +++ b/packages/kubernetes-api-app/webpack.config.js @@ -147,7 +147,6 @@ module.exports = () => { /Failed to parse source map/, ], resolve: { - modules: [path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, '../../node_modules')], extensions: ['.js', '.ts', '.tsx', '.jsx'], alias: { 'react-native': 'react-native-web', diff --git a/packages/kubernetes-api/package.json b/packages/kubernetes-api/package.json index 5be57730..a7e95830 100644 --- a/packages/kubernetes-api/package.json +++ b/packages/kubernetes-api/package.json @@ -32,7 +32,7 @@ "@hawtio/react": "^0.6.1", "@types/jquery": "^3.5.25", "@types/jsonpath": "^0.2.0", - "@types/node": "^18.17.18", + "@types/node": "^18.18.9", "eventemitter3": "^5.0.1", "jquery": "^3.7.0", "js-logger": "^1.6.1", @@ -61,7 +61,7 @@ "packageManager": "yarn@3.6.0", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" }, "publishConfig": { "access": "restricted" diff --git a/packages/management-api-app/package.json b/packages/management-api-app/package.json index 2cb492b4..d6ad43e5 100644 --- a/packages/management-api-app/package.json +++ b/packages/management-api-app/package.json @@ -16,7 +16,7 @@ "@patternfly/react-styles": "^4.92.6", "@patternfly/react-table": "^4.113.0", "@patternfly/react-tokens": "^4.94.6", - "@types/node": "^18.17.18", + "@types/node": "^18.18.9", "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", "mini-css-extract-plugin": "2.7.6", @@ -59,6 +59,6 @@ "packageManager": "yarn@3.6.0", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" } } diff --git a/packages/management-api-app/webpack.config.js b/packages/management-api-app/webpack.config.js index 24242b07..7f1d5507 100644 --- a/packages/management-api-app/webpack.config.js +++ b/packages/management-api-app/webpack.config.js @@ -152,7 +152,6 @@ module.exports = () => { /Failed to parse source map/, ], resolve: { - modules: [path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, '../../node_modules')], extensions: ['.js', '.ts', '.tsx', '.jsx'], alias: { 'react-native': 'react-native-web', diff --git a/packages/management-api/package.json b/packages/management-api/package.json index 916f921c..e4a6e2e7 100644 --- a/packages/management-api/package.json +++ b/packages/management-api/package.json @@ -62,7 +62,7 @@ "packageManager": "yarn@3.6.0", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" }, "publishConfig": { "access": "restricted" diff --git a/packages/oauth-app/package.json b/packages/oauth-app/package.json index 5c6521c5..029017ba 100644 --- a/packages/oauth-app/package.json +++ b/packages/oauth-app/package.json @@ -16,7 +16,7 @@ "@patternfly/react-styles": "^4.92.6", "@patternfly/react-table": "^4.113.0", "@patternfly/react-tokens": "^4.94.6", - "@types/node": "^18.17.18", + "@types/node": "^18.18.9", "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", "mini-css-extract-plugin": "2.7.6", @@ -61,6 +61,6 @@ "packageManager": "yarn@3.6.0", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" } } diff --git a/packages/oauth-app/webpack.config.js b/packages/oauth-app/webpack.config.js index dc5879c8..8aa7bd87 100644 --- a/packages/oauth-app/webpack.config.js +++ b/packages/oauth-app/webpack.config.js @@ -147,7 +147,6 @@ module.exports = () => { /Failed to parse source map/, ], resolve: { - modules: [path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, '../../node_modules')], extensions: ['.js', '.ts', '.tsx', '.jsx'], alias: { 'react-native': 'react-native-web', diff --git a/packages/oauth/package.json b/packages/oauth/package.json index 3bb22ed3..b14d7e40 100644 --- a/packages/oauth/package.json +++ b/packages/oauth/package.json @@ -31,11 +31,13 @@ "dependencies": { "@hawtio/react": "^0.6.1", "babel-jest": "^29.6.1", + "fetch-intercept": "^2.4.0", "jest-extended": "^4.0.0", "jquery": "^3.7.0", "js-logger": "^1.6.1", "ts-node": "^10.9.1", - "typescript": "^5.2.2" + "typescript": "^5.2.2", + "whatwg-fetch": "^3.6.19" }, "devDependencies": { "@types/jest": "^29.5.8", @@ -55,7 +57,7 @@ "packageManager": "yarn@3.6.0", "engines": { "yarn": ">=3.6.0", - "node": ">=16" + "node": ">=18" }, "publishConfig": { "access": "restricted" diff --git a/packages/oauth/src/form/form-service.ts b/packages/oauth/src/form/form-service.ts index ad84e8b8..9c8a16ed 100644 --- a/packages/oauth/src/form/form-service.ts +++ b/packages/oauth/src/form/form-service.ts @@ -1,4 +1,5 @@ import $ from 'jquery' +import * as fetchIntercept from 'fetch-intercept' import { getCookie } from '../utils' import { log, OAuthProtoService, UserProfile } from '../globals' import { FormConfig, FORM_TOKEN_STORAGE_KEY, FORM_AUTH_PROTOCOL_MODULE, ResolveUser } from './globals' @@ -10,10 +11,16 @@ type LoginOptions = { uri: URL } +interface Headers { + Authorization: string + 'X-XSRF-TOKEN'?: string +} + export class FormService implements OAuthProtoService { private userProfile: UserProfile private formConfig: FormConfig | null private loggedIn: boolean + private fetchUnregister: (() => void) | null constructor(formConfig: FormConfig | null, userProfile: UserProfile) { log.debug('Initialising Form Auth Service') @@ -21,6 +28,7 @@ export class FormService implements OAuthProtoService { this.userProfile.setOAuthType(FORM_AUTH_PROTOCOL_MODULE) this.formConfig = formConfig this.loggedIn = this.initLogin() + this.fetchUnregister = null } private initLogin(): boolean { @@ -111,28 +119,27 @@ export class FormService implements OAuthProtoService { } log.debug('Intercept Fetch API to attach auth token to authorization header') - const { fetch: originalFetch } = window - window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise => { - log.debug('Fetch intercepted for oAuth authentication') - - init = { ...init } - init.headers = { - ...init.headers, - Authorization: `Bearer ${this.userProfile.getToken()}`, - } + this.fetchUnregister = fetchIntercept.register({ + request: (url, config) => { + log.debug('Fetch intercepted for oAuth authentication') - // For CSRF protection with Spring Security - const token = getCookie('XSRF-TOKEN') - if (token) { - log.debug('Set XSRF token header from cookies') - init.headers = { - ...init.headers, - 'X-XSRF-TOKEN': token, + let headers: Headers = { + Authorization: `Bearer ${this.userProfile.getToken()}`, } - } - return originalFetch(input, init) - } + // For CSRF protection with Spring Security + const token = getCookie('XSRF-TOKEN') + if (token) { + log.debug('Set XSRF token header from cookies') + headers = { + ...headers, + 'X-XSRF-TOKEN': token, + } + } + + return [url, { headers, ...config }] + }, + }) } private setupJQueryAjax() { @@ -163,6 +170,8 @@ export class FormService implements OAuthProtoService { } doLogout(): void { + if (this.fetchUnregister) this.fetchUnregister() + const currentURI = new URL(window.location.href) this.forceRelogin(currentURI) } diff --git a/packages/oauth/src/openshift/osoauth-service.ts b/packages/oauth/src/openshift/osoauth-service.ts index feb15f18..13232976 100644 --- a/packages/oauth/src/openshift/osoauth-service.ts +++ b/packages/oauth/src/openshift/osoauth-service.ts @@ -1,4 +1,5 @@ import $ from 'jquery' +import * as fetchIntercept from 'fetch-intercept' import { log, OAuthProtoService, UserProfile } from '../globals' import { fetchPath, isBlank, getCookie } from '../utils' import { CLUSTER_CONSOLE_KEY } from '../metadata' @@ -12,7 +13,7 @@ import { OpenShiftOAuthConfig, ResolveUser, } from './globals' -import { buildUserInfoUri, checkToken, currentTimeSeconds, doLogout, tokenHasExpired } from './support' +import { buildUserInfoUri, checkToken, currentTimeSeconds, forceRelogin, tokenHasExpired } from './support' import { userService } from '@hawtio/react' interface UserObject { @@ -26,6 +27,11 @@ interface UserObject { groups: string[] } +interface Headers { + Authorization: string + 'X-XSRF-TOKEN'?: string +} + export class OSOAuthService implements OAuthProtoService { private userInfoUri = '' private keepaliveInterval = 10 @@ -34,6 +40,7 @@ export class OSOAuthService implements OAuthProtoService { private userProfile: UserProfile private readonly adaptedConfig: Promise private readonly login: Promise + private fetchUnregister: (() => void) | null constructor(openShiftConfig: OpenShiftOAuthConfig, userProfile: UserProfile) { log.debug('Initialising Openshift OAuth Service') @@ -41,6 +48,7 @@ export class OSOAuthService implements OAuthProtoService { this.userProfile.setOAuthType(OAUTH_OS_PROTOCOL_MODULE) this.adaptedConfig = this.processConfig(openShiftConfig) this.login = this.createLogin() + this.fetchUnregister = null } private async processConfig(config: OpenShiftOAuthConfig): Promise { @@ -95,37 +103,37 @@ export class OSOAuthService implements OAuthProtoService { } log.debug('Intercept Fetch API to attach Openshift auth token to authorization header') - const { fetch: originalFetch } = window - window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise => { - log.debug('Fetch intercepted for oAuth authentication') + const unregister = fetchIntercept.register({ + request: (url, config) => { + log.debug('Fetch intercepted for oAuth authentication') - if (tokenHasExpired(this.userProfile)) { - return new Promise((resolve, _) => { - const reason = `Cannot navigate to ${input} as token expired so need to logout` + if (tokenHasExpired(this.userProfile)) { + const reason = `Cannot navigate to ${url} as token expired so need to logout` log.debug(reason) - doLogout(config) - resolve(Response.error()) - }) - } - init = { ...init } - init.headers = { - ...init.headers, - Authorization: `Bearer ${this.userProfile.getToken()}`, - } + // Unregister this fetch handler before logging out + unregister() - // For CSRF protection with Spring Security - const token = getCookie('XSRF-TOKEN') - if (token) { - log.debug('Set XSRF token header from cookies') - init.headers = { - ...init.headers, - 'X-XSRF-TOKEN': token, + this.doLogout(config) } - } - return originalFetch(input, init) - } + let headers: Headers = { + Authorization: `Bearer ${this.userProfile.getToken()}`, + } + + // For CSRF protection with Spring Security + const token = getCookie('XSRF-TOKEN') + if (token) { + log.debug('Set XSRF token header from cookies') + headers = { + ...headers, + 'X-XSRF-TOKEN': token, + } + } + + return [url, { headers, ...config }] + }, + }) } private setupJQueryAjax(config: OpenShiftOAuthConfig) { @@ -137,7 +145,7 @@ export class OSOAuthService implements OAuthProtoService { const beforeSend = (xhr: JQueryXHR, settings: JQueryAjaxSettings) => { if (tokenHasExpired(this.userProfile)) { log.debug(`Cannot navigate to ${settings.url} as token expired so need to logout`) - doLogout(config) + this.doLogout(config) return } @@ -187,7 +195,7 @@ export class OSOAuthService implements OAuthProtoService { // In that case, let's just skip the error and go through another refresh cycle. // See http://stackoverflow.com/questions/2000609/jquery-ajax-status-code-0 for more details. log.error('Failed to fetch user info, status: ', response.statusText) - doLogout(config) + this.doLogout(config) } } @@ -206,7 +214,7 @@ export class OSOAuthService implements OAuthProtoService { if (tokenHasExpired(this.userProfile)) { log.debug('Token has expired so logging out') - doLogout(config) + this.doLogout(config) return true } @@ -233,7 +241,7 @@ export class OSOAuthService implements OAuthProtoService { const tokenParams = checkToken(currentURI) if (!tokenParams) { log.debug('No Token so initiating new login') - doLogout(config) + this.doLogout(config) return false } @@ -263,6 +271,19 @@ export class OSOAuthService implements OAuthProtoService { } } + private doLogout(config: OpenShiftOAuthConfig): void { + if (this.fetchUnregister) this.fetchUnregister() + + const currentURI = new URL(window.location.href) + // The following request returns 403 when delegated authentication with an + // OAuthClient is used, as possible scopes do not grant permissions to access the OAuth API: + // See https://github.com/openshift/origin/issues/7011 + // + // So little point in trying to delete the token. Lets do in client-side only + // + forceRelogin(currentURI, config) + } + async isLoggedIn(): Promise { return await this.login } @@ -308,7 +329,7 @@ export class OSOAuthService implements OAuthProtoService { log.info('Log out Openshift') try { - doLogout(config) + this.doLogout(config) } catch (error) { log.error('Error logging out Openshift:', error) } diff --git a/packages/oauth/src/openshift/support.ts b/packages/oauth/src/openshift/support.ts index 68312b1b..2fc8d3de 100644 --- a/packages/oauth/src/openshift/support.ts +++ b/packages/oauth/src/openshift/support.ts @@ -19,22 +19,11 @@ export function buildUserInfoUri(masterUri: string, config: OpenShiftOAuthConfig return uri.toString() } -function forceRelogin(url: URL, config: OpenShiftOAuthConfig) { +export function forceRelogin(url: URL, config: OpenShiftOAuthConfig) { clearTokenStorage() doLogin(config, { uri: url.toString() }) } -export function doLogout(config: OpenShiftOAuthConfig): void { - const currentURI = new URL(window.location.href) - // The following request returns 403 when delegated authentication with an - // OAuthClient is used, as possible scopes do not grant permissions to access the OAuth API: - // See https://github.com/openshift/origin/issues/7011 - // - // So little point in trying to delete the token. Lets do in client-side only - // - forceRelogin(currentURI, config) -} - export function doLogin(config: OpenShiftOAuthConfig, options: { uri: string }): void { if (!config) { log.debug('Cannot login due to config now being properly defined') diff --git a/packages/online-shell/package.json b/packages/online-shell/package.json index 6b95bffc..ce69a464 100644 --- a/packages/online-shell/package.json +++ b/packages/online-shell/package.json @@ -36,7 +36,7 @@ "@patternfly/react-styles": "^4.92.6", "@patternfly/react-table": "^4.113.0", "@patternfly/react-tokens": "^4.94.6", - "@types/node": "^18.17.18", + "@types/node": "^18.18.9", "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", "jquery-match-height": "^0.7.2", diff --git a/packages/online-shell/webpack.config.common.js b/packages/online-shell/webpack.config.common.js index 8a7db6d7..4f0efcb0 100644 --- a/packages/online-shell/webpack.config.common.js +++ b/packages/online-shell/webpack.config.common.js @@ -112,7 +112,6 @@ const common = mode => { /Failed to parse source map/, ], resolve: { - modules: [path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, '../../node_modules')], extensions: ['.js', '.ts', '.tsx', '.jsx'], alias: { 'react-native': 'react-native-web', diff --git a/yarn.lock b/yarn.lock index 76c567e1..0b6c187a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1959,7 +1959,7 @@ __metadata: "@patternfly/react-styles": ^4.92.6 "@patternfly/react-table": ^4.113.0 "@patternfly/react-tokens": ^4.94.6 - "@types/node": ^18.17.18 + "@types/node": ^18.18.9 "@types/react": ^18.2.21 "@types/react-dom": ^18.2.7 connect-history-api-fallback: ^2.0.0 @@ -1996,7 +1996,7 @@ __metadata: "@types/jest": ^29.5.8 "@types/jquery": ^3.5.25 "@types/jsonpath": ^0.2.0 - "@types/node": ^18.17.18 + "@types/node": ^18.18.9 babel-jest: ^29.6.1 eslint-config-react-app: ^7.0.1 eventemitter3: ^5.0.1 @@ -2030,7 +2030,7 @@ __metadata: "@patternfly/react-styles": ^4.92.6 "@patternfly/react-table": ^4.113.0 "@patternfly/react-tokens": ^4.94.6 - "@types/node": ^18.17.18 + "@types/node": ^18.18.9 "@types/react": ^18.2.21 "@types/react-dom": ^18.2.7 connect-history-api-fallback: ^2.0.0 @@ -2101,7 +2101,7 @@ __metadata: "@patternfly/react-styles": ^4.92.6 "@patternfly/react-table": ^4.113.0 "@patternfly/react-tokens": ^4.94.6 - "@types/node": ^18.17.18 + "@types/node": ^18.18.9 "@types/react": ^18.2.21 "@types/react-dom": ^18.2.7 connect-history-api-fallback: ^2.0.0 @@ -2139,6 +2139,7 @@ __metadata: "@types/jest": ^29.5.8 "@types/jquery": ^3.5.25 babel-jest: ^29.6.1 + fetch-intercept: ^2.4.0 jest: ^29.6.1 jest-environment-jsdom: ^29.6.1 jest-extended: ^4.0.0 @@ -2151,6 +2152,7 @@ __metadata: ts-node: ^10.9.1 tsup: ^7.1.0 typescript: ^5.2.2 + whatwg-fetch: ^3.6.19 peerDependencies: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 @@ -2187,7 +2189,7 @@ __metadata: "@patternfly/react-styles": ^4.92.6 "@patternfly/react-table": ^4.113.0 "@patternfly/react-tokens": ^4.94.6 - "@types/node": ^18.17.18 + "@types/node": ^18.18.9 "@types/react": ^18.2.21 "@types/react-dom": ^18.2.7 babel-loader: ^9.1.3 @@ -2954,13 +2956,6 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.10.0": - version: 1.10.0 - resolution: "@remix-run/router@npm:1.10.0" - checksum: f8f9fcd5f08465a7e0a05378398ff6df2c5c5ef5766df3490a134d64260b3b16f1bd490bb0c3f5925c2671a0c1d8d1fa01dfbdc7ecc3b2447dc6eafe6b73bcc2 - languageName: node - linkType: hard - "@remix-run/router@npm:1.11.0": version: 1.11.0 resolution: "@remix-run/router@npm:1.11.0" @@ -2968,6 +2963,13 @@ __metadata: languageName: node linkType: hard +"@remix-run/router@npm:1.12.0": + version: 1.12.0 + resolution: "@remix-run/router@npm:1.12.0" + checksum: 0528a5c9dac443f90aef30b65fed39c6654b5c2db1d01d700b212d783958935b4d800250530430d78eacf03f3baa104edeae75a29cfb13b3180cbfca3352e645 + languageName: node + linkType: hard + "@rushstack/eslint-patch@npm:^1.1.0": version: 1.5.1 resolution: "@rushstack/eslint-patch@npm:1.5.1" @@ -3616,17 +3618,7 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:^29.5.5": - version: 29.5.6 - resolution: "@types/jest@npm:29.5.6" - dependencies: - expect: ^29.0.0 - pretty-format: ^29.0.0 - checksum: fa13a27bd1c8efd0381a419478769d0d6d3a8e93e1952d7ac3a16274e8440af6f73ed6f96ac1ff00761198badf2ee226b5ab5583a5d87a78d609ea78da5c5a24 - languageName: node - linkType: hard - -"@types/jest@npm:^29.5.8": +"@types/jest@npm:^29.5.5, @types/jest@npm:^29.5.8": version: 29.5.8 resolution: "@types/jest@npm:29.5.8" dependencies: @@ -3732,13 +3724,22 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^18.17.18, @types/node@npm:^18.18.5": +"@types/node@npm:^18.18.5": version: 18.18.6 resolution: "@types/node@npm:18.18.6" checksum: a847639b8455fd3dfa6dbc2917274c82c9db789f1d41aaf69f94ac6c9e54c3c1dd29be6e1e1ccd7c17e54db3d78d7011bc4e70544c6447ceca253dccc0a187e1 languageName: node linkType: hard +"@types/node@npm:^18.18.9": + version: 18.18.9 + resolution: "@types/node@npm:18.18.9" + dependencies: + undici-types: ~5.26.4 + checksum: 629ce20357586144031cb43d601617eef45e59460dea6b1e123f708e6885664f44d54f65e5b72b2614af5b8613f3652ced832649c0b991accbc6a85139befa51 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.1 resolution: "@types/parse-json@npm:4.0.1" @@ -7393,6 +7394,13 @@ __metadata: languageName: node linkType: hard +"fetch-intercept@npm:^2.4.0": + version: 2.4.0 + resolution: "fetch-intercept@npm:2.4.0" + checksum: f89c9b40fdc4695e065b55c27f1f93dacb1a1dcdb36d19267d6b1671304598d144c407a22d33d96e82a05df3f0578020a57760a8dd57f0b851715e0fa1c965c5 + languageName: node + linkType: hard + "figures@npm:^3.0.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -11728,15 +11736,15 @@ __metadata: linkType: hard "react-router-dom@npm:^6.17.0": - version: 6.17.0 - resolution: "react-router-dom@npm:6.17.0" + version: 6.19.0 + resolution: "react-router-dom@npm:6.19.0" dependencies: - "@remix-run/router": 1.10.0 - react-router: 6.17.0 + "@remix-run/router": 1.12.0 + react-router: 6.19.0 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: e0ba4f4c507681e2ffdecdf2e67edf7ec0e2bf4be35222e29d013afdb03866a5e6ecacc8b452bd55797b9672785d02f81bd6dbf6b05ac93a59e48e774b0060de + checksum: 04453ca48eb900a4a6aa8b8e48368fa78d4ce8a9b69df108d9f53071a904349b18672a66c94252eb847ae4369e30bbe4ec7244bb6529b10fd474774e48f03669 languageName: node linkType: hard @@ -11753,25 +11761,25 @@ __metadata: languageName: node linkType: hard -"react-router@npm:6.17.0": - version: 6.17.0 - resolution: "react-router@npm:6.17.0" +"react-router@npm:6.18.0": + version: 6.18.0 + resolution: "react-router@npm:6.18.0" dependencies: - "@remix-run/router": 1.10.0 + "@remix-run/router": 1.11.0 peerDependencies: react: ">=16.8" - checksum: 99c30d94fbb34657e4c8c3ef1aaae33b143167d3869b442e06c83b4006f35200fde810029180e209654bef2f47f0b27a928f77cc2d859a358a2722cc9d494f03 + checksum: 03e9a23c5b75d8813720745e2952bb9e62ec310d238cde4f19e0ce73582701fa5e04cf609ff9ced978e9e6c531b5e333b9aee35371e6c4743afc2829e32e926a languageName: node linkType: hard -"react-router@npm:6.18.0": - version: 6.18.0 - resolution: "react-router@npm:6.18.0" +"react-router@npm:6.19.0": + version: 6.19.0 + resolution: "react-router@npm:6.19.0" dependencies: - "@remix-run/router": 1.11.0 + "@remix-run/router": 1.12.0 peerDependencies: react: ">=16.8" - checksum: 03e9a23c5b75d8813720745e2952bb9e62ec310d238cde4f19e0ce73582701fa5e04cf609ff9ced978e9e6c531b5e333b9aee35371e6c4743afc2829e32e926a + checksum: f7e3396b8f4299638029dc726cb02d9c05c8906dc5277e5f9d899ef113d8cec49dfab7d34cd496826f8c1a95666141f3eede446c4438ef56720fdb72c66473fb languageName: node linkType: hard @@ -13570,6 +13578,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -14431,6 +14446,13 @@ __metadata: languageName: node linkType: hard +"whatwg-fetch@npm:^3.6.19": + version: 3.6.19 + resolution: "whatwg-fetch@npm:3.6.19" + checksum: 2896bc9ca867ea514392c73e2a272f65d5c4916248fe0837a9df5b1b92f247047bc76cf7c29c28a01ac6c5fb4314021d2718958c8a08292a96d56f72b2f56806 + languageName: node + linkType: hard + "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0"