diff --git a/.deps/dev.md b/.deps/dev.md
index 991f1994d..3a04985f5 100644
--- a/.deps/dev.md
+++ b/.deps/dev.md
@@ -63,18 +63,18 @@
| [`@istanbuljs/schema@0.1.3`](git+https://github.com/istanbuljs/schema.git) | MIT | clearlydefined |
| [`@jest/console@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`@jest/core@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`@jest/environment@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`@jest/environment@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`@jest/expect-utils@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`@jest/expect@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`@jest/fake-timers@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`@jest/fake-timers@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`@jest/globals@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`@jest/reporters@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`@jest/schemas@29.6.0`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`@jest/source-map@29.6.0`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`@jest/test-result@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`@jest/test-sequencer@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`@jest/test-sequencer@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`@jest/transform@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`@jest/types@29.6.1`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`@jest/types@29.6.3`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`@jridgewell/gen-mapping@0.3.3`](https://github.com/jridgewell/gen-mapping) | MIT | clearlydefined |
| [`@jridgewell/resolve-uri@3.1.1`](https://github.com/jridgewell/resolve-uri) | MIT | clearlydefined |
| [`@jridgewell/set-array@1.1.2`](https://github.com/jridgewell/set-array) | MIT | clearlydefined |
@@ -138,7 +138,7 @@
| [`@sinonjs/commons@3.0.0`](git+https://github.com/sinonjs/commons.git) | BSD-3-Clause | clearlydefined |
| [`@sinonjs/fake-timers@10.3.0`](https://github.com/sinonjs/fake-timers.git) | BSD-3-Clause | #9214 |
| [`@testing-library/dom@7.31.2`](https://github.com/testing-library/dom-testing-library) | MIT | (clearlydefined)[https://clearlydefined.io/definitions/npm/npmjs/@testing-library/dom/7.31.2] |
-| [`@testing-library/jest-dom@5.17.0`](https://github.com/testing-library/jest-dom) | MIT | clearlydefined |
+| [`@testing-library/jest-dom@6.1.3`](https://github.com/testing-library/jest-dom) | MIT | clearlydefined |
| [`@testing-library/react@10.4.9`](https://github.com/testing-library/react-testing-library) | MIT | clearlydefined |
| [`@testing-library/user-event@12.8.3`](https://github.com/testing-library/user-event) | MIT | clearlydefined |
| [`@tootallnate/once@2.0.0`](git://github.com/TooTallNate/once.git) | MIT | clearlydefined |
@@ -253,11 +253,12 @@
| [`at-least-node@1.0.0`](git+https://github.com/RyanZim/at-least-node.git) | ISC | clearlydefined |
| [`available-typed-arrays@1.0.5`](git+https://github.com/inspect-js/available-typed-arrays.git) | MIT | clearlydefined |
| [`axios-mock-adapter@1.21.5`](git+https://github.com/ctimmerm/axios-mock-adapter.git) | MIT | clearlydefined |
-| [`babel-jest@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`axios@1.4.0`](https://github.com/axios/axios.git) | MIT | clearlydefined |
+| [`babel-jest@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`babel-plugin-istanbul@6.1.1`](git+https://github.com/istanbuljs/babel-plugin-istanbul.git) | BSD-3-Clause | clearlydefined |
-| [`babel-plugin-jest-hoist@29.5.0`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`babel-plugin-jest-hoist@29.6.3`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`babel-preset-current-node-syntax@1.0.1`](https://github.com/nicolo-ribaudo/babel-preset-current-node-syntax.git) | MIT | clearlydefined |
-| [`babel-preset-jest@29.5.0`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`babel-preset-jest@29.6.3`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`before-after-hook@2.2.3`](https://github.com/gr2m/before-after-hook.git) | Apache-2.0 | clearlydefined |
| [`big-integer@1.6.51`](git@github.com:peterolson/BigInteger.js.git) | Unlicense | #2439 |
| [`big.js@5.2.2`](https://github.com/MikeMcl/big.js.git) | MIT | clearlydefined |
@@ -279,7 +280,7 @@
| [`callsites@3.1.0`](https://github.com/sindresorhus/callsites.git) | MIT | clearlydefined |
| [`camel-case@4.1.2`](git://github.com/blakeembrey/change-case.git) | MIT | clearlydefined |
| [`camelcase-keys@6.2.2`](https://github.com/sindresorhus/camelcase-keys.git) | MIT | clearlydefined |
-| [`camelcase@5.3.1`](https://github.com/sindresorhus/camelcase.git) | MIT | clearlydefined |
+| [`camelcase@6.3.0`](https://github.com/sindresorhus/camelcase.git) | MIT | clearlydefined |
| [`caniuse-api@3.0.0`](https://github.com/nyalab/caniuse-api.git) | MIT | clearlydefined |
| [`caniuse-lite@1.0.30001521`](https://github.com/browserslist/caniuse-lite.git) | CC-BY-4.0 | #1196 |
| [`chalk@4.1.2`](https://github.com/chalk/chalk.git) | MIT | clearlydefined |
@@ -324,6 +325,7 @@
| [`copy-webpack-plugin@11.0.0`](https://github.com/webpack-contrib/copy-webpack-plugin.git) | MIT | clearlydefined |
| [`core-js-pure@3.32.0`](https://github.com/zloirock/core-js.git) | MIT | #9880 |
| [`cosmiconfig@7.0.0`](git+https://github.com/davidtheclark/cosmiconfig.git) | MIT | clearlydefined |
+| [`create-jest@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`cross-spawn@7.0.3`](git@github.com:moxystudio/node-cross-spawn.git) | MIT | clearlydefined |
| [`crypto-random-string@2.0.0`](https://github.com/sindresorhus/crypto-random-string.git) | MIT | clearlydefined |
| [`css-declaration-sorter@6.4.1`](https://github.com/Siilwyn/css-declaration-sorter.git) | ISC | #9434 |
@@ -559,20 +561,20 @@
| [`jackspeak@2.3.0`](git+https://github.com/isaacs/jackspeak.git) | BlueOak-1.0.0 | transitive dependency |
| [`jake@10.8.7`](git://github.com/jakejs/jake.git) | Apache-2.0 | #1316 |
| [`jest-changed-files@29.5.0`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`jest-circus@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`jest-circus@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`jest-cli@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`jest-config@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`jest-config@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`jest-diff@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-docblock@29.4.3`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`jest-each@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`jest-environment-jsdom@29.6.2`](https://github.com/facebook/jest.git) | MIT | #9317 |
+| [`jest-each@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
+| [`jest-environment-jsdom@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`jest-environment-node@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-get-type@29.4.3`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-haste-map@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-leak-detector@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-matcher-utils@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-message-util@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`jest-mock@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`jest-mock@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`jest-pnp-resolver@1.2.3`](https://github.com/arcanis/jest-pnp-resolver.git) | MIT | clearlydefined |
| [`jest-regex-util@29.4.3`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-resolve-dependencies@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
@@ -580,13 +582,14 @@
| [`jest-runner@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-runtime@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-snapshot@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
-| [`jest-util@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
+| [`jest-util@29.7.0`](https://github.com/jestjs/jest.git) | MIT | clearlydefined |
| [`jest-validate@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-watcher@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest-websocket-mock@2.4.1`](git+https://github.com/romgain/jest-websocket-mock.git) | MIT | clearlydefined |
| [`jest-worker@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jest@29.6.2`](https://github.com/facebook/jest.git) | MIT | clearlydefined |
| [`jsdom@20.0.3`](https://github.com/jsdom/jsdom.git) | MIT | #7436 |
+| [`jsesc@2.5.2`](https://github.com/mathiasbynens/jsesc.git) | MIT | clearlydefined |
| [`json-parse-better-errors@1.0.2`](https://github.com/zkat/json-parse-better-errors) | MIT | clearlydefined |
| [`json-parse-even-better-errors@3.0.0`](https://github.com/npm/json-parse-even-better-errors.git) | MIT | clearlydefined |
| [`json-stable-stringify-without-jsonify@1.0.1`](git://github.com/samn/json-stable-stringify.git) | MIT | clearlydefined |
@@ -600,6 +603,7 @@
| [`kleur@3.0.3`](https://github.com/lukeed/kleur.git) | MIT | clearlydefined |
| [`known-css-properties@0.27.0`](https://github.com/known-css/known-css-properties.git) | MIT | clearlydefined |
| [`lerna@6.6.2`](git+https://github.com/lerna/lerna.git) | MIT | #7595 |
+| [`leven@3.1.0`](https://github.com/sindresorhus/leven.git) | MIT | clearlydefined |
| [`levn@0.4.1`](git://github.com/gkz/levn.git) | MIT | clearlydefined |
| [`libnpmaccess@6.0.4`](https://github.com/npm/cli.git) | ISC | clearlydefined |
| [`libnpmpublish@7.1.4`](https://github.com/npm/cli.git) | ISC | clearlydefined |
@@ -841,7 +845,7 @@
| [`string.prototype.trimstart@1.0.6`](git://github.com/es-shims/String.prototype.trimStart.git) | MIT | #4647 |
| [`strip-ansi-cjs@6.0.1`](https://github.com/chalk/strip-ansi.git) | MIT | transitive dependency |
| [`strip-ansi@6.0.1`](https://github.com/chalk/strip-ansi.git) | MIT | clearlydefined |
-| [`strip-bom@3.0.0`](https://github.com/sindresorhus/strip-bom.git) | MIT | clearlydefined |
+| [`strip-bom@4.0.0`](https://github.com/sindresorhus/strip-bom.git) | MIT | clearlydefined |
| [`strip-final-newline@2.0.0`](https://github.com/sindresorhus/strip-final-newline.git) | MIT | clearlydefined |
| [`strip-indent@3.0.0`](https://github.com/sindresorhus/strip-indent.git) | MIT | clearlydefined |
| [`strip-json-comments@3.1.1`](https://github.com/sindresorhus/strip-json-comments.git) | MIT | clearlydefined |
@@ -875,6 +879,7 @@
| [`through2@4.0.2`](https://github.com/rvagg/through2.git) | MIT | clearlydefined |
| [`through@2.3.8`](https://github.com/dominictarr/through.git) | MIT | #1036 |
| [`titleize@3.0.0`](https://github.com/sindresorhus/titleize.git) | MIT | clearlydefined |
+| [`to-fast-properties@2.0.0`](https://github.com/sindresorhus/to-fast-properties.git) | MIT | clearlydefined |
| [`to-regex-range@5.0.1`](https://github.com/micromatch/to-regex-range.git) | MIT | clearlydefined |
| [`totalist@1.1.0`](https://github.com/lukeed/totalist.git) | MIT | clearlydefined |
| [`touch@3.1.0`](git://github.com/isaacs/node-touch.git) | ISC | clearlydefined |
diff --git a/.deps/prod.md b/.deps/prod.md
index c69c156b5..345f3409c 100644
--- a/.deps/prod.md
+++ b/.deps/prod.md
@@ -10,7 +10,6 @@
| [`@eclipse-che/dashboard-backend@7.75.0-next`](https://github.com/eclipse-che/che-dashboard) | EPL-2.0 | ecd.che |
| [`@eclipse-che/dashboard-frontend@7.75.0-next`](git://github.com/eclipse/che-dashboard.git) | EPL-2.0 | ecd.che |
| [`@eclipse-che/devfile-converter@0.0.1-ff55f9a`](git+https://github.com/che-incubator/devfile-converter.git) | EPL-2.0 | ecd.che |
-| [`@eclipse-che/workspace-client@0.0.1-1672830275`](https://github.com/eclipse/che-workspace-client) | EPL-2.0 | ecd.che |
| [`@fastify/accept-negotiator@1.1.0`](git+https://github.com/fastify/accept-negotiator.git) | MIT | clearlydefined |
| [`@fastify/ajv-compiler@3.5.0`](git+https://github.com/fastify/ajv-compiler.git) | MIT | clearlydefined |
| [`@fastify/cookie@8.3.0`](git+ssh://git@github.com/fastify/fastify-cookie.git) | MIT | clearlydefined |
@@ -379,7 +378,6 @@
| [`trim-right@1.0.1`](https://github.com/sindresorhus/trim-right.git) | MIT | clearlydefined |
| [`tslib@2.6.1`](https://github.com/Microsoft/tslib.git) | 0BSD | #9189 |
| [`tunnel-agent@0.6.0`](https://github.com/mikeal/tunnel-agent) | Apache-2.0 | clearlydefined |
-| [`tunnel@0.0.6`](https://github.com/koichik/node-tunnel.git) | MIT | clearlydefined |
| [`tweetnacl@0.14.5`](https://github.com/dchest/tweetnacl-js.git) | Unlicense | #1035 |
| [`type-fest@1.4.0`](https://github.com/sindresorhus/type-fest.git) | (MIT OR CC0-1.0) | clearlydefined |
| [`underscore@1.13.6`](git://github.com/jashkenas/underscore.git) | MIT | clearlydefined |
diff --git a/packages/common/package.json b/packages/common/package.json
index 4b5bda377..98a80ca78 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -28,7 +28,7 @@
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-notice": "^0.9.10",
"eslint-plugin-prettier": "^5.0.0",
- "jest": "^29.6.2",
+ "jest": "^29.7.0",
"prettier": "^3.0.1",
"rimraf": "^5.0.1",
"ts-jest": "^29.1.1",
diff --git a/packages/common/src/helpers/__tests__/errors.spec.ts b/packages/common/src/helpers/__tests__/errors.spec.ts
index fb3cd428d..fec4743b2 100644
--- a/packages/common/src/helpers/__tests__/errors.spec.ts
+++ b/packages/common/src/helpers/__tests__/errors.spec.ts
@@ -335,5 +335,26 @@ describe('Errors helper', () => {
};
expect(getMessage(error)).toEqual(expectedMessage);
});
+
+ it('should return a message if `error.response.data` includes a HTML page', () => {
+ const htmlPage =
+ '
...';
+ const error = {
+ name: 'Error',
+ config: {},
+ request: {},
+ response: {
+ data: htmlPage,
+ status: 500,
+ statusText: 'Internal Server Error',
+ headers: {},
+ config: {},
+ request: {},
+ },
+ message: '"500" returned by "/kubernetes/namespace/provision".',
+ };
+
+ expect(getMessage(error)).toEqual(error.message);
+ });
});
});
diff --git a/packages/common/src/helpers/errors.ts b/packages/common/src/helpers/errors.ts
index c60b03f53..3b7a64589 100644
--- a/packages/common/src/helpers/errors.ts
+++ b/packages/common/src/helpers/errors.ts
@@ -50,7 +50,9 @@ export function getMessage(error: unknown): string {
if (includesAxiosResponse(error)) {
const response = error.response;
if (typeof response.data === 'string') {
- return response.data;
+ if (response.data.toLowerCase().trim().indexOf('{componentToWrap};
+ return {componentToWrap};
}
describe('Error boundary', () => {
@@ -66,6 +67,7 @@ describe('Error boundary', () => {
const showDetailsAction = screen.getByRole('button', { name: 'View stack' });
userEvent.click(showDetailsAction);
+ expect(mockOnError).not.toHaveBeenCalled();
expect(screen.queryByText('in BadComponent', { exact: false })).toBeTruthy();
expect(screen.queryByText('in ErrorBoundary', { exact: false })).toBeTruthy();
@@ -98,6 +100,7 @@ describe('Error boundary', () => {
const errorBoundary = wrapComponent();
render(errorBoundary);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(
screen.queryByText('The application has been likely updated on the server.', {
exact: false,
@@ -111,6 +114,7 @@ describe('Error boundary', () => {
const errorBoundary = wrapComponent();
render(errorBoundary);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(
screen.queryByText('Refreshing a page to get newer resources in', { exact: false }),
).toBeTruthy();
@@ -127,6 +131,7 @@ describe('Error boundary', () => {
const stopCountdownAction = screen.getByRole('button', { name: 'Stop countdown' });
userEvent.click(stopCountdownAction);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(
screen.queryByText('Refreshing a page to get newer resources in', { exact: false }),
).toBeFalsy();
@@ -148,6 +153,7 @@ describe('Error boundary', () => {
jest.advanceTimersByTime(35000);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(window.location.reload).toHaveBeenCalled();
expect(window.location.reload).toHaveBeenCalledTimes(1);
});
@@ -161,6 +167,7 @@ describe('Error boundary', () => {
userEvent.click(reloadNowAction);
userEvent.click(reloadNowAction);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(window.location.reload).toHaveBeenCalled();
expect(window.location.reload).toHaveBeenCalledTimes(3);
});
@@ -185,6 +192,7 @@ describe('Error boundary', () => {
window.dispatchEvent(new Event('beforeunload'));
render(errorBoundary);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(
screen.queryByText(
'Contact an administrator if refreshing continues after the next load.',
@@ -225,6 +233,7 @@ describe('Error boundary', () => {
window.dispatchEvent(new Event('beforeunload'));
render(goodComponent);
+ expect(mockOnError).toHaveBeenCalledWith('Loading chunk 23 failed.');
expect(sessionStorage.getItem(STORAGE_KEY_RELOAD_NUMBER)).toBeNull();
});
});
diff --git a/packages/dashboard-frontend/src/Layout/ErrorBoundary/index.tsx b/packages/dashboard-frontend/src/Layout/ErrorBoundary/index.tsx
index c56c270da..c876057c3 100644
--- a/packages/dashboard-frontend/src/Layout/ErrorBoundary/index.tsx
+++ b/packages/dashboard-frontend/src/Layout/ErrorBoundary/index.tsx
@@ -28,7 +28,9 @@ export const STORAGE_KEY_RELOAD_NUMBER = 'UD:ErrorBoundary:reloaded';
const RELOAD_TIMEOUT_SEC = 30;
const RELOADS_FOR_EXTENDED_MESSAGE = 2;
-type Props = PropsWithChildren;
+type Props = PropsWithChildren & {
+ onError: (error?: string) => void;
+};
type State = {
hasError: boolean;
error?: Error;
@@ -74,6 +76,7 @@ export class ErrorBoundary extends React.PureComponent {
});
if (this.testResourceNotFound(error)) {
+ this.props.onError(error.message);
this.setState({
shouldReload: true,
});
diff --git a/packages/dashboard-frontend/src/Layout/StoreErrorsAlert/__tests__/index.spec.tsx b/packages/dashboard-frontend/src/Layout/StoreErrorsAlert/__tests__/index.spec.tsx
index 66362fb80..18192c7a8 100644
--- a/packages/dashboard-frontend/src/Layout/StoreErrorsAlert/__tests__/index.spec.tsx
+++ b/packages/dashboard-frontend/src/Layout/StoreErrorsAlert/__tests__/index.spec.tsx
@@ -138,31 +138,6 @@ describe('StoreErrorAlert component', () => {
const workspacesSettingsAlert = screen.queryByRole('heading', { name: /expected error 7/i });
expect(workspacesSettingsAlert).toBeFalsy();
});
-
- it('should show sanity check error after bootstrap', () => {
- const store = new FakeStoreBuilder().build();
- const { rerender } = renderComponent(store);
-
- // no alerts at this point
- const alertHeading = screen.queryByRole('heading', { name: /danger alert/i });
- expect(alertHeading).toBeFalsy();
-
- const nextStore = new FakeStoreBuilder()
- .withSanityCheck({
- error: 'expected error',
- })
- .build();
- rerender(
-
-
-
- ,
- );
-
- const nextAlertHeading = screen.queryByRole('heading', { name: /danger alert/i });
- expect(nextAlertHeading).toBeTruthy();
- expect(nextAlertHeading).toHaveTextContent('expected error');
- });
});
function renderComponent(store: Store): RenderResult {
diff --git a/packages/dashboard-frontend/src/Layout/index.tsx b/packages/dashboard-frontend/src/Layout/index.tsx
index ba31a3179..ce38ab714 100644
--- a/packages/dashboard-frontend/src/Layout/index.tsx
+++ b/packages/dashboard-frontend/src/Layout/index.tsx
@@ -30,6 +30,8 @@ import { selectBranding } from '../store/Branding/selectors';
import { ToggleBarsContext } from '../contexts/ToggleBars';
import { signOut } from '../services/helpers/login';
import { selectDashboardLogo } from '../store/ServerConfig/selectors';
+import * as SanityCheckStore from '../store/SanityCheck';
+import { selectSanityCheckError } from '../store/SanityCheck/selectors';
const IS_MANAGED_SIDEBAR = false;
@@ -86,6 +88,14 @@ export class Layout extends React.PureComponent {
this.hideAllBars();
}
}
+ private testBackends(error?: string): void {
+ this.props.testBackends().catch(() => {
+ if (error) {
+ console.error(error);
+ }
+ console.error('Error testing backends:', this.props.sanityCheckError);
+ });
+ }
public render(): React.ReactElement {
/* check for startup issues */
@@ -135,7 +145,7 @@ export class Layout extends React.PureComponent {
}
isManagedSidebar={IS_MANAGED_SIDEBAR}
>
-
+ this.testBackends(error)}>
{this.props.children}
@@ -149,9 +159,10 @@ export class Layout extends React.PureComponent {
const mapStateToProps = (state: AppState) => ({
branding: selectBranding(state),
dashboardLogo: selectDashboardLogo(state),
+ sanityCheckError: selectSanityCheckError(state),
});
-const connector = connect(mapStateToProps);
+const connector = connect(mapStateToProps, SanityCheckStore.actionCreators);
type MappedProps = ConnectedProps;
export default connector(Layout);
diff --git a/packages/dashboard-frontend/src/__tests__/workspaceCreationTimeCheck.check.tsx b/packages/dashboard-frontend/src/__tests__/workspaceCreationTimeCheck.check.tsx
index cd3c2e037..c5bda5f94 100644
--- a/packages/dashboard-frontend/src/__tests__/workspaceCreationTimeCheck.check.tsx
+++ b/packages/dashboard-frontend/src/__tests__/workspaceCreationTimeCheck.check.tsx
@@ -91,7 +91,7 @@ describe('Workspace creation time', () => {
await waitFor(
() => expect(mockPost).toBeCalledWith('/api/factory/resolver', expect.anything()),
- { timeout: 6000 },
+ { timeout: 8000 },
);
expect(mockPost).toHaveBeenCalledTimes(1);
expect(mockGet).not.toHaveBeenCalled();
diff --git a/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/__tests__/index.spec.tsx b/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/__tests__/index.spec.tsx
index c64b8e784..b4de42d7e 100644
--- a/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/__tests__/index.spec.tsx
+++ b/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/__tests__/index.spec.tsx
@@ -19,7 +19,7 @@ import { BrandingData } from '../../../../services/bootstrap/branding.constant';
import {
ConnectionEvent,
WebsocketClient,
-} from '../../../../services/dashboard-backend-client/websocketClient';
+} from '../../../../services/backend-client/websocketClient';
import { FakeStoreBuilder } from '../../../../store/__mocks__/storeBuilder';
const failingMessage = 'WebSocket connections are failing';
diff --git a/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/index.tsx b/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/index.tsx
index dccfb4ae8..f79c5a863 100644
--- a/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/index.tsx
+++ b/packages/dashboard-frontend/src/components/BannerAlert/WebSocket/index.tsx
@@ -20,7 +20,7 @@ import {
ConnectionEvent,
ConnectionListener,
WebsocketClient,
-} from '../../../services/dashboard-backend-client/websocketClient';
+} from '../../../services/backend-client/websocketClient';
type Props = MappedProps;
diff --git a/packages/dashboard-frontend/src/inversify.config.ts b/packages/dashboard-frontend/src/inversify.config.ts
index 601d8faf4..941d68534 100644
--- a/packages/dashboard-frontend/src/inversify.config.ts
+++ b/packages/dashboard-frontend/src/inversify.config.ts
@@ -13,20 +13,18 @@
import 'reflect-metadata';
import { Container } from 'inversify';
import getDecorators from 'inversify-inject-decorators';
-import { CheWorkspaceClient } from './services/workspace-client/cheworkspace/cheWorkspaceClient';
import { AppAlerts } from './services/alerts/appAlerts';
import { IssuesReporterService } from './services/bootstrap/issuesReporter';
import { DevWorkspaceClient } from './services/workspace-client/devworkspace/devWorkspaceClient';
import { DevWorkspaceDefaultPluginsHandler } from './services/workspace-client/devworkspace/DevWorkspaceDefaultPluginsHandler';
import { WorkspaceStoppedDetector } from './services/bootstrap/workspaceStoppedDetector';
-import { WebsocketClient } from './services/dashboard-backend-client/websocketClient';
+import { WebsocketClient } from './services/backend-client/websocketClient';
const container = new Container();
const { lazyInject } = getDecorators(container);
container.bind(IssuesReporterService).toSelf().inSingletonScope();
container.bind(WebsocketClient).toSelf().inSingletonScope();
-container.bind(CheWorkspaceClient).toSelf().inSingletonScope();
container.bind(DevWorkspaceClient).toSelf().inSingletonScope();
container.bind(AppAlerts).toSelf().inSingletonScope();
container.bind(DevWorkspaceDefaultPluginsHandler).toSelf().inSingletonScope();
diff --git a/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/GitRepoLocationInput.tsx b/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/GitRepoLocationInput.tsx
index 4ea52209f..d6efee721 100644
--- a/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/GitRepoLocationInput.tsx
+++ b/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/GitRepoLocationInput.tsx
@@ -28,7 +28,6 @@ import { ExclamationCircleIcon } from '@patternfly/react-icons';
import { FactoryLocationAdapter } from '../../../../services/factory-location-adapter';
const ERROR_PATTERN_MISMATCH = 'The URL or SSHLocation is not valid.';
-const ERROR_FAILED_LOAD = 'Failed to load the devfile.';
type Props = {
onChange: (location: string) => void;
@@ -41,8 +40,6 @@ type State = {
};
export class GitRepoLocationInput extends React.PureComponent {
- options: JSX.Element[];
-
constructor(props: Props) {
super(props);
@@ -52,16 +49,6 @@ export class GitRepoLocationInput extends React.PureComponent {
};
}
- /**
- * This method is used from parent component by reference.
- */
- public invalidateInput(): void {
- this.setState({
- errorMessage: ERROR_FAILED_LOAD,
- validated: ValidatedOptions.error,
- });
- }
-
private handleChange(location: string): void {
const isValid =
FactoryLocationAdapter.isHttpLocation(location) ||
diff --git a/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/index.tsx b/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/index.tsx
index 1363c6bca..0168d9a69 100644
--- a/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/index.tsx
+++ b/packages/dashboard-frontend/src/pages/GetStarted/GetStartedTab/ImportFromGit/index.tsx
@@ -11,36 +11,25 @@
*/
import React from 'react';
-import { connect, ConnectedProps } from 'react-redux';
import { Flex, FlexItem, FormGroup, Text, TextContent, TextVariants } from '@patternfly/react-core';
-import { AppState } from '../../../../store';
-import * as DevfileRegistriesStore from '../../../../store/DevfileRegistries';
import * as FactoryResolverStore from '../../../../store/FactoryResolver';
import { GitRepoLocationInput } from './GitRepoLocationInput';
import { FactoryLocationAdapter } from '../../../../services/factory-location-adapter';
-type Props = MappedProps & {
+type Props = {
onDevfileResolve: (resolverState: FactoryResolverStore.ResolverState, location: string) => void;
};
type State = {
isLoading: boolean;
};
-export class ImportFromGit extends React.PureComponent {
- private factoryResolver: FactoryResolverStore.State;
- private readonly devfileLocationRef: React.RefObject;
-
+export default class ImportFromGit extends React.PureComponent {
constructor(props: Props) {
super(props);
this.state = {
isLoading: false,
};
- this.devfileLocationRef = React.createRef();
- }
-
- public componentDidUpdate(): void {
- this.factoryResolver = this.props.factoryResolver;
}
private async handleLocationChange(location: string): Promise {
@@ -73,7 +62,6 @@ export class ImportFromGit extends React.PureComponent {
this.handleLocationChange(location)}
/>
@@ -84,14 +72,3 @@ export class ImportFromGit extends React.PureComponent {
);
}
}
-
-const mapStateToProps = (state: AppState) => ({
- factoryResolver: state.factoryResolver,
-});
-
-const connector = connect(mapStateToProps, {
- ...DevfileRegistriesStore.actionCreators,
-});
-
-type MappedProps = ConnectedProps;
-export default connector(ImportFromGit);
diff --git a/packages/dashboard-frontend/src/services/backend-client/__tests__/factoryApi.spec.tsx b/packages/dashboard-frontend/src/services/backend-client/__tests__/factoryApi.spec.tsx
new file mode 100644
index 000000000..dbc828cfc
--- /dev/null
+++ b/packages/dashboard-frontend/src/services/backend-client/__tests__/factoryApi.spec.tsx
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+
+import mockAxios from 'axios';
+import { getFactoryResolver, refreshFactoryOauthToken } from '../factoryApi';
+import { FactoryResolver } from '../../helpers/types';
+import devfileApi from '../../devfileApi';
+
+describe('Factory API', () => {
+ const mockPost = mockAxios.post as jest.Mock;
+
+ const location = 'https://github.com/eclipse-che/che-dashboard.git';
+ const factoryResolver: FactoryResolver = {
+ v: '4.0',
+ source: 'devfile.yaml',
+ scm_info: {
+ clone_url: location,
+ scm_provider: 'github',
+ },
+ devfile: {
+ schemaVersion: '2.2.1',
+ metadata: {
+ name: 'che-dashboard',
+ namespace: 'namespace',
+ },
+ } as devfileApi.Devfile,
+ links: [],
+ };
+
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ describe('resolve factory', () => {
+ it('should call "/factory/resolver"', async () => {
+ mockPost.mockResolvedValueOnce({
+ data: expect.anything(),
+ });
+ await getFactoryResolver(location, {});
+
+ expect(mockPost).toBeCalledWith('/api/factory/resolver', {
+ url: 'https://github.com/eclipse-che/che-dashboard.git',
+ });
+ });
+
+ it('should return a factory resolver', async () => {
+ mockPost.mockResolvedValueOnce({
+ data: factoryResolver,
+ });
+
+ const res = await getFactoryResolver(location, {});
+
+ expect(res).toEqual(factoryResolver);
+ });
+ });
+
+ describe('refresh factory OAuth token', () => {
+ it('should call "/api/factory/token/refresh?url=${url}"', async () => {
+ mockPost.mockResolvedValueOnce({
+ data: expect.anything(),
+ });
+
+ await refreshFactoryOauthToken(location);
+
+ expect(mockPost).toBeCalledWith(
+ '/api/factory/token/refresh?url=https://github.com/eclipse-che/che-dashboard.git',
+ );
+ });
+
+ it('should return undefined', async () => {
+ mockPost.mockResolvedValueOnce(undefined);
+
+ const res = await refreshFactoryOauthToken(location);
+
+ expect(res).toBeUndefined();
+ });
+ });
+});
diff --git a/packages/dashboard-frontend/src/services/backend-client/__tests__/kubernetesNamespaceApi.spec.tsx b/packages/dashboard-frontend/src/services/backend-client/__tests__/kubernetesNamespaceApi.spec.tsx
new file mode 100644
index 000000000..7b1ed92b0
--- /dev/null
+++ b/packages/dashboard-frontend/src/services/backend-client/__tests__/kubernetesNamespaceApi.spec.tsx
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+
+import mockAxios from 'axios';
+import { getKubernetesNamespace, provisionKubernetesNamespace } from '../kubernetesNamespaceApi';
+
+describe('Kubernetes namespace API', () => {
+ const mockGet = mockAxios.get as jest.Mock;
+ const mockPost = mockAxios.post as jest.Mock;
+
+ const namespace: che.KubernetesNamespace = { name: 'test-name', attributes: { phase: 'Active' } };
+
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ describe('fetch namespace', () => {
+ it('should call "/api/kubernetes/namespace"', async () => {
+ mockGet.mockResolvedValueOnce({
+ data: expect.anything(),
+ });
+ await getKubernetesNamespace();
+
+ expect(mockGet).toBeCalledWith('/api/kubernetes/namespace');
+ expect(mockPost).not.toBeCalled();
+ });
+
+ it('should return a list of namespaces', async () => {
+ mockGet.mockResolvedValueOnce({
+ data: [namespace],
+ });
+
+ const res = await getKubernetesNamespace();
+
+ expect(res).toEqual([namespace]);
+ });
+ });
+
+ describe('provision namespace', () => {
+ it('should call "/api/kubernetes/namespace/provision"', async () => {
+ mockPost.mockResolvedValueOnce({
+ data: expect.anything(),
+ });
+ await provisionKubernetesNamespace();
+
+ expect(mockGet).not.toBeCalled();
+ expect(mockPost).toBeCalledWith('/api/kubernetes/namespace/provision');
+ });
+
+ it('should return a list of namespaces', async () => {
+ mockPost.mockResolvedValueOnce({
+ data: [namespace],
+ });
+
+ const res = await provisionKubernetesNamespace();
+
+ expect(res).toEqual([namespace]);
+ });
+ });
+});
diff --git a/packages/dashboard-frontend/src/services/backend-client/__tests__/oAuthApi.spec.tsx b/packages/dashboard-frontend/src/services/backend-client/__tests__/oAuthApi.spec.tsx
new file mode 100644
index 000000000..c425bc46d
--- /dev/null
+++ b/packages/dashboard-frontend/src/services/backend-client/__tests__/oAuthApi.spec.tsx
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+
+import mockAxios from 'axios';
+import { IGitOauth } from '../../../store/GitOauthConfig/types';
+import { deleteOAuthToken, getOAuthProviders, getOAuthToken } from '../oAuthApi';
+
+describe('Open Authorization API', () => {
+ const mockGet = mockAxios.get as jest.Mock;
+ const mockDelete = mockAxios.delete as jest.Mock;
+
+ const oAuthProvider = { name: 'github', endpointUrl: 'https://github.com' } as IGitOauth;
+ const oAuthProviderToken = { token: 'dummy_token' };
+
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ describe('fetch OAuthProviders', () => {
+ it('should call "/api/oauth"', async () => {
+ mockGet.mockResolvedValueOnce({
+ data: expect.anything(),
+ });
+ await getOAuthProviders();
+
+ expect(mockDelete).not.toBeCalled();
+ expect(mockGet).toBeCalledWith('/api/oauth');
+ });
+
+ it('should return a list of providers', async () => {
+ mockGet.mockResolvedValueOnce({
+ data: [oAuthProvider],
+ });
+
+ const res = await getOAuthProviders();
+
+ expect(res).toEqual([oAuthProvider]);
+ });
+ });
+
+ describe('fetch OAuthToken', () => {
+ it('should call "/api/oauth/token?oauth_provider=github"', async () => {
+ mockGet.mockResolvedValueOnce({
+ data: expect.anything(),
+ });
+
+ await getOAuthToken(oAuthProvider.name);
+
+ expect(mockDelete).not.toBeCalled();
+ expect(mockGet).toBeCalledWith('/api/oauth/token?oauth_provider=github');
+ });
+
+ it('should return the OAuth token', async () => {
+ mockGet.mockResolvedValueOnce({
+ data: oAuthProviderToken,
+ });
+
+ const res = await getOAuthToken(oAuthProvider.name);
+
+ expect(mockDelete).not.toBeCalled();
+ expect(res).toEqual(oAuthProviderToken);
+ });
+ });
+
+ describe('delete OAuthToken', () => {
+ it('should call "/api/oauth/token?oauth_provider=github"', async () => {
+ mockDelete.mockResolvedValueOnce(undefined);
+
+ await deleteOAuthToken(oAuthProvider.name);
+
+ expect(mockGet).not.toBeCalled();
+ expect(mockDelete).toBeCalledWith('/api/oauth/token?oauth_provider=github');
+ });
+
+ it('should return undefined', async () => {
+ mockDelete.mockResolvedValueOnce(undefined);
+
+ const res = await deleteOAuthToken(oAuthProvider.name);
+
+ expect(mockGet).not.toBeCalled();
+ expect(res).toBeUndefined();
+ });
+ });
+});
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/clusterConfigApi.ts b/packages/dashboard-frontend/src/services/backend-client/clusterConfigApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/clusterConfigApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/clusterConfigApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/clusterInfoApi.ts b/packages/dashboard-frontend/src/services/backend-client/clusterInfoApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/clusterInfoApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/clusterInfoApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/const.ts b/packages/dashboard-frontend/src/services/backend-client/const.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/const.ts
rename to packages/dashboard-frontend/src/services/backend-client/const.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/devWorkspaceApi.ts b/packages/dashboard-frontend/src/services/backend-client/devWorkspaceApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/devWorkspaceApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/devWorkspaceApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/devWorkspaceTemplateApi.ts b/packages/dashboard-frontend/src/services/backend-client/devWorkspaceTemplateApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/devWorkspaceTemplateApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/devWorkspaceTemplateApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/devworkspaceResourcesApi.ts b/packages/dashboard-frontend/src/services/backend-client/devworkspaceResourcesApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/devworkspaceResourcesApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/devworkspaceResourcesApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/eventsApi.ts b/packages/dashboard-frontend/src/services/backend-client/eventsApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/eventsApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/eventsApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/factoryResolverApi.ts b/packages/dashboard-frontend/src/services/backend-client/factoryApi.ts
similarity index 76%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/factoryResolverApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/factoryApi.ts
index bace20774..cadb9fdd5 100644
--- a/packages/dashboard-frontend/src/services/dashboard-backend-client/factoryResolverApi.ts
+++ b/packages/dashboard-frontend/src/services/backend-client/factoryApi.ts
@@ -14,16 +14,20 @@ import axios from 'axios';
import { cheServerPrefix } from './const';
import { FactoryResolver } from '../helpers/types';
-const factoryResolverEndpoint = '/factory/resolver';
-
export async function getFactoryResolver(
url: string,
overrideParams: { [params: string]: string } = {},
): Promise {
const response = await axios.post(
- `${cheServerPrefix}${factoryResolverEndpoint}`,
+ `${cheServerPrefix}/factory/resolver`,
Object.assign({}, overrideParams, { url }),
);
return response.data;
}
+
+export async function refreshFactoryOauthToken(url: string): Promise {
+ await axios.post(`${cheServerPrefix}/factory/token/refresh?url=${url}`);
+
+ return Promise.resolve();
+}
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/gitConfigApi.ts b/packages/dashboard-frontend/src/services/backend-client/gitConfigApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/gitConfigApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/gitConfigApi.ts
diff --git a/packages/dashboard-frontend/src/services/backend-client/kubernetesNamespaceApi.ts b/packages/dashboard-frontend/src/services/backend-client/kubernetesNamespaceApi.ts
new file mode 100644
index 000000000..a80986d0d
--- /dev/null
+++ b/packages/dashboard-frontend/src/services/backend-client/kubernetesNamespaceApi.ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+
+import axios from 'axios';
+import { cheServerPrefix } from './const';
+
+export async function getKubernetesNamespace(): Promise {
+ const response = await axios.get(`${cheServerPrefix}/kubernetes/namespace`);
+
+ return response.data;
+}
+
+export async function provisionKubernetesNamespace(): Promise {
+ const response = await axios.post(`${cheServerPrefix}/kubernetes/namespace/provision`);
+
+ return response.data;
+}
diff --git a/packages/dashboard-frontend/src/services/backend-client/oAuthApi.ts b/packages/dashboard-frontend/src/services/backend-client/oAuthApi.ts
new file mode 100644
index 000000000..79991a81b
--- /dev/null
+++ b/packages/dashboard-frontend/src/services/backend-client/oAuthApi.ts
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2023 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+
+import axios from 'axios';
+import { cheServerPrefix } from './const';
+import { api } from '@eclipse-che/common';
+import { IGitOauth } from '../../store/GitOauthConfig/types';
+
+export async function getOAuthProviders(): Promise {
+ const response = await axios.get(`${cheServerPrefix}/oauth`);
+
+ return response.data;
+}
+
+export async function getOAuthToken(provider: api.GitOauthProvider): Promise<{ token: string }> {
+ const response = await axios.get(`${cheServerPrefix}/oauth/token?oauth_provider=${provider}`);
+
+ return response.data;
+}
+
+export async function deleteOAuthToken(provider: api.GitOauthProvider): Promise {
+ await axios.delete(`${cheServerPrefix}/oauth/token?oauth_provider=${provider}`);
+
+ return Promise.resolve();
+}
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/personalAccessTokenApi.ts b/packages/dashboard-frontend/src/services/backend-client/personalAccessTokenApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/personalAccessTokenApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/personalAccessTokenApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/podsApi.ts b/packages/dashboard-frontend/src/services/backend-client/podsApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/podsApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/podsApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/serverConfigApi.ts b/packages/dashboard-frontend/src/services/backend-client/serverConfigApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/serverConfigApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/serverConfigApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/userProfileApi.ts b/packages/dashboard-frontend/src/services/backend-client/userProfileApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/userProfileApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/userProfileApi.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/__tests__/index.spec.ts b/packages/dashboard-frontend/src/services/backend-client/websocketClient/__tests__/index.spec.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/__tests__/index.spec.ts
rename to packages/dashboard-frontend/src/services/backend-client/websocketClient/__tests__/index.spec.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/__tests__/messageHandler.spec.ts b/packages/dashboard-frontend/src/services/backend-client/websocketClient/__tests__/messageHandler.spec.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/__tests__/messageHandler.spec.ts
rename to packages/dashboard-frontend/src/services/backend-client/websocketClient/__tests__/messageHandler.spec.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/__tests__/subscriptionsManager.spec.ts b/packages/dashboard-frontend/src/services/backend-client/websocketClient/__tests__/subscriptionsManager.spec.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/__tests__/subscriptionsManager.spec.ts
rename to packages/dashboard-frontend/src/services/backend-client/websocketClient/__tests__/subscriptionsManager.spec.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/index.ts b/packages/dashboard-frontend/src/services/backend-client/websocketClient/index.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/index.ts
rename to packages/dashboard-frontend/src/services/backend-client/websocketClient/index.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/messageHandler.ts b/packages/dashboard-frontend/src/services/backend-client/websocketClient/messageHandler.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/messageHandler.ts
rename to packages/dashboard-frontend/src/services/backend-client/websocketClient/messageHandler.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/subscriptionsManager.ts b/packages/dashboard-frontend/src/services/backend-client/websocketClient/subscriptionsManager.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/websocketClient/subscriptionsManager.ts
rename to packages/dashboard-frontend/src/services/backend-client/websocketClient/subscriptionsManager.ts
diff --git a/packages/dashboard-frontend/src/services/dashboard-backend-client/yamlResolverApi.ts b/packages/dashboard-frontend/src/services/backend-client/yamlResolverApi.ts
similarity index 100%
rename from packages/dashboard-frontend/src/services/dashboard-backend-client/yamlResolverApi.ts
rename to packages/dashboard-frontend/src/services/backend-client/yamlResolverApi.ts
diff --git a/packages/dashboard-frontend/src/services/bootstrap/index.ts b/packages/dashboard-frontend/src/services/bootstrap/index.ts
index 7662967cf..39b0c1579 100644
--- a/packages/dashboard-frontend/src/services/bootstrap/index.ts
+++ b/packages/dashboard-frontend/src/services/bootstrap/index.ts
@@ -41,10 +41,10 @@ import { Workspace } from '../workspace-adapter';
import { WorkspaceRunningError, WorkspaceStoppedDetector } from './workspaceStoppedDetector';
import { selectOpenVSXUrl } from '../../store/ServerConfig/selectors';
import { selectEmptyWorkspaceUrl } from '../../store/DevfileRegistries/selectors';
-import { WebsocketClient } from '../dashboard-backend-client/websocketClient';
+import { WebsocketClient } from '../backend-client/websocketClient';
import { selectEventsResourceVersion } from '../../store/Events/selectors';
import { selectPodsResourceVersion } from '../../store/Pods/selectors';
-import { ChannelListener } from '../dashboard-backend-client/websocketClient/messageHandler';
+import { ChannelListener } from '../backend-client/websocketClient/messageHandler';
import { selectApplications } from '../../store/ClusterInfo/selectors';
import { isAvailableEndpoint } from '../helpers/api-ping';
import { DEFAULT_REGISTRY } from '../../store/DevfileRegistries';
diff --git a/packages/dashboard-frontend/src/services/helpers/types.ts b/packages/dashboard-frontend/src/services/helpers/types.ts
index 80a2b4af6..8c4cf7511 100644
--- a/packages/dashboard-frontend/src/services/helpers/types.ts
+++ b/packages/dashboard-frontend/src/services/helpers/types.ts
@@ -13,6 +13,7 @@
import { AlertVariant } from '@patternfly/react-core';
import * as React from 'react';
import devfileApi from '../devfileApi';
+import * as cheApi from '@eclipse-che/api';
export type ActionCallback = {
title: string;
@@ -35,7 +36,7 @@ export interface FactoryResolver {
devfile: devfileApi.Devfile | che.WorkspaceDevfile;
location?: string;
scm_info?: FactoryResolverScmInfo;
- links: api.che.core.rest.Link[];
+ links: cheApi.che.core.rest.Link[];
}
export type FactoryResolverScmInfo = {
diff --git a/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts b/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts
index 21aff6029..5a15c2e85 100644
--- a/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts
+++ b/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts
@@ -13,16 +13,10 @@
import { AxiosError } from 'axios';
import common from '@eclipse-che/common';
import OAuthService from '..';
-import { container } from '../../../inversify.config';
import { DevWorkspaceBuilder } from '../../../store/__mocks__/devWorkspaceBuilder';
-import { CheWorkspaceClient } from '../../workspace-client/cheworkspace/cheWorkspaceClient';
+import * as factoryApi from '../../backend-client/factoryApi';
-const cheWorkspaceClient = container.get(CheWorkspaceClient);
-
-const refreshFactoryOauthTokenSpy = jest.spyOn(
- cheWorkspaceClient.restApiClient,
- 'refreshFactoryOauthToken',
-);
+const refreshFactoryOauthTokenSpy = jest.spyOn(factoryApi, 'refreshFactoryOauthToken');
const mockOpenOAuthPage = jest.fn().mockImplementation();
OAuthService.openOAuthPage = mockOpenOAuthPage;
diff --git a/packages/dashboard-frontend/src/services/oauth/index.ts b/packages/dashboard-frontend/src/services/oauth/index.ts
index 9f6953d69..2518dee6f 100644
--- a/packages/dashboard-frontend/src/services/oauth/index.ts
+++ b/packages/dashboard-frontend/src/services/oauth/index.ts
@@ -12,11 +12,8 @@
import common, { helpers } from '@eclipse-che/common';
import { OAuthResponse } from '../../store/FactoryResolver';
-import { container } from '../../inversify.config';
-import { CheWorkspaceClient } from '../workspace-client/cheworkspace/cheWorkspaceClient';
import devfileApi from '../devfileApi';
-
-const WorkspaceClient = container.get(CheWorkspaceClient);
+import { refreshFactoryOauthToken } from '../backend-client/factoryApi';
export default class OAuthService {
static openOAuthPage(authenticationUrl: string, redirectUrl: string): void {
@@ -44,7 +41,7 @@ export default class OAuthService {
}
try {
- await WorkspaceClient.restApiClient.refreshFactoryOauthToken(project.git.remotes.origin);
+ await refreshFactoryOauthToken(project.git.remotes.origin);
} catch (e) {
if (!common.helpers.errors.includesAxiosResponse(e)) {
return;
diff --git a/packages/dashboard-frontend/src/services/workspace-client/__tests__/helpers.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/__tests__/helpers.spec.ts
index 124c82401..12dd9fd50 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/__tests__/helpers.spec.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/__tests__/helpers.spec.ts
@@ -10,14 +10,71 @@
* Red Hat, Inc. - initial API and implementation
*/
-import { getCustomEditor, isForbidden, isInternalServerError, isUnauthorized } from '../helpers';
-import { CHE_EDITOR_YAML_PATH } from '../';
+import {
+ getCustomEditor,
+ hasLoginPage,
+ getErrorMessage,
+ isForbidden,
+ isInternalServerError,
+ isUnauthorized,
+} from '../helpers';
+import { CHE_EDITOR_YAML_PATH } from '../helpers';
import { dump } from 'js-yaml';
import common from '@eclipse-che/common';
import devfileApi from '../../devfileApi';
import { FakeStoreBuilder } from '../../../store/__mocks__/storeBuilder';
describe('Workspace-client helpers', () => {
+ describe('get an error message', () => {
+ it('should return the default error message', () => {
+ expect(getErrorMessage(undefined)).toEqual('Check the browser logs message.');
+ });
+ it('should return the unknown error message', () => {
+ expect(getErrorMessage({})).toEqual('Unexpected error type. Please report a bug.');
+ });
+ it('should return the error message', () => {
+ expect(
+ getErrorMessage({
+ response: {
+ status: 401,
+ },
+ request: {
+ responseURL: 'http://dummyurl.com',
+ },
+ }),
+ ).toEqual(
+ 'HTTP Error code 401. Endpoint which throws an error http://dummyurl.com. Check the browser logs message.',
+ );
+ });
+ });
+ describe('checks for HTML login page in response data', () => {
+ it('should return false without HTML login page', () => {
+ expect(
+ hasLoginPage({
+ response: {
+ status: 401,
+ statusText: '...',
+ headers: {},
+ config: {},
+ data: '...',
+ },
+ }),
+ ).toBeFalsy();
+ });
+ it('should return true in the case with HTML login page', () => {
+ expect(
+ hasLoginPage({
+ response: {
+ status: 401,
+ statusText: '...',
+ headers: {},
+ config: {},
+ data: 'Log In',
+ },
+ }),
+ ).toBeTruthy();
+ });
+ });
describe('checks for HTTP 401 Unauthorized response status code', () => {
it('should return false in the case with HTTP 400 Bad Request', () => {
expect(isUnauthorized('...HTTP Status 400 ....')).toBeFalsy();
diff --git a/packages/dashboard-frontend/src/services/workspace-client/cheworkspace/cheWorkspaceClient.ts b/packages/dashboard-frontend/src/services/workspace-client/cheworkspace/cheWorkspaceClient.ts
deleted file mode 100644
index 9c783beeb..000000000
--- a/packages/dashboard-frontend/src/services/workspace-client/cheworkspace/cheWorkspaceClient.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2018-2023 Red Hat, Inc.
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Red Hat, Inc. - initial API and implementation
- */
-
-import { injectable } from 'inversify';
-import { default as WorkspaceClientLib, IRemoteAPI } from '@eclipse-che/workspace-client';
-
-/**
- * This class manages the api connection.
- */
-@injectable()
-export class CheWorkspaceClient {
- private baseUrl: string;
- private _restApiClient: IRemoteAPI;
-
- /**
- * Default constructor that is using resource.
- */
- constructor() {
- this.baseUrl = '/api';
- }
-
- get restApiClient(): IRemoteAPI {
- // Lazy initialization of restApiClient
- if (!this._restApiClient) {
- this.updateRestApiClient();
- }
- return this._restApiClient;
- }
-
- updateRestApiClient(): void {
- const baseUrl = this.baseUrl;
- this._restApiClient = WorkspaceClientLib.getRestApi({ baseUrl });
- }
-}
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/DevWorkspaceDefaultPluginsHandler.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/DevWorkspaceDefaultPluginsHandler.ts
index aceaf43dd..932498c11 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/DevWorkspaceDefaultPluginsHandler.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/DevWorkspaceDefaultPluginsHandler.ts
@@ -10,7 +10,7 @@
* Red Hat, Inc. - initial API and implementation
*/
-import * as DwApi from '../../dashboard-backend-client/devWorkspaceApi';
+import * as DwApi from '../../backend-client/devWorkspaceApi';
import devfileApi from '../../devfileApi';
import { api } from '@eclipse-che/common';
import { createHash } from 'crypto';
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.changeWorkspaceStatus.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.changeWorkspaceStatus.spec.ts
index 2e1738a3f..b49b7d8ce 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.changeWorkspaceStatus.spec.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.changeWorkspaceStatus.spec.ts
@@ -13,7 +13,7 @@
import { container } from '../../../../inversify.config';
import { DevWorkspaceBuilder } from '../../../../store/__mocks__/devWorkspaceBuilder';
import { DevWorkspaceClient } from '../devWorkspaceClient';
-import * as DwApi from '../../../dashboard-backend-client/devWorkspaceApi';
+import * as DwApi from '../../../backend-client/devWorkspaceApi';
describe('DevWorkspace client, changeWorkspaceStatus', () => {
let client: DevWorkspaceClient;
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts
index 557432a82..165f29e52 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.create.spec.ts
@@ -12,8 +12,8 @@
import { container } from '../../../../inversify.config';
import { DevWorkspaceClient } from '../devWorkspaceClient';
-import * as DwtApi from '../../../dashboard-backend-client/devWorkspaceTemplateApi';
-import * as DwApi from '../../../dashboard-backend-client/devWorkspaceApi';
+import * as DwtApi from '../../../backend-client/devWorkspaceTemplateApi';
+import * as DwApi from '../../../backend-client/devWorkspaceApi';
import devfileApi from '../../../devfileApi';
describe('DevWorkspace client, create', () => {
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts
index 555362c37..89879393b 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.editorUpdate.spec.ts
@@ -13,10 +13,10 @@
import { container } from '../../../../inversify.config';
import { DevWorkspaceClient } from '../devWorkspaceClient';
import mockAxios from 'axios';
-import { dashboardBackendPrefix } from '../../../dashboard-backend-client/const';
+import { dashboardBackendPrefix } from '../../../backend-client/const';
import getDevWorkspaceTemplate from './__mocks__/devWorkspaceSpecTemplates';
import devfileApi from '../../../devfileApi';
-import * as DwtApi from '../../../dashboard-backend-client/devWorkspaceTemplateApi';
+import * as DwtApi from '../../../backend-client/devWorkspaceTemplateApi';
describe('DevWorkspace client editor update', () => {
const namespace = 'admin-che';
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.onStart.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.onStart.spec.ts
index 223b1836c..54fffda36 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.onStart.spec.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.onStart.spec.ts
@@ -13,7 +13,7 @@
import { container } from '../../../../inversify.config';
import { DevWorkspaceBuilder } from '../../../../store/__mocks__/devWorkspaceBuilder';
import { DevWorkspaceClient } from '../devWorkspaceClient';
-import * as DwApi from '../../../dashboard-backend-client/devWorkspaceApi';
+import * as DwApi from '../../../backend-client/devWorkspaceApi';
import mockAxios from 'axios';
/* eslint-disable @typescript-eslint/no-non-null-assertion */
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.update.spec.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.update.spec.ts
index 72eb58f9f..59a3b1ea1 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.update.spec.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/__tests__/devWorkspaceClient.update.spec.ts
@@ -13,7 +13,7 @@
import { container } from '../../../../inversify.config';
import { DevWorkspaceBuilder } from '../../../../store/__mocks__/devWorkspaceBuilder';
import { DevWorkspaceClient } from '../devWorkspaceClient';
-import * as DwApi from '../../../dashboard-backend-client/devWorkspaceApi';
+import * as DwApi from '../../../backend-client/devWorkspaceApi';
describe('DevWorkspace client, update', () => {
let client: DevWorkspaceClient;
diff --git a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts
index 629ce1cc2..bdb67e226 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/devworkspace/devWorkspaceClient.ts
@@ -18,11 +18,11 @@ import {
} from '@devfile/api';
import { api } from '@eclipse-che/common';
import { WorkspacesDefaultPlugins } from 'dashboard-frontend/src/store/Plugins/devWorkspacePlugins';
-import { decorate, inject, injectable } from 'inversify';
+import { inject, injectable } from 'inversify';
import { load } from 'js-yaml';
import { cloneDeep, isEqual } from 'lodash';
-import * as DwApi from '../../dashboard-backend-client/devWorkspaceApi';
-import * as DwtApi from '../../dashboard-backend-client/devWorkspaceTemplateApi';
+import * as DwApi from '../../backend-client/devWorkspaceApi';
+import * as DwtApi from '../../backend-client/devWorkspaceTemplateApi';
import devfileApi from '../../devfileApi';
import {
DEVWORKSPACE_CHE_EDITOR,
@@ -38,7 +38,6 @@ import { isWebTerminal } from '../../helpers/devworkspace';
import { DevWorkspaceStatus } from '../../helpers/types';
import { fetchData } from '../../registry/fetchData';
import { WorkspaceAdapter } from '../../workspace-adapter';
-import { WorkspaceClient } from '../index';
import {
devWorkspaceApiGroup,
devWorkspaceSingularSubresource,
@@ -73,13 +72,11 @@ export interface ICheEditorYaml {
};
}
-decorate(injectable(), WorkspaceClient);
-
/**
* This class manages the connection between the frontend and the devworkspace typescript library
*/
@injectable()
-export class DevWorkspaceClient extends WorkspaceClient {
+export class DevWorkspaceClient {
private readonly maxStatusAttempts: number;
private readonly pluginRegistryUrlEnvName: string;
private readonly pluginRegistryInternalUrlEnvName: string;
@@ -93,7 +90,6 @@ export class DevWorkspaceClient extends WorkspaceClient {
@inject(DevWorkspaceDefaultPluginsHandler)
defaultPluginsHandler: DevWorkspaceDefaultPluginsHandler,
) {
- super();
this.maxStatusAttempts = 10;
this.pluginRegistryUrlEnvName = 'CHE_PLUGIN_REGISTRY_URL';
this.pluginRegistryInternalUrlEnvName = 'CHE_PLUGIN_REGISTRY_INTERNAL_URL';
diff --git a/packages/dashboard-frontend/src/services/workspace-client/helpers.ts b/packages/dashboard-frontend/src/services/workspace-client/helpers.ts
index 847816c31..c64cc1df6 100644
--- a/packages/dashboard-frontend/src/services/workspace-client/helpers.ts
+++ b/packages/dashboard-frontend/src/services/workspace-client/helpers.ts
@@ -14,52 +14,96 @@ import common from '@eclipse-che/common';
import devfileApi, { isDevfileV2 } from '../devfileApi';
import { load, dump } from 'js-yaml';
import { ICheEditorYaml } from './devworkspace/devWorkspaceClient';
-import { CHE_EDITOR_YAML_PATH } from './';
import { AppState } from '../../store';
import { ThunkDispatch } from 'redux-thunk';
import { KnownAction } from '../../store/DevfileRegistries';
import { getEditor } from '../../store/DevfileRegistries/getEditor';
+import { includesAxiosResponse } from '@eclipse-che/common/lib/helpers/errors';
+
+/**
+ * Returns an error message for the sanity check service
+ */
+export function getErrorMessage(error: unknown): string {
+ let errorMessage = 'Check the browser logs message.';
+
+ if (typeof error === 'object' && error !== null) {
+ const { request, response } = error as { [propName: string]: any };
+ const code = response?.status ? response?.status : response?.request?.status;
+ const endpoint = request?.responseURL ? request?.responseURL : response?.request?.responseURL;
+
+ if (!code || !endpoint) {
+ return 'Unexpected error type. Please report a bug.';
+ }
+
+ errorMessage = `HTTP Error code ${code}. Endpoint which throws an error ${endpoint}. ${errorMessage}`;
+ }
+
+ if (isUnauthorized(error) || isForbidden(error)) {
+ errorMessage += ' User session has expired. You need to re-login to the Dashboard.';
+ }
+
+ return errorMessage;
+}
+
+/**
+ * Checks for login page in the axios response data
+ */
+export function hasLoginPage(error: unknown): boolean {
+ if (includesAxiosResponse(error)) {
+ const response = error.response;
+ if (typeof response.data === 'string') {
+ try {
+ const doc = new DOMParser().parseFromString(response.data, 'text/html');
+ const docText = doc.documentElement.textContent;
+ if (docText && docText.toLowerCase().indexOf('log in') !== -1) {
+ return true;
+ }
+ } catch (e) {
+ // no op
+ }
+ }
+ }
+ return false;
+}
/**
* Checks for HTTP 401 Unauthorized response status code
*/
-export function isUnauthorized(response: unknown): boolean {
- return hasStatus(response, 401);
+export function isUnauthorized(error: unknown): boolean {
+ return hasStatus(error, 401);
}
/**
* Checks for HTTP 403 Forbidden
*/
-export function isForbidden(response: unknown): boolean {
- return hasStatus(response, 403);
+export function isForbidden(error: unknown): boolean {
+ return hasStatus(error, 403);
}
/**
* Checks for HTTP 500 Internal Server Error
*/
-export function isInternalServerError(response: unknown): boolean {
- return hasStatus(response, 500);
+export function isInternalServerError(error: unknown): boolean {
+ return hasStatus(error, 500);
}
-function hasStatus(response: unknown, _status: number): boolean {
- if (typeof response === 'string') {
- if (response.toLowerCase().includes(`http status ${_status}`)) {
+function hasStatus(error: unknown, _status: number): boolean {
+ if (typeof error === 'string') {
+ if (error.toLowerCase().includes(`http status ${_status}`)) {
return true;
}
- } else if (common.helpers.errors.isError(response)) {
- const str = response.message.toLowerCase();
+ } else if (common.helpers.errors.isError(error)) {
+ const str = error.message.toLowerCase();
if (str.includes(`status code ${_status}`)) {
return true;
}
- } else if (typeof response === 'object' && response !== null) {
- const { status, statusCode } = response as { [propName: string]: string | number };
- if (statusCode == _status) {
- return true;
- } else if (status == _status) {
+ } else if (typeof error === 'object' && error !== null) {
+ const { status, statusCode } = error as { [propName: string]: string | number };
+ if (statusCode == _status || status == _status) {
return true;
} else {
try {
- const str = JSON.stringify(response).toLowerCase();
+ const str = JSON.stringify(error).toLowerCase();
if (str.includes(`http status ${_status}`)) {
return true;
} else if (str.includes(`status code ${_status}`)) {
@@ -73,6 +117,8 @@ function hasStatus(response: unknown, _status: number): boolean {
return false;
}
+export const CHE_EDITOR_YAML_PATH = '.che/che-editor.yaml';
+
/**
* Look for the custom editor in .che/che-editor.yaml
*/
diff --git a/packages/dashboard-frontend/src/services/workspace-client/index.ts b/packages/dashboard-frontend/src/services/workspace-client/index.ts
deleted file mode 100644
index b708ea009..000000000
--- a/packages/dashboard-frontend/src/services/workspace-client/index.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2018-2023 Red Hat, Inc.
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Red Hat, Inc. - initial API and implementation
- */
-
-import { default as WorkspaceClientLib } from '@eclipse-che/workspace-client';
-import axios, { AxiosInstance } from 'axios';
-
-export const CHE_EDITOR_YAML_PATH = '.che/che-editor.yaml';
-
-/**
- * This class manages the common functions between the che workspace client and the devworkspace client
- */
-export abstract class WorkspaceClient {
- protected readonly axios: AxiosInstance;
-
- protected constructor() {
- // change this temporary solution after adding the proper method to workspace-client https://github.com/eclipse/che/issues/18311
- this.axios = (WorkspaceClientLib as any).createAxiosInstance({ loggingEnabled: false });
-
- // workspaceClientLib axios interceptor
- this.axios.interceptors.response.use(
- response => response,
- async error => {
- // any status codes that falls outside the range of 2xx
- return Promise.reject(error);
- },
- );
-
- // dashboard-backend axios interceptor
- axios.interceptors.response.use(
- response => response,
- async error => {
- // any status codes that falls outside the range of 2xx
- return Promise.reject(error);
- },
- );
- }
-}
diff --git a/packages/dashboard-frontend/src/store/BannerAlert/index.ts b/packages/dashboard-frontend/src/store/BannerAlert/index.ts
index 2bcac8a60..65c9961a2 100644
--- a/packages/dashboard-frontend/src/store/BannerAlert/index.ts
+++ b/packages/dashboard-frontend/src/store/BannerAlert/index.ts
@@ -71,13 +71,13 @@ export const reducer: Reducer = (
switch (action.type) {
case 'ADD_BANNER':
- return createObject(state, {
+ return createObject(state, {
messages: state.messages.includes(action.message)
? state.messages
: state.messages.concat([action.message]),
});
case 'REMOVE_BANNER':
- return createObject(state, {
+ return createObject(state, {
messages: state.messages.includes(action.message)
? state.messages.filter(message => message !== action.message)
: state.messages,
diff --git a/packages/dashboard-frontend/src/store/Branding/index.ts b/packages/dashboard-frontend/src/store/Branding/index.ts
index 5d0ae0201..4991d2b87 100644
--- a/packages/dashboard-frontend/src/store/Branding/index.ts
+++ b/packages/dashboard-frontend/src/store/Branding/index.ts
@@ -117,17 +117,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_BRANDING':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case 'RECEIVED_BRANDING':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
data: action.data,
});
case 'RECEIVED_BRANDING_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/ClusterConfig/index.ts b/packages/dashboard-frontend/src/store/ClusterConfig/index.ts
index e6e10ec31..616dc2dcb 100644
--- a/packages/dashboard-frontend/src/store/ClusterConfig/index.ts
+++ b/packages/dashboard-frontend/src/store/ClusterConfig/index.ts
@@ -15,7 +15,7 @@ import common, { ClusterConfig } from '@eclipse-che/common';
import { AppThunk } from '..';
import { createObject } from '../helpers';
import * as BannerAlertStore from '../BannerAlert';
-import { fetchClusterConfig } from '../../services/dashboard-backend-client/clusterConfigApi';
+import { fetchClusterConfig } from '../../services/backend-client/clusterConfigApi';
import { AddBannerAction } from '../BannerAlert';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
@@ -105,17 +105,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_CLUSTER_CONFIG:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_CLUSTER_CONFIG:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
clusterConfig: action.clusterConfig,
});
case Type.RECEIVE_CLUSTER_CONFIG_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/ClusterInfo/index.ts b/packages/dashboard-frontend/src/store/ClusterInfo/index.ts
index b1593808d..62d78ff2d 100644
--- a/packages/dashboard-frontend/src/store/ClusterInfo/index.ts
+++ b/packages/dashboard-frontend/src/store/ClusterInfo/index.ts
@@ -14,7 +14,7 @@ import { Action, Reducer } from 'redux';
import common, { ClusterInfo } from '@eclipse-che/common';
import { AppThunk } from '..';
import { createObject } from '../helpers';
-import { fetchClusterInfo } from '../../services/dashboard-backend-client/clusterInfoApi';
+import { fetchClusterInfo } from '../../services/backend-client/clusterInfoApi';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
export interface State {
@@ -97,17 +97,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_CLUSTER_INFO:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_CLUSTER_INFO:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
clusterInfo: action.clusterInfo,
});
case Type.RECEIVE_CLUSTER_INFO_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/DevfileRegistries/__tests__/index.spec.ts b/packages/dashboard-frontend/src/store/DevfileRegistries/__tests__/index.spec.ts
index 58fa8b3f8..ce2a9380c 100644
--- a/packages/dashboard-frontend/src/store/DevfileRegistries/__tests__/index.spec.ts
+++ b/packages/dashboard-frontend/src/store/DevfileRegistries/__tests__/index.spec.ts
@@ -58,6 +58,14 @@ describe('Devfile registries', () => {
const actions = store.getActions();
const expectedActions: devfileRegistriesStore.KnownAction[] = [
+ {
+ type: devfileRegistriesStore.Type.REQUEST_REGISTRY_METADATA,
+ check: AUTHORIZED,
+ },
+ {
+ type: devfileRegistriesStore.Type.REQUEST_REGISTRY_METADATA,
+ check: AUTHORIZED,
+ },
{
type: devfileRegistriesStore.Type.REQUEST_REGISTRY_METADATA,
check: AUTHORIZED,
@@ -116,6 +124,14 @@ describe('Devfile registries', () => {
const actions = store.getActions();
const expectedActions: devfileRegistriesStore.KnownAction[] = [
+ {
+ type: devfileRegistriesStore.Type.REQUEST_REGISTRY_METADATA,
+ check: AUTHORIZED,
+ },
+ {
+ type: devfileRegistriesStore.Type.REQUEST_REGISTRY_METADATA,
+ check: AUTHORIZED,
+ },
{
type: devfileRegistriesStore.Type.REQUEST_REGISTRY_METADATA,
check: AUTHORIZED,
diff --git a/packages/dashboard-frontend/src/store/DevfileRegistries/fetchAndUpdateDevfileSchema.ts b/packages/dashboard-frontend/src/store/DevfileRegistries/fetchAndUpdateDevfileSchema.ts
index 9f0c4ae6b..2c8c0e78b 100644
--- a/packages/dashboard-frontend/src/store/DevfileRegistries/fetchAndUpdateDevfileSchema.ts
+++ b/packages/dashboard-frontend/src/store/DevfileRegistries/fetchAndUpdateDevfileSchema.ts
@@ -11,7 +11,7 @@
*/
import { JSONSchema7 } from 'json-schema';
-import { getDevfileSchema } from '../../services/dashboard-backend-client/devWorkspaceApi';
+import { getDevfileSchema } from '../../services/backend-client/devWorkspaceApi';
export default async function fetchAndUpdateDevfileSchema(
schemaVersion: string,
diff --git a/packages/dashboard-frontend/src/store/DevfileRegistries/index.ts b/packages/dashboard-frontend/src/store/DevfileRegistries/index.ts
index f8980f7b4..dc6128eca 100644
--- a/packages/dashboard-frontend/src/store/DevfileRegistries/index.ts
+++ b/packages/dashboard-frontend/src/store/DevfileRegistries/index.ts
@@ -19,6 +19,7 @@ import fetchAndUpdateDevfileSchema from './fetchAndUpdateDevfileSchema';
import devfileApi from '../../services/devfileApi';
import { fetchResources, loadResourcesContent } from '../../services/registry/resources';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
export const DEFAULT_REGISTRY = '/dashboard/devfile-registry/';
@@ -170,12 +171,15 @@ export const actionCreators: ActionCreators = {
*/
requestRegistriesMetadata:
(registryUrls: string, isExternal: boolean): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_REGISTRY_METADATA, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
const registries: string[] = registryUrls.split(' ');
const promises = registries.map(async url => {
try {
+ await dispatch({ type: Type.REQUEST_REGISTRY_METADATA, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const metadata: che.DevfileMetaData[] = await fetchRegistryMetadata(url, isExternal);
if (!Array.isArray(metadata) || metadata.length === 0) {
return;
@@ -205,9 +209,13 @@ export const actionCreators: ActionCreators = {
requestDevfile:
(url: string): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_DEVFILE, check: AUTHORIZED });
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_DEVFILE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const devfile = await fetchDevfile(url);
dispatch({ type: Type.RECEIVE_DEVFILE, devfile, url });
return devfile;
@@ -218,10 +226,13 @@ export const actionCreators: ActionCreators = {
requestResources:
(resourcesUrl: string): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_RESOURCES, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_RESOURCES, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const resourcesContent = await fetchResources(resourcesUrl);
const resources = loadResourcesContent(resourcesContent);
@@ -259,9 +270,13 @@ export const actionCreators: ActionCreators = {
requestJsonSchema:
(): AppThunk =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_SCHEMA, check: AUTHORIZED });
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_SCHEMA, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const schemav200 = await fetchAndUpdateDevfileSchema('2.0.0');
const schemav210 = await fetchAndUpdateDevfileSchema('2.1.0');
const schemav220 = await fetchAndUpdateDevfileSchema('2.2.0');
@@ -319,24 +334,24 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_REGISTRY_METADATA:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
});
case Type.REQUEST_SCHEMA:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
schema: {},
});
case Type.REQUEST_DEVFILE:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
});
case Type.REQUEST_RESOURCES:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
});
case Type.RECEIVE_REGISTRY_METADATA:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
registries: createObject(state.registries, {
[action.url]: {
@@ -345,7 +360,7 @@ export const reducer: Reducer = (
}),
});
case Type.RECEIVE_REGISTRY_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
registries: {
[action.url]: {
@@ -354,7 +369,7 @@ export const reducer: Reducer = (
},
});
case Type.RECEIVE_DEVFILE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
devfiles: createObject(state.devfiles, {
[action.url]: {
@@ -363,7 +378,7 @@ export const reducer: Reducer = (
}),
});
case Type.RECEIVE_RESOURCES:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
devWorkspaceResources: createObject(state.devWorkspaceResources, {
[action.url]: {
@@ -372,7 +387,7 @@ export const reducer: Reducer = (
}),
});
case Type.RECEIVE_RESOURCES_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
devWorkspaceResources: {
[action.url]: {
@@ -381,26 +396,26 @@ export const reducer: Reducer = (
},
});
case Type.RECEIVE_SCHEMA:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
schema: {
schema: action.schema,
},
});
case Type.RECEIVE_SCHEMA_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
schema: {
error: action.error,
},
});
case Type.SET_FILTER: {
- return createObject(state, {
+ return createObject(state, {
filter: action.value,
});
}
case Type.CLEAR_FILTER: {
- return createObject(state, {
+ return createObject(state, {
filter: '',
});
}
diff --git a/packages/dashboard-frontend/src/store/DockerConfig/__tests__/index.spec.ts b/packages/dashboard-frontend/src/store/DockerConfig/__tests__/index.spec.ts
index cb00ccd91..0ead30ea3 100644
--- a/packages/dashboard-frontend/src/store/DockerConfig/__tests__/index.spec.ts
+++ b/packages/dashboard-frontend/src/store/DockerConfig/__tests__/index.spec.ts
@@ -18,6 +18,7 @@ import * as dwDockerConfigStore from '..';
import { AppState } from '../..';
import { AnyAction } from 'redux';
import { AUTHORIZED } from '../../sanityCheckMiddleware';
+import { Type } from '..';
// mute the outputs
console.error = jest.fn();
@@ -48,11 +49,11 @@ describe('dwDockerConfig store', () => {
const expectedActions: dwDockerConfigStore.KnownAction[] = [
{
- type: 'REQUEST_DEVWORKSPACE_CREDENTIALS',
+ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS,
check: AUTHORIZED,
},
{
- type: 'SET_DEVWORKSPACE_CREDENTIALS',
+ type: Type.SET_DEVWORKSPACE_CREDENTIALS,
registries: [
{
password: 'XXXXXXXXXXXXXXX',
@@ -93,11 +94,11 @@ describe('dwDockerConfig store', () => {
const expectedActions: dwDockerConfigStore.KnownAction[] = [
{
- type: 'REQUEST_DEVWORKSPACE_CREDENTIALS',
+ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS,
check: AUTHORIZED,
},
{
- type: 'SET_DEVWORKSPACE_CREDENTIALS',
+ type: Type.SET_DEVWORKSPACE_CREDENTIALS,
registries: [
{
password: 'YYYYYYYYYYYY',
@@ -115,7 +116,7 @@ describe('dwDockerConfig store', () => {
describe('reducers', () => {
it('should return initial state', () => {
const incomingAction: dwDockerConfigStore.RequestCredentialsAction = {
- type: 'REQUEST_DEVWORKSPACE_CREDENTIALS',
+ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS,
check: AUTHORIZED,
};
const initialState = dwDockerConfigStore.reducer(undefined, incomingAction);
@@ -180,7 +181,7 @@ describe('dwDockerConfig store', () => {
error: undefined,
};
const incomingAction: dwDockerConfigStore.RequestCredentialsAction = {
- type: 'REQUEST_DEVWORKSPACE_CREDENTIALS',
+ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS,
check: AUTHORIZED,
};
@@ -216,7 +217,7 @@ describe('dwDockerConfig store', () => {
error: undefined,
};
const incomingAction: dwDockerConfigStore.SetCredentialsAction = {
- type: 'SET_DEVWORKSPACE_CREDENTIALS',
+ type: Type.SET_DEVWORKSPACE_CREDENTIALS,
registries: [],
resourceVersion: '345',
};
@@ -241,7 +242,7 @@ describe('dwDockerConfig store', () => {
error: undefined,
};
const incomingAction: dwDockerConfigStore.ReceiveErrorAction = {
- type: 'RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR',
+ type: Type.RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR,
error: 'unexpected error',
};
diff --git a/packages/dashboard-frontend/src/store/DockerConfig/dockerConfigState.ts b/packages/dashboard-frontend/src/store/DockerConfig/dockerConfigState.ts
deleted file mode 100644
index 4e9229efe..000000000
--- a/packages/dashboard-frontend/src/store/DockerConfig/dockerConfigState.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2018-2023 Red Hat, Inc.
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Red Hat, Inc. - initial API and implementation
- */
-
-import { RegistryEntry } from './types';
-
-export interface State {
- isLoading: boolean;
- registries: RegistryEntry[];
- resourceVersion?: string;
- error: string | undefined;
-}
diff --git a/packages/dashboard-frontend/src/store/DockerConfig/index.ts b/packages/dashboard-frontend/src/store/DockerConfig/index.ts
index 453e04556..c1f4ff8ec 100644
--- a/packages/dashboard-frontend/src/store/DockerConfig/index.ts
+++ b/packages/dashboard-frontend/src/store/DockerConfig/index.ts
@@ -14,25 +14,37 @@ import { Action, Reducer } from 'redux';
import { api, helpers } from '@eclipse-che/common';
import { AppThunk } from '..';
import { createObject } from '../helpers';
-import * as DwApi from '../../services/dashboard-backend-client/devWorkspaceApi';
+import * as DwApi from '../../services/backend-client/devWorkspaceApi';
import { RegistryEntry } from './types';
-import { State } from './dockerConfigState';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
import { selectDefaultNamespace } from '../InfrastructureNamespaces/selectors';
-export * from './dockerConfigState';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
+
+export interface State {
+ isLoading: boolean;
+ registries: RegistryEntry[];
+ resourceVersion?: string;
+ error: string | undefined;
+}
+
+export enum Type {
+ REQUEST_DEVWORKSPACE_CREDENTIALS = 'REQUEST_DEVWORKSPACE_CREDENTIALS',
+ SET_DEVWORKSPACE_CREDENTIALS = 'SET_DEVWORKSPACE_CREDENTIALS',
+ RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR = 'RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR',
+}
export interface RequestCredentialsAction extends Action, SanityCheckAction {
- type: 'REQUEST_DEVWORKSPACE_CREDENTIALS';
+ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS;
}
export interface SetCredentialsAction extends Action {
- type: 'SET_DEVWORKSPACE_CREDENTIALS';
+ type: Type.SET_DEVWORKSPACE_CREDENTIALS;
registries: RegistryEntry[];
resourceVersion: string | undefined;
}
export interface ReceiveErrorAction extends Action {
- type: 'RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR';
+ type: Type.RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR;
error: string;
}
@@ -47,20 +59,23 @@ export const actionCreators: ActionCreators = {
requestCredentials:
(): AppThunk> =>
async (dispatch, getState): Promise => {
- const state = getState();
- const namespace = selectDefaultNamespace(state).name;
- await dispatch({ type: 'REQUEST_DEVWORKSPACE_CREDENTIALS', check: AUTHORIZED });
+ const namespace = selectDefaultNamespace(getState()).name;
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const { registries, resourceVersion } = await getDockerConfig(namespace);
dispatch({
- type: 'SET_DEVWORKSPACE_CREDENTIALS',
+ type: Type.SET_DEVWORKSPACE_CREDENTIALS,
registries,
resourceVersion,
});
} catch (e) {
const errorMessage = helpers.errors.getMessage(e);
dispatch({
- type: 'RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR',
+ type: Type.RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR,
error: errorMessage,
});
throw e;
@@ -70,24 +85,28 @@ export const actionCreators: ActionCreators = {
updateCredentials:
(registries: RegistryEntry[]): AppThunk> =>
async (dispatch, getState): Promise => {
- await dispatch({ type: 'REQUEST_DEVWORKSPACE_CREDENTIALS', check: AUTHORIZED });
const state = getState();
const namespace = selectDefaultNamespace(state).name;
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE_CREDENTIALS, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const { resourceVersion } = await putDockerConfig(
namespace,
registries,
state.dockerConfig?.resourceVersion,
);
dispatch({
- type: 'SET_DEVWORKSPACE_CREDENTIALS',
+ type: Type.SET_DEVWORKSPACE_CREDENTIALS,
registries,
resourceVersion,
});
} catch (e) {
const errorMessage = helpers.errors.getMessage(e);
dispatch({
- type: 'RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR',
+ type: Type.RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR,
error: errorMessage,
});
throw e;
@@ -165,19 +184,19 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
- case 'REQUEST_DEVWORKSPACE_CREDENTIALS':
- return createObject(state, {
+ case Type.REQUEST_DEVWORKSPACE_CREDENTIALS:
+ return createObject(state, {
isLoading: true,
error: undefined,
});
- case 'SET_DEVWORKSPACE_CREDENTIALS':
- return createObject(state, {
+ case Type.SET_DEVWORKSPACE_CREDENTIALS:
+ return createObject(state, {
isLoading: false,
registries: action.registries,
resourceVersion: action.resourceVersion,
});
- case 'RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR':
- return createObject(state, {
+ case Type.RECEIVE_DEVWORKSPACE_CREDENTIALS_ERROR:
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/DockerConfig/selectors.ts b/packages/dashboard-frontend/src/store/DockerConfig/selectors.ts
index 2464bf009..824d8103a 100644
--- a/packages/dashboard-frontend/src/store/DockerConfig/selectors.ts
+++ b/packages/dashboard-frontend/src/store/DockerConfig/selectors.ts
@@ -12,7 +12,7 @@
import { createSelector } from 'reselect';
import { AppState } from '..';
-import { State } from './dockerConfigState';
+import { State } from './index';
const selectState = (state: AppState) => state.dockerConfig;
diff --git a/packages/dashboard-frontend/src/store/Events/__tests__/actions.spec.ts b/packages/dashboard-frontend/src/store/Events/__tests__/actions.spec.ts
index 6679b20ab..01b8e3684 100644
--- a/packages/dashboard-frontend/src/store/Events/__tests__/actions.spec.ts
+++ b/packages/dashboard-frontend/src/store/Events/__tests__/actions.spec.ts
@@ -18,7 +18,7 @@ import { ThunkDispatch } from 'redux-thunk';
import * as testStore from '..';
import { AppState } from '../..';
import { container } from '../../../inversify.config';
-import { WebsocketClient } from '../../../services/dashboard-backend-client/websocketClient';
+import { WebsocketClient } from '../../../services/backend-client/websocketClient';
import { AUTHORIZED } from '../../sanityCheckMiddleware';
import { FakeStoreBuilder } from '../../__mocks__/storeBuilder';
import { event1, event2 } from './stubs';
diff --git a/packages/dashboard-frontend/src/store/Events/index.ts b/packages/dashboard-frontend/src/store/Events/index.ts
index cb0a5b8c5..a1d6c1297 100644
--- a/packages/dashboard-frontend/src/store/Events/index.ts
+++ b/packages/dashboard-frontend/src/store/Events/index.ts
@@ -15,8 +15,8 @@ import { CoreV1Event } from '@kubernetes/client-node';
import { Action, Reducer } from 'redux';
import { AppThunk } from '..';
import { container } from '../../inversify.config';
-import { fetchEvents } from '../../services/dashboard-backend-client/eventsApi';
-import { WebsocketClient } from '../../services/dashboard-backend-client/websocketClient';
+import { fetchEvents } from '../../services/backend-client/eventsApi';
+import { WebsocketClient } from '../../services/backend-client/websocketClient';
import { getNewerResourceVersion } from '../../services/helpers/resourceVersion';
import { createObject } from '../helpers';
import { selectDefaultNamespace } from '../InfrastructureNamespaces/selectors';
@@ -188,18 +188,18 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_EVENTS:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_EVENTS:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
events: state.events.concat(action.events),
resourceVersion: getNewerResourceVersion(action.resourceVersion, state.resourceVersion),
});
case Type.MODIFY_EVENT:
- return createObject(state, {
+ return createObject(state, {
events: state.events.map(event => {
if (event.metadata.uid === action.event.metadata.uid) {
return action.event;
@@ -212,7 +212,7 @@ export const reducer: Reducer = (
),
});
case Type.DELETE_EVENT:
- return createObject(state, {
+ return createObject(state, {
events: state.events.filter(event => event.metadata.uid !== action.event.metadata.uid),
resourceVersion: getNewerResourceVersion(
action.event.metadata.resourceVersion,
@@ -220,7 +220,7 @@ export const reducer: Reducer = (
),
});
case Type.RECEIVE_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/FactoryResolver/__tests__/index.spec.ts b/packages/dashboard-frontend/src/store/FactoryResolver/__tests__/index.spec.ts
index 3e60c7fc4..c2a3126a0 100644
--- a/packages/dashboard-frontend/src/store/FactoryResolver/__tests__/index.spec.ts
+++ b/packages/dashboard-frontend/src/store/FactoryResolver/__tests__/index.spec.ts
@@ -16,7 +16,7 @@ import common from '@eclipse-che/common';
import { AppState } from '../..';
import { FakeStoreBuilder } from '../../__mocks__/storeBuilder';
import devfileApi from '../../../services/devfileApi';
-import * as factoryResolver from '../../../services/dashboard-backend-client/factoryResolverApi';
+import * as factoryResolver from '../../../services/backend-client/factoryApi';
import * as factoryResolverStore from '..';
import { AxiosError } from 'axios';
import normalizeDevfileV1 from '../normalizeDevfileV1';
@@ -26,7 +26,7 @@ import {
convertDevfileV1toDevfileV2,
} from '../../../services/devfile/converters';
import { AUTHORIZED } from '../../sanityCheckMiddleware';
-import * as yamlResolver from '../../../services/dashboard-backend-client/yamlResolverApi';
+import * as yamlResolver from '../../../services/backend-client/yamlResolverApi';
jest.mock('../normalizeDevfileV1.ts');
(normalizeDevfileV1 as jest.Mock).mockImplementation(devfile => {
diff --git a/packages/dashboard-frontend/src/store/FactoryResolver/index.ts b/packages/dashboard-frontend/src/store/FactoryResolver/index.ts
index f390dab1e..aa52b9eeb 100644
--- a/packages/dashboard-frontend/src/store/FactoryResolver/index.ts
+++ b/packages/dashboard-frontend/src/store/FactoryResolver/index.ts
@@ -22,13 +22,15 @@ import { convertDevfileV1toDevfileV2 } from '../../services/devfile/converters';
import normalizeDevfileV2 from './normalizeDevfileV2';
import normalizeDevfileV1 from './normalizeDevfileV1';
import { selectDefaultNamespace } from '../InfrastructureNamespaces/selectors';
-import { getYamlResolver } from '../../services/dashboard-backend-client/yamlResolverApi';
+import { getYamlResolver } from '../../services/backend-client/yamlResolverApi';
import { DEFAULT_REGISTRY } from '../DevfileRegistries';
import { isOAuthResponse } from '../../services/oauth';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
-import { CHE_EDITOR_YAML_PATH } from '../../services/workspace-client';
+import { CHE_EDITOR_YAML_PATH } from '../../services/workspace-client/helpers';
import { FactoryParams } from '../../services/helpers/factoryFlow/buildFactoryParams';
-import { getFactoryResolver } from '../../services/dashboard-backend-client/factoryResolverApi';
+import { getFactoryResolver } from '../../services/backend-client/factoryApi';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
+import * as cheApi from '@eclipse-che/api';
export type OAuthResponse = {
attributes: {
@@ -87,7 +89,7 @@ export type ActionCreators = {
};
export async function grabLink(
- links: api.che.core.rest.Link,
+ links: cheApi.che.core.rest.Link[],
filename: string,
): Promise {
// handle servers not yet providing links
@@ -95,8 +97,8 @@ export async function grabLink(
return undefined;
}
// grab the one matching
- const foundLink = links.find(link => link.href.includes(`file=${filename}`));
- if (!foundLink) {
+ const foundLink = links.find(link => link.href?.includes(`file=${filename}`));
+ if (!foundLink || !foundLink.href) {
return undefined;
}
@@ -129,7 +131,6 @@ export const actionCreators: ActionCreators = {
factoryParams: Partial = {},
): AppThunk> =>
async (dispatch, getState): Promise => {
- await dispatch({ type: 'REQUEST_FACTORY_RESOLVER', check: AUTHORIZED });
const state = getState();
const namespace = selectDefaultNamespace(state).name;
const optionalFilesContent = {};
@@ -157,6 +158,11 @@ export const actionCreators: ActionCreators = {
};
try {
+ await dispatch({ type: 'REQUEST_FACTORY_RESOLVER', check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
let data: FactoryResolver;
if (isDevfileRegistryLocation(location)) {
data = await getYamlResolver(namespace, location);
@@ -245,18 +251,18 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_FACTORY_RESOLVER':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case 'RECEIVE_FACTORY_RESOLVER':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
resolver: action.resolver,
converted: action.converted,
});
case 'RECEIVE_FACTORY_RESOLVER_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/GitConfig/__tests__/index.spec.ts b/packages/dashboard-frontend/src/store/GitConfig/__tests__/index.spec.ts
index a7c5020dd..3c3355181 100644
--- a/packages/dashboard-frontend/src/store/GitConfig/__tests__/index.spec.ts
+++ b/packages/dashboard-frontend/src/store/GitConfig/__tests__/index.spec.ts
@@ -20,7 +20,7 @@ import { AUTHORIZED } from '../../sanityCheckMiddleware';
const mockFetchGitConfig = jest.fn().mockResolvedValue({ gitconfig: {} } as api.IGitConfig);
const mockPatchGitConfig = jest.fn().mockResolvedValue({ gitconfig: {} } as api.IGitConfig);
-jest.mock('../../../services/dashboard-backend-client/gitConfigApi', () => {
+jest.mock('../../../services/backend-client/gitConfigApi', () => {
return {
fetchGitConfig: (...args: unknown[]) => mockFetchGitConfig(...args),
patchGitConfig: (...args: unknown[]) => mockPatchGitConfig(...args),
diff --git a/packages/dashboard-frontend/src/store/GitConfig/index.ts b/packages/dashboard-frontend/src/store/GitConfig/index.ts
index 77576d279..479a469e6 100644
--- a/packages/dashboard-frontend/src/store/GitConfig/index.ts
+++ b/packages/dashboard-frontend/src/store/GitConfig/index.ts
@@ -12,13 +12,11 @@
import common, { api, helpers } from '@eclipse-che/common';
import { AppThunk } from '..';
-import {
- fetchGitConfig,
- patchGitConfig,
-} from '../../services/dashboard-backend-client/gitConfigApi';
+import { fetchGitConfig, patchGitConfig } from '../../services/backend-client/gitConfigApi';
import { selectDefaultNamespace } from '../InfrastructureNamespaces/selectors';
import { AUTHORIZED } from '../sanityCheckMiddleware';
import { GitConfigUser, KnownAction, Type } from './types';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
export * from './reducer';
export * from './types';
@@ -31,11 +29,14 @@ export const actionCreators: ActionCreators = {
requestGitConfig:
(): AppThunk> =>
async (dispatch, getState): Promise => {
- await dispatch({ type: Type.REQUEST_GITCONFIG, check: AUTHORIZED });
-
const state = getState();
const namespace = selectDefaultNamespace(state).name;
try {
+ await dispatch({ type: Type.REQUEST_GITCONFIG, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const config = await fetchGitConfig(namespace);
dispatch({
type: Type.RECEIVE_GITCONFIG,
@@ -62,16 +63,20 @@ export const actionCreators: ActionCreators = {
updateGitConfig:
(changedGitConfig: GitConfigUser): AppThunk> =>
async (dispatch, getState): Promise => {
- await dispatch({ type: Type.REQUEST_GITCONFIG, check: AUTHORIZED });
-
- const namespace = selectDefaultNamespace(getState()).name;
- const { gitConfig } = getState();
+ const state = getState();
+ const namespace = selectDefaultNamespace(state).name;
+ const { gitConfig } = state;
const gitconfig = Object.assign(gitConfig.config || {}, {
gitconfig: {
user: changedGitConfig,
},
} as api.IGitConfig);
try {
+ await dispatch({ type: Type.REQUEST_GITCONFIG, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const updated = await patchGitConfig(namespace, gitconfig);
dispatch({
type: Type.RECEIVE_GITCONFIG,
diff --git a/packages/dashboard-frontend/src/store/GitOauthConfig/index.ts b/packages/dashboard-frontend/src/store/GitOauthConfig/index.ts
index 500add196..a7d94dc49 100644
--- a/packages/dashboard-frontend/src/store/GitOauthConfig/index.ts
+++ b/packages/dashboard-frontend/src/store/GitOauthConfig/index.ts
@@ -15,9 +15,13 @@ import common, { api } from '@eclipse-che/common';
import { AppThunk } from '..';
import { createObject } from '../helpers';
import { AUTHORIZED } from '../sanityCheckMiddleware';
-import { container } from '../../inversify.config';
-import { CheWorkspaceClient } from '../../services/workspace-client/cheworkspace/cheWorkspaceClient';
import { IGitOauth } from './types';
+import {
+ deleteOAuthToken,
+ getOAuthProviders,
+ getOAuthToken,
+} from '../../services/backend-client/oAuthApi';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
export interface State {
isLoading: boolean;
@@ -25,8 +29,6 @@ export interface State {
error: string | undefined;
}
-const cheWorkspaceClient = container.get(CheWorkspaceClient);
-
export enum Type {
REQUEST_GIT_OAUTH_CONFIG = 'REQUEST_GIT_OAUTH_CONFIG',
DELETE_OAUTH = 'DELETE_OAUTH',
@@ -67,21 +69,31 @@ export type ActionCreators = {
export const actionCreators: ActionCreators = {
requestGitOauthConfig:
(): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({
+ async (dispatch, getState): Promise => {
+ dispatch({
type: Type.REQUEST_GIT_OAUTH_CONFIG,
check: AUTHORIZED,
});
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ dispatch({
+ type: Type.RECEIVE_GIT_OAUTH_CONFIG_ERROR,
+ error,
+ });
+ throw new Error(error);
+ }
+
const gitOauth: IGitOauth[] = [];
try {
- const oAuthProviders = await cheWorkspaceClient.restApiClient.getOAuthProviders();
+ const oAuthProviders = await getOAuthProviders();
const promises: Promise[] = [];
- for (const { name, endpointUrl } of oAuthProviders) {
+ for (const { name, endpointUrl, links } of oAuthProviders) {
promises.push(
- cheWorkspaceClient.restApiClient.getOAuthToken(name).then(() => {
+ getOAuthToken(name).then(() => {
gitOauth.push({
name: name as api.GitOauthProvider,
endpointUrl,
+ links,
});
}),
);
@@ -104,13 +116,22 @@ export const actionCreators: ActionCreators = {
revokeOauth:
(oauthProvider: api.GitOauthProvider): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({
+ async (dispatch, getState): Promise => {
+ dispatch({
type: Type.REQUEST_GIT_OAUTH_CONFIG,
check: AUTHORIZED,
});
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ dispatch({
+ type: Type.RECEIVE_GIT_OAUTH_CONFIG_ERROR,
+ error,
+ });
+ throw new Error(error);
+ }
+
try {
- await cheWorkspaceClient.restApiClient.deleteOAuthToken(oauthProvider);
+ await deleteOAuthToken(oauthProvider);
dispatch({
type: Type.DELETE_OAUTH,
provider: oauthProvider,
@@ -143,22 +164,22 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_GIT_OAUTH_CONFIG:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_GIT_OAUTH_CONFIG:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
gitOauth: action.gitOauth,
});
case Type.DELETE_OAUTH:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
gitOauth: state.gitOauth.filter(v => v.name !== action.provider),
});
case Type.RECEIVE_GIT_OAUTH_CONFIG_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/GitOauthConfig/types.ts b/packages/dashboard-frontend/src/store/GitOauthConfig/types.ts
index ef436a426..c470f1961 100644
--- a/packages/dashboard-frontend/src/store/GitOauthConfig/types.ts
+++ b/packages/dashboard-frontend/src/store/GitOauthConfig/types.ts
@@ -10,9 +10,11 @@
* Red Hat, Inc. - initial API and implementation
*/
-import { api } from '@eclipse-che/common';
+import { api as commonApi } from '@eclipse-che/common';
+import * as cheApi from '@eclipse-che/api';
export interface IGitOauth {
- name: api.GitOauthProvider;
+ name: commonApi.GitOauthProvider;
endpointUrl: string;
+ links?: cheApi.che.core.rest.Link[];
}
diff --git a/packages/dashboard-frontend/src/store/InfrastructureNamespaces/index.ts b/packages/dashboard-frontend/src/store/InfrastructureNamespaces/index.ts
index 9aadd8431..94a6a2e5c 100644
--- a/packages/dashboard-frontend/src/store/InfrastructureNamespaces/index.ts
+++ b/packages/dashboard-frontend/src/store/InfrastructureNamespaces/index.ts
@@ -12,13 +12,11 @@
import { Action, Reducer } from 'redux';
import common from '@eclipse-che/common';
-import { container } from '../../inversify.config';
-import { CheWorkspaceClient } from '../../services/workspace-client/cheworkspace/cheWorkspaceClient';
import { AppThunk } from '..';
import { createObject } from '../helpers';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
-
-const WorkspaceClient = container.get(CheWorkspaceClient);
+import { getKubernetesNamespace } from '../../services/backend-client/kubernetesNamespaceApi';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
export interface State {
isLoading: boolean;
@@ -49,14 +47,14 @@ export type ActionCreators = {
export const actionCreators: ActionCreators = {
requestNamespaces:
(): AppThunk>> =>
- async (dispatch): Promise> => {
- await dispatch({ type: 'REQUEST_NAMESPACES', check: AUTHORIZED });
-
+ async (dispatch, getState): Promise> => {
try {
- const namespaces =
- await WorkspaceClient.restApiClient.getKubernetesNamespace<
- Array
- >();
+ await dispatch({ type: 'REQUEST_NAMESPACES', check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
+ const namespaces = await getKubernetesNamespace();
dispatch({
type: 'RECEIVE_NAMESPACES',
namespaces,
@@ -91,17 +89,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_NAMESPACES':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case 'RECEIVE_NAMESPACES':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
namespaces: action.namespaces,
});
case 'RECEIVE_NAMESPACES_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/PersonalAccessToken/__tests__/actions.spec.ts b/packages/dashboard-frontend/src/store/PersonalAccessToken/__tests__/actions.spec.ts
index 80a300b39..ddbdada66 100644
--- a/packages/dashboard-frontend/src/store/PersonalAccessToken/__tests__/actions.spec.ts
+++ b/packages/dashboard-frontend/src/store/PersonalAccessToken/__tests__/actions.spec.ts
@@ -17,21 +17,23 @@ import { AppState } from '../..';
import { AUTHORIZED } from '../../sanityCheckMiddleware';
import { FakeStoreBuilder } from '../../__mocks__/storeBuilder';
import { token1, token2 } from './stub';
-import * as PersonalAccessTokenApi from '../../../services/dashboard-backend-client/personalAccessTokenApi';
-import { container } from '../../../inversify.config';
-import { CheWorkspaceClient } from '../../../services/workspace-client/cheworkspace/cheWorkspaceClient';
+import * as PersonalAccessTokenApi from '../../../services/backend-client/personalAccessTokenApi';
+import * as KubernetesNamespaceApi from '../../../services/backend-client/kubernetesNamespaceApi';
-const cheWorkspaceClient = container.get(CheWorkspaceClient);
-jest
- .spyOn(cheWorkspaceClient.restApiClient, 'provisionKubernetesNamespace')
- .mockImplementation(() => Promise.resolve({} as che.KubernetesNamespace));
+jest.mock(
+ '../../../services/backend-client/kubernetesNamespaceApi',
+ () =>
+ ({
+ provisionKubernetesNamespace: () => Promise.resolve({} as che.KubernetesNamespace),
+ }) as typeof KubernetesNamespaceApi,
+);
const mockFetchTokens = jest.fn();
const mockAddToken = jest.fn();
const mockUpdateToken = jest.fn();
const mockRemoveToken = jest.fn();
jest.mock(
- '../../../services/dashboard-backend-client/personalAccessTokenApi',
+ '../../../services/backend-client/personalAccessTokenApi',
() =>
({
fetchTokens: (...args) => mockFetchTokens(...args),
diff --git a/packages/dashboard-frontend/src/store/PersonalAccessToken/index.ts b/packages/dashboard-frontend/src/store/PersonalAccessToken/index.ts
index 52773b06d..81519fd11 100644
--- a/packages/dashboard-frontend/src/store/PersonalAccessToken/index.ts
+++ b/packages/dashboard-frontend/src/store/PersonalAccessToken/index.ts
@@ -13,23 +13,21 @@
import { api, helpers } from '@eclipse-che/common';
import { Action, Reducer } from 'redux';
import { AppThunk } from '..';
-import { container } from '../../inversify.config';
import {
addToken,
fetchTokens,
removeToken,
updateToken,
-} from '../../services/dashboard-backend-client/personalAccessTokenApi';
-import { CheWorkspaceClient } from '../../services/workspace-client/cheworkspace/cheWorkspaceClient';
+} from '../../services/backend-client/personalAccessTokenApi';
import { createObject } from '../helpers';
import { selectDefaultNamespace } from '../InfrastructureNamespaces/selectors';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
import { State } from './state';
+import { provisionKubernetesNamespace } from '../../services/backend-client/kubernetesNamespaceApi';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../SanityCheck/selectors';
export * from './state';
-const WorkspaceClient = container.get(CheWorkspaceClient);
-
export enum Type {
RECEIVE_ERROR = 'RECEIVE_ERROR',
RECEIVE_TOKENS = 'RECEIVE_TOKENS',
@@ -87,14 +85,21 @@ export const actionCreators: ActionCreators = {
requestTokens:
(): AppThunk> =>
async (dispatch, getState): Promise => {
- const state = getState();
- const namespace = selectDefaultNamespace(state).name;
-
- await dispatch({
+ dispatch({
type: Type.REQUEST_TOKENS,
check: AUTHORIZED,
});
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ dispatch({
+ type: Type.RECEIVE_ERROR,
+ error,
+ });
+ throw new Error(error);
+ }
+ const state = getState();
+ const namespace = selectDefaultNamespace(state).name;
try {
const tokens = await fetchTokens(namespace);
dispatch({
@@ -114,14 +119,21 @@ export const actionCreators: ActionCreators = {
addToken:
(token: api.PersonalAccessToken): AppThunk> =>
async (dispatch, getState): Promise => {
- const state = getState();
- const namespace = selectDefaultNamespace(state).name;
-
- await dispatch({
+ dispatch({
type: Type.REQUEST_TOKENS,
check: AUTHORIZED,
});
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ dispatch({
+ type: Type.RECEIVE_ERROR,
+ error,
+ });
+ throw new Error(error);
+ }
+ const state = getState();
+ const namespace = selectDefaultNamespace(state).name;
let newToken: api.PersonalAccessToken;
try {
newToken = await addToken(namespace, token);
@@ -135,8 +147,7 @@ export const actionCreators: ActionCreators = {
}
/* request namespace provision as it triggers tokens validation */
-
- await WorkspaceClient.restApiClient.provisionKubernetesNamespace();
+ await provisionKubernetesNamespace();
/* check if the new token is available */
@@ -161,14 +172,21 @@ export const actionCreators: ActionCreators = {
updateToken:
(token: api.PersonalAccessToken): AppThunk> =>
async (dispatch, getState): Promise => {
- const state = getState();
- const namespace = selectDefaultNamespace(state).name;
-
- await dispatch({
+ dispatch({
type: Type.REQUEST_TOKENS,
check: AUTHORIZED,
});
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ dispatch({
+ type: Type.RECEIVE_ERROR,
+ error,
+ });
+ throw new Error(error);
+ }
+ const state = getState();
+ const namespace = selectDefaultNamespace(state).name;
try {
const newToken = await updateToken(namespace, token);
dispatch({
@@ -188,14 +206,21 @@ export const actionCreators: ActionCreators = {
removeToken:
(token: api.PersonalAccessToken): AppThunk> =>
async (dispatch, getState): Promise => {
- const state = getState();
- const namespace = selectDefaultNamespace(state).name;
-
- await dispatch({
+ dispatch({
type: Type.REQUEST_TOKENS,
check: AUTHORIZED,
});
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ dispatch({
+ type: Type.RECEIVE_ERROR,
+ error,
+ });
+ throw new Error(error);
+ }
+ const state = getState();
+ const namespace = selectDefaultNamespace(state).name;
try {
await removeToken(namespace, token);
dispatch({
@@ -229,34 +254,34 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_TOKENS:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_TOKENS:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
tokens: action.tokens,
});
case Type.ADD_TOKEN:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
tokens: [...state.tokens, action.token],
});
case Type.UPDATE_TOKEN:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
tokens: state.tokens.map(token =>
token.tokenName === action.token.tokenName ? action.token : token,
),
});
case Type.REMOVE_TOKEN:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
tokens: state.tokens.filter(token => token.tokenName !== action.token.tokenName),
});
case Type.RECEIVE_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/Plugins/chePlugins/index.ts b/packages/dashboard-frontend/src/store/Plugins/chePlugins/index.ts
index 05148122f..4b9a0783b 100644
--- a/packages/dashboard-frontend/src/store/Plugins/chePlugins/index.ts
+++ b/packages/dashboard-frontend/src/store/Plugins/chePlugins/index.ts
@@ -16,6 +16,7 @@ import common from '@eclipse-che/common';
import { AppThunk } from '../..';
import { createObject } from '../../helpers';
import { AUTHORIZED, SanityCheckAction } from '../../sanityCheckMiddleware';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../../SanityCheck/selectors';
// create new instance of `axios` to avoid adding an authorization header
const axiosInstance = axios.create();
@@ -49,10 +50,13 @@ export type ActionCreators = {
export const actionCreators: ActionCreators = {
requestPlugins:
(registryUrl: string): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: 'REQUEST_PLUGINS', check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: 'REQUEST_PLUGINS', check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const response = await axiosInstance.request({
method: 'GET',
url: `${registryUrl}/plugins/`,
@@ -93,17 +97,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_PLUGINS':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case 'RECEIVE_PLUGINS':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
plugins: action.plugins,
});
case 'RECEIVE_PLUGINS_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/index.ts b/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/index.ts
index 6b65d1915..59db6b12d 100644
--- a/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/index.ts
+++ b/packages/dashboard-frontend/src/store/Plugins/devWorkspacePlugins/index.ts
@@ -127,7 +127,7 @@ export const actionCreators: ActionCreators = {
requestDwDevfile:
(url: string): AppThunk> =>
async (dispatch): Promise => {
- await dispatch({
+ dispatch({
type: 'REQUEST_DW_PLUGIN',
check: AUTHORIZED,
url,
@@ -177,7 +177,7 @@ export const actionCreators: ActionCreators = {
}
try {
- await dispatch({
+ dispatch({
type: 'REQUEST_DW_EDITOR',
check: AUTHORIZED,
url: editorUrl,
@@ -208,7 +208,7 @@ export const actionCreators: ActionCreators = {
async (dispatch, getState): Promise => {
const config = getState().dwServerConfig.config;
const defaultEditor = config.defaults.editor;
- await dispatch({
+ dispatch({
type: 'REQUEST_DW_DEFAULT_EDITOR',
check: AUTHORIZED,
});
@@ -223,7 +223,7 @@ export const actionCreators: ActionCreators = {
throw errorMessage;
}
- const defaultEditorUrl = defaultEditor.startsWith('https://')
+ const defaultEditorUrl = (defaultEditor as string).startsWith('https://')
? defaultEditor
: `${config.pluginRegistryURL}/plugins/${defaultEditor}/devfile.yaml`;
@@ -240,7 +240,7 @@ export const actionCreators: ActionCreators = {
requestDwDefaultPlugins:
(): AppThunk> =>
async (dispatch, getState): Promise => {
- await dispatch({
+ dispatch({
type: 'REQUEST_DW_DEFAULT_PLUGINS',
check: AUTHORIZED,
});
@@ -280,7 +280,7 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_DW_PLUGIN':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
plugins: {
[action.url]: {
@@ -291,7 +291,7 @@ export const reducer: Reducer = (
},
});
case 'REQUEST_DW_EDITOR':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
editors: createObject(state.editors, {
[action.editorName]: {
@@ -301,13 +301,13 @@ export const reducer: Reducer = (
}),
});
case 'REQUEST_DW_DEFAULT_EDITOR':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
defaultEditorName: undefined,
defaultEditorError: undefined,
});
case 'RECEIVE_DW_PLUGIN':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
plugins: {
[action.url]: {
@@ -317,7 +317,7 @@ export const reducer: Reducer = (
},
});
case 'RECEIVE_DW_EDITOR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
editors: createObject(state.editors, {
[action.editorName]: {
@@ -327,7 +327,7 @@ export const reducer: Reducer = (
}),
});
case 'RECEIVE_DW_EDITOR_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
editors: {
[action.editorName]: {
@@ -338,7 +338,7 @@ export const reducer: Reducer = (
});
case 'RECEIVE_DW_PLUGIN_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
plugins: {
[action.url]: {
@@ -350,21 +350,21 @@ export const reducer: Reducer = (
},
});
case 'RECEIVE_DW_DEFAULT_EDITOR_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
defaultEditorError: action.error,
});
case 'RECEIVE_DW_DEFAULT_EDITOR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
defaultEditorName: action.defaultEditorName,
});
case 'REQUEST_DW_DEFAULT_PLUGINS':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
});
case 'RECEIVE_DW_DEFAULT_PLUGINS':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
defaultPlugins: action.defaultPlugins,
});
diff --git a/packages/dashboard-frontend/src/store/Pods/Logs/__tests__/actions.spec.ts b/packages/dashboard-frontend/src/store/Pods/Logs/__tests__/actions.spec.ts
index 17ca36e37..6ea27c969 100644
--- a/packages/dashboard-frontend/src/store/Pods/Logs/__tests__/actions.spec.ts
+++ b/packages/dashboard-frontend/src/store/Pods/Logs/__tests__/actions.spec.ts
@@ -19,7 +19,7 @@ import { ThunkDispatch } from 'redux-thunk';
import * as testStore from '..';
import { AppState } from '../../..';
import { container } from '../../../../inversify.config';
-import { WebsocketClient } from '../../../../services/dashboard-backend-client/websocketClient';
+import { WebsocketClient } from '../../../../services/backend-client/websocketClient';
import { FakeStoreBuilder } from '../../../__mocks__/storeBuilder';
describe('Pod logs store, actions', () => {
diff --git a/packages/dashboard-frontend/src/store/Pods/Logs/index.ts b/packages/dashboard-frontend/src/store/Pods/Logs/index.ts
index 490e5a365..d43e5f26f 100644
--- a/packages/dashboard-frontend/src/store/Pods/Logs/index.ts
+++ b/packages/dashboard-frontend/src/store/Pods/Logs/index.ts
@@ -15,8 +15,8 @@ import { V1Pod } from '@kubernetes/client-node';
import { Action, Reducer } from 'redux';
import { AppThunk } from '../..';
import { container } from '../../../inversify.config';
-import { WebsocketClient } from '../../../services/dashboard-backend-client/websocketClient';
-import { ChannelListener } from '../../../services/dashboard-backend-client/websocketClient/messageHandler';
+import { WebsocketClient } from '../../../services/backend-client/websocketClient';
+import { ChannelListener } from '../../../services/backend-client/websocketClient/messageHandler';
import { createObject } from '../../helpers';
import { selectDefaultNamespace } from '../../InfrastructureNamespaces/selectors';
import { selectAllPods } from '../selectors';
@@ -193,11 +193,11 @@ export const reducer: Reducer = (
const _containers = _pod?.containers;
const _containerLogs = _containers?.[action.containerName];
const _logs = action.failure === _containerLogs?.failure ? _containerLogs.logs : '';
- return createObject(state, {
+ return createObject(state, {
logs: createObject(state.logs, {
- [action.podName]: createObject(_pod, {
+ [action.podName]: createObject(_pod, {
error: undefined,
- containers: createObject(_containers, {
+ containers: createObject(_containers, {
[action.containerName]: {
logs: _logs + action.logs,
failure: action.failure,
@@ -208,7 +208,7 @@ export const reducer: Reducer = (
});
}
case Type.DELETE_LOGS:
- return createObject(state, {
+ return createObject(state, {
logs: createObject(state.logs, {
[action.podName]: undefined,
}),
diff --git a/packages/dashboard-frontend/src/store/Pods/__tests__/actions.spec.ts b/packages/dashboard-frontend/src/store/Pods/__tests__/actions.spec.ts
index b5299a2d0..7b989aa07 100644
--- a/packages/dashboard-frontend/src/store/Pods/__tests__/actions.spec.ts
+++ b/packages/dashboard-frontend/src/store/Pods/__tests__/actions.spec.ts
@@ -18,7 +18,7 @@ import { ThunkDispatch } from 'redux-thunk';
import * as testStore from '..';
import { AppState } from '../..';
import { container } from '../../../inversify.config';
-import { WebsocketClient } from '../../../services/dashboard-backend-client/websocketClient';
+import { WebsocketClient } from '../../../services/backend-client/websocketClient';
import { AUTHORIZED } from '../../sanityCheckMiddleware';
import { FakeStoreBuilder } from '../../__mocks__/storeBuilder';
import { pod1, pod2 } from './stub';
diff --git a/packages/dashboard-frontend/src/store/Pods/index.ts b/packages/dashboard-frontend/src/store/Pods/index.ts
index d4d0d09e4..624ae8300 100644
--- a/packages/dashboard-frontend/src/store/Pods/index.ts
+++ b/packages/dashboard-frontend/src/store/Pods/index.ts
@@ -15,8 +15,8 @@ import { V1Pod } from '@kubernetes/client-node';
import { Action, Reducer } from 'redux';
import { AppThunk } from '..';
import { container } from '../../inversify.config';
-import { fetchPods } from '../../services/dashboard-backend-client/podsApi';
-import { WebsocketClient } from '../../services/dashboard-backend-client/websocketClient';
+import { fetchPods } from '../../services/backend-client/podsApi';
+import { WebsocketClient } from '../../services/backend-client/websocketClient';
import { getNewerResourceVersion } from '../../services/helpers/resourceVersion';
import { createObject } from '../helpers';
import { selectDefaultNamespace } from '../InfrastructureNamespaces/selectors';
@@ -198,23 +198,23 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_PODS:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_PODS:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
pods: action.pods,
resourceVersion: getNewerResourceVersion(action.resourceVersion, state.resourceVersion),
});
case Type.RECEIVE_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
case Type.RECEIVE_POD:
- return createObject(state, {
+ return createObject(state, {
pods: state.pods.concat([action.pod]),
resourceVersion: getNewerResourceVersion(
action.pod.metadata?.resourceVersion,
@@ -222,7 +222,7 @@ export const reducer: Reducer = (
),
});
case Type.MODIFY_POD:
- return createObject(state, {
+ return createObject(state, {
pods: state.pods.map(pod => (isSamePod(pod, action.pod) ? action.pod : pod)),
resourceVersion: getNewerResourceVersion(
action.pod.metadata?.resourceVersion,
@@ -230,7 +230,7 @@ export const reducer: Reducer = (
),
});
case Type.DELETE_POD:
- return createObject(state, {
+ return createObject(state, {
pods: state.pods.filter(pod => isSamePod(pod, action.pod) === false),
resourceVersion: getNewerResourceVersion(
action.pod.metadata?.resourceVersion,
diff --git a/packages/dashboard-frontend/src/store/SanityCheck/index.ts b/packages/dashboard-frontend/src/store/SanityCheck/index.ts
index b43807b09..83d81b001 100644
--- a/packages/dashboard-frontend/src/store/SanityCheck/index.ts
+++ b/packages/dashboard-frontend/src/store/SanityCheck/index.ts
@@ -13,14 +13,16 @@
import { Action, Reducer } from 'redux';
import { AppThunk } from '..';
import { helpers } from '@eclipse-che/common';
-import { container } from '../../inversify.config';
import { getDefer } from '../../services/helpers/deferred';
import { delay } from '../../services/helpers/delay';
-import { CheWorkspaceClient } from '../../services/workspace-client/cheworkspace/cheWorkspaceClient';
-import { isForbidden, isUnauthorized } from '../../services/workspace-client/helpers';
+import {
+ getErrorMessage,
+ hasLoginPage,
+ isForbidden,
+ isUnauthorized,
+} from '../../services/workspace-client/helpers';
import { createObject } from '../helpers';
-
-const WorkspaceClient = container.get(CheWorkspaceClient);
+import { provisionKubernetesNamespace } from '../../services/backend-client/kubernetesNamespaceApi';
const secToStale = 5;
const timeToStale = secToStale * 1000;
@@ -93,7 +95,7 @@ export const actionCreators: ActionCreators = {
for (let attempt = 1; attempt <= maxAttemptsNumber; attempt++) {
try {
- await WorkspaceClient.restApiClient.provisionKubernetesNamespace();
+ await provisionKubernetesNamespace();
deferred.resolve(true);
dispatch({
@@ -105,20 +107,19 @@ export const actionCreators: ActionCreators = {
if (attempt === maxAttemptsNumber) {
throw e;
}
- delay(1000);
+ await delay(1000);
}
}
} catch (e) {
- let errorMessage =
- 'Backend is not available. Try to refresh the page or re-login to the Dashboard.';
- if (isUnauthorized(e) || isForbidden(e)) {
- errorMessage = 'User session has expired. You need to re-login to the Dashboard.';
+ if (isUnauthorized(e) || (isForbidden(e) && hasLoginPage(e))) {
+ window.location.reload();
}
- deferred.resolve(false);
+ const errorMessage = getErrorMessage(e);
dispatch({
type: Type.RECEIVED_BACKEND_CHECK_ERROR,
error: errorMessage,
});
+ deferred.resolve(false);
console.error(helpers.errors.getMessage(e));
if (
helpers.errors.includesAxiosResponse(e) &&
@@ -148,15 +149,15 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_BACKEND_CHECK:
- return createObject(state, {
+ return createObject(state, {
error: undefined,
authorized: action.authorized,
lastFetched: action.lastFetched,
});
case Type.RECEIVED_BACKEND_CHECK:
- return createObject(state, {});
+ return createObject(state, {});
case Type.RECEIVED_BACKEND_CHECK_ERROR:
- return createObject(state, {
+ return createObject(state, {
authorized: state.authorized,
lastFetched: state.lastFetched,
error: action.error,
diff --git a/packages/dashboard-frontend/src/store/SanityCheck/selectors.ts b/packages/dashboard-frontend/src/store/SanityCheck/selectors.ts
index 78aee4006..7fd58f906 100644
--- a/packages/dashboard-frontend/src/store/SanityCheck/selectors.ts
+++ b/packages/dashboard-frontend/src/store/SanityCheck/selectors.ts
@@ -26,4 +26,4 @@ export const selectAsyncIsAuthorized = createSelector(
},
);
-export const selectSanityCheckError = createSelector(selectState, state => state.error);
+export const selectSanityCheckError = createSelector(selectState, state => state.error || '');
diff --git a/packages/dashboard-frontend/src/store/ServerConfig/index.ts b/packages/dashboard-frontend/src/store/ServerConfig/index.ts
index a81b545bd..1041215e1 100644
--- a/packages/dashboard-frontend/src/store/ServerConfig/index.ts
+++ b/packages/dashboard-frontend/src/store/ServerConfig/index.ts
@@ -14,7 +14,7 @@ import { Action, Reducer } from 'redux';
import common, { api } from '@eclipse-che/common';
import { AppThunk } from '../';
import { createObject } from '../helpers';
-import * as ServerConfigApi from '../../services/dashboard-backend-client/serverConfigApi';
+import * as ServerConfigApi from '../../services/backend-client/serverConfigApi';
import { AUTHORIZED, SanityCheckAction } from '../sanityCheckMiddleware';
export interface State {
@@ -112,17 +112,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case 'REQUEST_DW_SERVER_CONFIG':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
});
case 'RECEIVE_DW_SERVER_CONFIG':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
config: action.config,
error: undefined,
});
case 'RECEIVE_DW_SERVER_CONFIG_ERROR':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/User/Id/index.ts b/packages/dashboard-frontend/src/store/User/Id/index.ts
index 47391d31a..7a697e6e7 100644
--- a/packages/dashboard-frontend/src/store/User/Id/index.ts
+++ b/packages/dashboard-frontend/src/store/User/Id/index.ts
@@ -16,6 +16,7 @@ import { fetchCheUserId } from '../../../services/che-user-id';
import { createObject } from '../../helpers';
import { AppThunk } from '../../index';
import { AUTHORIZED, SanityCheckAction } from '../../sanityCheckMiddleware';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../../SanityCheck/selectors';
export interface State {
cheUserId: string;
@@ -52,10 +53,13 @@ export type ActionCreators = {
export const actionCreators: ActionCreators = {
requestCheUserId:
(): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_CHE_USER_ID, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_CHE_USER_ID, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const cheUserId = await fetchCheUserId();
dispatch({
type: Type.RECEIVE_CHE_USER_ID,
@@ -88,17 +92,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_CHE_USER_ID:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_CHE_USER_ID:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
cheUserId: action.cheUserId,
});
case Type.RECEIVE_CHE_USER_ID_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/User/Profile/index.ts b/packages/dashboard-frontend/src/store/User/Profile/index.ts
index af906e376..f4ff0e890 100644
--- a/packages/dashboard-frontend/src/store/User/Profile/index.ts
+++ b/packages/dashboard-frontend/src/store/User/Profile/index.ts
@@ -14,10 +14,11 @@
import common, { api } from '@eclipse-che/common';
import { Action, Reducer } from 'redux';
-import { fetchUserProfile } from '../../../services/dashboard-backend-client/userProfileApi';
+import { fetchUserProfile } from '../../../services/backend-client/userProfileApi';
import { createObject } from '../../helpers';
import { AppThunk } from '../../index';
import { AUTHORIZED, SanityCheckAction } from '../../sanityCheckMiddleware';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../../SanityCheck/selectors';
export interface State {
userProfile: api.IUserProfile;
@@ -57,10 +58,13 @@ export type ActionCreators = {
export const actionCreators: ActionCreators = {
requestUserProfile:
(namespace: string): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_USER_PROFILE, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_USER_PROFILE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const userProfile = await fetchUserProfile(namespace);
dispatch({
type: Type.RECEIVE_USER_PROFILE,
@@ -99,17 +103,17 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_USER_PROFILE:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_USER_PROFILE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
userProfile: action.userProfile,
});
case Type.RECEIVE_USER_PROFILE_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
diff --git a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/__tests__/actions.spec.ts b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/__tests__/actions.spec.ts
index 86acb05e8..5fbf4ebb4 100644
--- a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/__tests__/actions.spec.ts
+++ b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/__tests__/actions.spec.ts
@@ -22,8 +22,8 @@ import * as testStore from '..';
import { AppState } from '../../..';
import { container } from '../../../../inversify.config';
import { FactoryParams } from '../../../../services/helpers/factoryFlow/buildFactoryParams';
-import { fetchServerConfig } from '../../../../services/dashboard-backend-client/serverConfigApi';
-import { WebsocketClient } from '../../../../services/dashboard-backend-client/websocketClient';
+import { fetchServerConfig } from '../../../../services/backend-client/serverConfigApi';
+import { WebsocketClient } from '../../../../services/backend-client/websocketClient';
import devfileApi from '../../../../services/devfileApi';
import { DevWorkspaceClient } from '../../../../services/workspace-client/devworkspace/devWorkspaceClient';
import { AUTHORIZED } from '../../../sanityCheckMiddleware';
@@ -33,13 +33,13 @@ import { FakeStoreBuilder } from '../../../__mocks__/storeBuilder';
import { checkRunningWorkspacesLimit } from '../checkRunningWorkspacesLimit';
import { DEVWORKSPACE_STORAGE_TYPE_ATTR } from '../../../../services/devfileApi/devWorkspace/spec/template';
-jest.mock('../../../../services/dashboard-backend-client/serverConfigApi');
+jest.mock('../../../../services/backend-client/serverConfigApi');
jest.mock('../../../../services/helpers/delay', () => ({
delay: jest.fn().mockResolvedValue(undefined),
}));
jest.mock('../checkRunningWorkspacesLimit.ts');
-jest.mock('../../../../services/dashboard-backend-client/devworkspaceResourcesApi', () => ({
+jest.mock('../../../../services/backend-client/devworkspaceResourcesApi', () => ({
fetchResources: () => `
apiVersion: workspace.devfile.io/v1alpha2
kind: DevWorkspaceTemplate
@@ -95,7 +95,7 @@ spec:
}));
const mockPatchTemplate = jest.fn();
-jest.mock('../../../../services/dashboard-backend-client/devWorkspaceTemplateApi', () => ({
+jest.mock('../../../../services/backend-client/devWorkspaceTemplateApi', () => ({
getTemplates: () => [
{
apiVersion: 'workspace.devfile.io/v1alpha2',
@@ -111,7 +111,7 @@ jest.mock('../../../../services/dashboard-backend-client/devWorkspaceTemplateApi
mockPatchTemplate(templateNamespace, templateName, targetTemplatePatch),
}));
const mockPatchWorkspace = jest.fn();
-jest.mock('../../../../services/dashboard-backend-client/devWorkspaceApi', () => ({
+jest.mock('../../../../services/backend-client/devWorkspaceApi', () => ({
patchWorkspace: (namespace, workspaceName, patch) =>
mockPatchWorkspace(namespace, workspaceName, patch),
}));
@@ -635,6 +635,10 @@ describe('DevWorkspace store, actions', () => {
const actions = store.getActions();
const expectedActions: Array = [
+ {
+ type: testStore.Type.REQUEST_DEVWORKSPACE,
+ check: AUTHORIZED,
+ },
{
message: 'Cleaning up resources for deletion',
type: testStore.Type.TERMINATE_DEVWORKSPACE,
@@ -659,6 +663,10 @@ describe('DevWorkspace store, actions', () => {
const actions = store.getActions();
const expectedActions: Array = [
+ {
+ type: testStore.Type.REQUEST_DEVWORKSPACE,
+ check: AUTHORIZED,
+ },
{
type: testStore.Type.RECEIVE_DEVWORKSPACE_ERROR,
error: `Failed to delete the workspace ${devWorkspace.metadata.name}, reason: Something unexpected happened.`,
diff --git a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts
index cbe99da2f..d291052b3 100644
--- a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts
+++ b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts
@@ -16,12 +16,9 @@ import { Action, Reducer } from 'redux';
import { AppThunk } from '../..';
import { container } from '../../../inversify.config';
import { FactoryParams } from '../../../services/helpers/factoryFlow/buildFactoryParams';
-import {
- injectKubeConfig,
- podmanLogin,
-} from '../../../services/dashboard-backend-client/devWorkspaceApi';
-import { fetchResources } from '../../../services/dashboard-backend-client/devworkspaceResourcesApi';
-import { WebsocketClient } from '../../../services/dashboard-backend-client/websocketClient';
+import { injectKubeConfig, podmanLogin } from '../../../services/backend-client/devWorkspaceApi';
+import { fetchResources } from '../../../services/backend-client/devworkspaceResourcesApi';
+import { WebsocketClient } from '../../../services/backend-client/websocketClient';
import devfileApi, { isDevWorkspace } from '../../../services/devfileApi';
import { devWorkspaceKind } from '../../../services/devfileApi/devWorkspace';
import {
@@ -56,11 +53,12 @@ import {
} from '../../ServerConfig/selectors';
import { checkRunningWorkspacesLimit } from './checkRunningWorkspacesLimit';
import { selectDevWorkspacesResourceVersion } from './selectors';
-import * as DwtApi from '../../../services/dashboard-backend-client/devWorkspaceTemplateApi';
+import * as DwtApi from '../../../services/backend-client/devWorkspaceTemplateApi';
import { selectDefaultDevfile } from '../../DevfileRegistries/selectors';
-import * as DwApi from '../../../services/dashboard-backend-client/devWorkspaceApi';
+import * as DwApi from '../../../services/backend-client/devWorkspaceApi';
import { selectDefaultEditor } from '../../Plugins/devWorkspacePlugins/selectors';
import { DEVWORKSPACE_STORAGE_TYPE_ATTR } from '../../../services/devfileApi/devWorkspace/spec/template';
+import { selectAsyncIsAuthorized, selectSanityCheckError } from '../../SanityCheck/selectors';
export const onStatusChangeCallbacks = new Map void>();
@@ -196,9 +194,12 @@ export const actionCreators: ActionCreators = {
requestWorkspaces:
(): AppThunk> =>
async (dispatch, getState): Promise => {
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const defaultKubernetesNamespace = selectDefaultNamespace(getState());
const defaultNamespace = defaultKubernetesNamespace.name;
const { workspaces, resourceVersion } = defaultNamespace
@@ -242,10 +243,13 @@ export const actionCreators: ActionCreators = {
requestWorkspace:
(workspace: devfileApi.DevWorkspace): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const namespace = workspace.metadata.namespace;
const name = workspace.metadata.name;
const update = await getDevWorkspaceClient().getWorkspaceByName(namespace, name);
@@ -290,8 +294,12 @@ export const actionCreators: ActionCreators = {
return;
}
await OAuthService.refreshTokenIfNeeded(workspace);
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
checkRunningWorkspacesLimit(getState());
if (workspace.metadata.annotations?.[DEVWORKSPACE_NEXT_START_ANNOTATION]) {
@@ -435,8 +443,13 @@ export const actionCreators: ActionCreators = {
terminateWorkspace:
(workspace: devfileApi.DevWorkspace): AppThunk> =>
- async (dispatch): Promise => {
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const namespace = workspace.metadata.namespace;
const name = workspace.metadata.name;
await getDevWorkspaceClient().delete(namespace, name);
@@ -461,10 +474,13 @@ export const actionCreators: ActionCreators = {
updateWorkspaceAnnotation:
(workspace: devfileApi.DevWorkspace): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const updated = await getDevWorkspaceClient().updateAnnotation(workspace);
dispatch({
type: Type.UPDATE_DEVWORKSPACE,
@@ -484,10 +500,13 @@ export const actionCreators: ActionCreators = {
updateWorkspace:
(workspace: devfileApi.DevWorkspace): AppThunk> =>
- async (dispatch): Promise => {
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
+ async (dispatch, getState): Promise => {
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const updated = await getDevWorkspaceClient().update(workspace);
dispatch({
type: Type.UPDATE_DEVWORKSPACE,
@@ -513,15 +532,18 @@ export const actionCreators: ActionCreators = {
): AppThunk> =>
async (dispatch, getState): Promise => {
const state = getState();
-
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
const defaultKubernetesNamespace = selectDefaultNamespace(state);
const openVSXUrl = selectOpenVSXUrl(state);
const pluginRegistryUrl = selectPluginRegistryUrl(state);
const pluginRegistryInternalUrl = selectPluginRegistryInternalUrl(state);
const defaultNamespace = defaultKubernetesNamespace.name;
+
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
/* create a new DevWorkspace */
const createResp = await getDevWorkspaceClient().createDevWorkspace(
defaultNamespace,
@@ -592,9 +614,6 @@ export const actionCreators: ActionCreators = {
(workspace: devfileApi.DevWorkspace): AppThunk> =>
async (dispatch, getState): Promise => {
const state = getState();
-
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
const defaultsDevfile = selectDefaultDevfile(state);
if (!defaultsDevfile) {
throw new Error('Cannot define default devfile');
@@ -616,6 +635,11 @@ export const actionCreators: ActionCreators = {
let devWorkspaceTemplateResource: devfileApi.DevWorkspaceTemplate;
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const response = await getEditor(defaultsEditor, dispatch, getState, pluginRegistryUrl);
if (response.content) {
editorContent = response.content;
@@ -796,9 +820,6 @@ export const actionCreators: ActionCreators = {
): AppThunk> =>
async (dispatch, getState): Promise => {
const state = getState();
-
- await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
-
const pluginRegistryUrl = state.dwServerConfig.config.pluginRegistryURL;
let devWorkspaceResource: devfileApi.DevWorkspace;
let devWorkspaceTemplateResource: devfileApi.DevWorkspaceTemplate;
@@ -846,6 +867,11 @@ export const actionCreators: ActionCreators = {
}
try {
+ await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED });
+ if (!(await selectAsyncIsAuthorized(getState()))) {
+ const error = selectSanityCheckError(getState());
+ throw new Error(error);
+ }
const resourcesContent = await fetchResources({
pluginRegistryUrl,
devfileContent: dump(devfile),
@@ -1019,23 +1045,23 @@ export const reducer: Reducer = (
const action = incomingAction as KnownAction;
switch (action.type) {
case Type.REQUEST_DEVWORKSPACE:
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
error: undefined,
});
case Type.RECEIVE_DEVWORKSPACE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
workspaces: action.workspaces,
resourceVersion: getNewerResourceVersion(action.resourceVersion, state.resourceVersion),
});
case Type.RECEIVE_DEVWORKSPACE_ERROR:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
error: action.error,
});
case Type.UPDATE_DEVWORKSPACE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
workspaces: state.workspaces.map(workspace =>
WorkspaceAdapter.getUID(workspace) === WorkspaceAdapter.getUID(action.workspace)
@@ -1048,7 +1074,7 @@ export const reducer: Reducer = (
),
});
case Type.ADD_DEVWORKSPACE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
workspaces: state.workspaces
.filter(
@@ -1062,7 +1088,7 @@ export const reducer: Reducer = (
),
});
case Type.TERMINATE_DEVWORKSPACE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
workspaces: state.workspaces.map(workspace => {
if (WorkspaceAdapter.getUID(workspace) === action.workspaceUID) {
@@ -1078,7 +1104,7 @@ export const reducer: Reducer = (
}),
});
case Type.DELETE_DEVWORKSPACE:
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
workspaces: state.workspaces.filter(
workspace =>
@@ -1090,7 +1116,7 @@ export const reducer: Reducer = (
),
});
case Type.UPDATE_STARTED_WORKSPACES:
- return createObject(state, {
+ return createObject(state, {
startedWorkspaces: action.workspaces.reduce((acc, workspace) => {
if (workspace.spec.started === false) {
delete acc[WorkspaceAdapter.getUID(workspace)];
@@ -1113,7 +1139,7 @@ export const reducer: Reducer = (
}, state.startedWorkspaces),
});
case Type.UPDATE_WARNING:
- return createObject(state, {
+ return createObject(state, {
warnings: {
[WorkspaceAdapter.getUID(action.workspace)]: action.warning,
},
diff --git a/packages/dashboard-frontend/src/store/Workspaces/index.ts b/packages/dashboard-frontend/src/store/Workspaces/index.ts
index e5b8736a5..ece5fc2b1 100644
--- a/packages/dashboard-frontend/src/store/Workspaces/index.ts
+++ b/packages/dashboard-frontend/src/store/Workspaces/index.ts
@@ -300,7 +300,7 @@ export const reducer: Reducer = (state: State | undefined, action: KnownA
switch (action.type) {
case 'REQUEST_WORKSPACES':
- return createObject(state, {
+ return createObject(state, {
isLoading: true,
});
case 'RECEIVE_ERROR':
@@ -308,25 +308,25 @@ export const reducer: Reducer = (state: State | undefined, action: KnownA
case 'ADD_WORKSPACE':
case 'DELETE_WORKSPACE':
case 'RECEIVE_WORKSPACES':
- return createObject(state, {
+ return createObject(state, {
isLoading: false,
});
case 'SET_WORKSPACE_NAME':
- return createObject(state, {
+ return createObject(state, {
namespace: action.namespace,
workspaceName: action.workspaceName,
});
case 'CLEAR_WORKSPACE_NAME':
- return createObject(state, {
+ return createObject(state, {
namespace: '',
workspaceName: '',
});
case 'SET_WORKSPACE_UID':
- return createObject(state, {
+ return createObject(state, {
workspaceUID: action.workspaceUID,
});
case 'CLEAR_WORKSPACE_UID':
- return createObject(state, {
+ return createObject(state, {
workspaceUID: '',
});
default:
diff --git a/yarn.lock b/yarn.lock
index 0a98245fb..efcf7f011 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,7 +7,7 @@
resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
-"@adobe/css-tools@^4.0.1":
+"@adobe/css-tools@^4.3.0":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28"
integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==
@@ -376,7 +376,7 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
-"@eclipse-che/api@^7.0.0-beta-4.0", "@eclipse-che/api@^7.18.1", "@eclipse-che/api@^7.39.2":
+"@eclipse-che/api@^7.18.1", "@eclipse-che/api@^7.39.2":
version "7.72.0"
resolved "https://registry.yarnpkg.com/@eclipse-che/api/-/api-7.72.0.tgz#f16a19f2628c307783203aa5c205b6098b7e57df"
integrity sha512-baah1TSYAmCOuiFCHssb7mBoO5BrTAAz8tLV8Y1nqXvDIYMXXyHOnbBpl8/rVeplHGEZIDpFyFN1OGLoy6mcJA==
@@ -406,16 +406,6 @@
jsonc-parser "^3.0.0"
reflect-metadata "^0.1.13"
-"@eclipse-che/workspace-client@0.0.1-1672830275":
- version "0.0.1-1672830275"
- resolved "https://registry.yarnpkg.com/@eclipse-che/workspace-client/-/workspace-client-0.0.1-1672830275.tgz#7724fbe74fa8ee86a23f888e23d7031cb608787e"
- integrity sha512-QgbLxTns7m/efbWZbFRqd9UxH4ELN5Np3JzYWzqN5i/R3cra/xuV9KwDedctarZ6iwnW9ptZFsfDcU5zedZKKQ==
- dependencies:
- "@eclipse-che/api" "^7.0.0-beta-4.0"
- axios "^0.21.4"
- qs "^6.9.4"
- tunnel "0.0.6"
-
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
@@ -697,6 +687,18 @@
jest-util "^29.6.2"
slash "^3.0.0"
+"@jest/console@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc"
+ integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+ slash "^3.0.0"
+
"@jest/core@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.2.tgz#6f2d1dbe8aa0265fcd4fb8082ae1952f148209c8"
@@ -731,6 +733,40 @@
slash "^3.0.0"
strip-ansi "^6.0.0"
+"@jest/core@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f"
+ integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==
+ dependencies:
+ "@jest/console" "^29.7.0"
+ "@jest/reporters" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-changed-files "^29.7.0"
+ jest-config "^29.7.0"
+ jest-haste-map "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-regex-util "^29.6.3"
+ jest-resolve "^29.7.0"
+ jest-resolve-dependencies "^29.7.0"
+ jest-runner "^29.7.0"
+ jest-runtime "^29.7.0"
+ jest-snapshot "^29.7.0"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ jest-watcher "^29.7.0"
+ micromatch "^4.0.4"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ strip-ansi "^6.0.0"
+
"@jest/environment@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.2.tgz#794c0f769d85e7553439d107d3f43186dc6874a9"
@@ -741,6 +777,16 @@
"@types/node" "*"
jest-mock "^29.6.2"
+"@jest/environment@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7"
+ integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==
+ dependencies:
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+
"@jest/expect-utils@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.2.tgz#1b97f290d0185d264dd9fdec7567a14a38a90534"
@@ -748,6 +794,13 @@
dependencies:
jest-get-type "^29.4.3"
+"@jest/expect-utils@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6"
+ integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==
+ dependencies:
+ jest-get-type "^29.6.3"
+
"@jest/expect@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.2.tgz#5a2ad58bb345165d9ce0a1845bbf873c480a4b28"
@@ -756,6 +809,14 @@
expect "^29.6.2"
jest-snapshot "^29.6.2"
+"@jest/expect@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2"
+ integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==
+ dependencies:
+ expect "^29.7.0"
+ jest-snapshot "^29.7.0"
+
"@jest/fake-timers@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.2.tgz#fe9d43c5e4b1b901168fe6f46f861b3e652a2df4"
@@ -768,6 +829,18 @@
jest-mock "^29.6.2"
jest-util "^29.6.2"
+"@jest/fake-timers@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565"
+ integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@sinonjs/fake-timers" "^10.0.2"
+ "@types/node" "*"
+ jest-message-util "^29.7.0"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
"@jest/globals@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.2.tgz#74af81b9249122cc46f1eb25793617eec69bf21a"
@@ -778,6 +851,16 @@
"@jest/types" "^29.6.1"
jest-mock "^29.6.2"
+"@jest/globals@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d"
+ integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/expect" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ jest-mock "^29.7.0"
+
"@jest/reporters@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.2.tgz#524afe1d76da33d31309c2c4a2c8062d0c48780a"
@@ -808,6 +891,36 @@
strip-ansi "^6.0.0"
v8-to-istanbul "^9.0.1"
+"@jest/reporters@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7"
+ integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==
+ dependencies:
+ "@bcoe/v8-coverage" "^0.2.3"
+ "@jest/console" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@jridgewell/trace-mapping" "^0.3.18"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ collect-v8-coverage "^1.0.0"
+ exit "^0.1.2"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-instrument "^6.0.0"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.1.3"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+ jest-worker "^29.7.0"
+ slash "^3.0.0"
+ string-length "^4.0.1"
+ strip-ansi "^6.0.0"
+ v8-to-istanbul "^9.0.1"
+
"@jest/schemas@^29.4.3", "@jest/schemas@^29.6.0":
version "29.6.0"
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.0.tgz#0f4cb2c8e3dca80c135507ba5635a4fd755b0040"
@@ -815,6 +928,13 @@
dependencies:
"@sinclair/typebox" "^0.27.8"
+"@jest/schemas@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
+ integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
+ dependencies:
+ "@sinclair/typebox" "^0.27.8"
+
"@jest/source-map@^29.6.0":
version "29.6.0"
resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.0.tgz#bd34a05b5737cb1a99d43e1957020ac8e5b9ddb1"
@@ -824,6 +944,15 @@
callsites "^3.0.0"
graceful-fs "^4.2.9"
+"@jest/source-map@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4"
+ integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.18"
+ callsites "^3.0.0"
+ graceful-fs "^4.2.9"
+
"@jest/test-result@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.2.tgz#fdd11583cd1608e4db3114e8f0cce277bf7a32ed"
@@ -834,6 +963,16 @@
"@types/istanbul-lib-coverage" "^2.0.0"
collect-v8-coverage "^1.0.0"
+"@jest/test-result@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c"
+ integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==
+ dependencies:
+ "@jest/console" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
"@jest/test-sequencer@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz#585eff07a68dd75225a7eacf319780cb9f6b9bf4"
@@ -844,6 +983,16 @@
jest-haste-map "^29.6.2"
slash "^3.0.0"
+"@jest/test-sequencer@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce"
+ integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==
+ dependencies:
+ "@jest/test-result" "^29.7.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ slash "^3.0.0"
+
"@jest/transform@^29.6.2":
version "29.6.2"
resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.2.tgz#522901ebbb211af08835bc3bcdf765ab778094e3"
@@ -865,6 +1014,27 @@
slash "^3.0.0"
write-file-atomic "^4.0.2"
+"@jest/transform@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c"
+ integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==
+ dependencies:
+ "@babel/core" "^7.11.6"
+ "@jest/types" "^29.6.3"
+ "@jridgewell/trace-mapping" "^0.3.18"
+ babel-plugin-istanbul "^6.1.1"
+ chalk "^4.0.0"
+ convert-source-map "^2.0.0"
+ fast-json-stable-stringify "^2.1.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ jest-regex-util "^29.6.3"
+ jest-util "^29.7.0"
+ micromatch "^4.0.4"
+ pirates "^4.0.4"
+ slash "^3.0.0"
+ write-file-atomic "^4.0.2"
+
"@jest/types@^26.6.2":
version "26.6.2"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
@@ -888,6 +1058,18 @@
"@types/yargs" "^17.0.8"
chalk "^4.0.0"
+"@jest/types@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
+ integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
@@ -1603,14 +1785,13 @@
lz-string "^1.4.4"
pretty-format "^26.6.2"
-"@testing-library/jest-dom@^5.17.0":
- version "5.17.0"
- resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz#5e97c8f9a15ccf4656da00fecab505728de81e0c"
- integrity sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==
+"@testing-library/jest-dom@^6.1.3":
+ version "6.1.3"
+ resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.1.3.tgz#443118c9e4043f96396f120de2c7122504a079c5"
+ integrity sha512-YzpjRHoCBWPzpPNtg6gnhasqtE/5O4qz8WCwDEaxtfnPO6gkaLrnuXusrGSPyhIGPezr1HM7ZH0CFaUTY9PJEQ==
dependencies:
- "@adobe/css-tools" "^4.0.1"
+ "@adobe/css-tools" "^4.3.0"
"@babel/runtime" "^7.9.2"
- "@types/testing-library__jest-dom" "^5.9.1"
aria-query "^5.0.0"
chalk "^3.0.0"
css.escape "^1.5.1"
@@ -1953,7 +2134,7 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
-"@types/testing-library__jest-dom@^5.14.9", "@types/testing-library__jest-dom@^5.9.1":
+"@types/testing-library__jest-dom@^5.14.9":
version "5.14.9"
resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz#0fb1e6a0278d87b6737db55af5967570b67cb466"
integrity sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==
@@ -2796,6 +2977,19 @@ babel-jest@^29.6.2:
graceful-fs "^4.2.9"
slash "^3.0.0"
+babel-jest@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5"
+ integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==
+ dependencies:
+ "@jest/transform" "^29.7.0"
+ "@types/babel__core" "^7.1.14"
+ babel-plugin-istanbul "^6.1.1"
+ babel-preset-jest "^29.6.3"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ slash "^3.0.0"
+
babel-messages@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
@@ -2824,6 +3018,16 @@ babel-plugin-jest-hoist@^29.5.0:
"@types/babel__core" "^7.1.14"
"@types/babel__traverse" "^7.0.6"
+babel-plugin-jest-hoist@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626"
+ integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==
+ dependencies:
+ "@babel/template" "^7.3.3"
+ "@babel/types" "^7.3.3"
+ "@types/babel__core" "^7.1.14"
+ "@types/babel__traverse" "^7.0.6"
+
babel-plugin-transform-es2015-block-scoping@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
@@ -2861,6 +3065,14 @@ babel-preset-jest@^29.5.0:
babel-plugin-jest-hoist "^29.5.0"
babel-preset-current-node-syntax "^1.0.0"
+babel-preset-jest@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c"
+ integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==
+ dependencies:
+ babel-plugin-jest-hoist "^29.6.3"
+ babel-preset-current-node-syntax "^1.0.0"
+
babel-register@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
@@ -3821,6 +4033,19 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
+create-jest@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320"
+ integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ chalk "^4.0.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-config "^29.7.0"
+ jest-util "^29.7.0"
+ prompts "^2.0.1"
+
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -4239,6 +4464,11 @@ diff-sequences@^29.4.3:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2"
integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==
+diff-sequences@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
+ integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
+
diffie-hellman@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -4890,6 +5120,17 @@ expect@^29.0.0, expect@^29.6.2:
jest-message-util "^29.6.2"
jest-util "^29.6.2"
+expect@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc"
+ integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==
+ dependencies:
+ "@jest/expect-utils" "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+
exponential-backoff@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
@@ -6570,6 +6811,17 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0:
istanbul-lib-coverage "^3.2.0"
semver "^6.3.0"
+istanbul-lib-instrument@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz#7a8af094cbfff1d5bb280f62ce043695ae8dd5b8"
+ integrity sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/parser" "^7.14.7"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^7.5.4"
+
istanbul-lib-report@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d"
@@ -6634,6 +6886,15 @@ jest-changed-files@^29.5.0:
execa "^5.0.0"
p-limit "^3.1.0"
+jest-changed-files@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a"
+ integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==
+ dependencies:
+ execa "^5.0.0"
+ jest-util "^29.7.0"
+ p-limit "^3.1.0"
+
jest-circus@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.2.tgz#1e6ffca60151ac66cad63fce34f443f6b5bb4258"
@@ -6660,6 +6921,32 @@ jest-circus@^29.6.2:
slash "^3.0.0"
stack-utils "^2.0.3"
+jest-circus@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a"
+ integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/expect" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ dedent "^1.0.0"
+ is-generator-fn "^2.0.0"
+ jest-each "^29.7.0"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-runtime "^29.7.0"
+ jest-snapshot "^29.7.0"
+ jest-util "^29.7.0"
+ p-limit "^3.1.0"
+ pretty-format "^29.7.0"
+ pure-rand "^6.0.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
jest-cli@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.2.tgz#edb381763398d1a292cd1b636a98bfa5644b8fda"
@@ -6678,6 +6965,23 @@ jest-cli@^29.6.2:
prompts "^2.0.1"
yargs "^17.3.1"
+jest-cli@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995"
+ integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==
+ dependencies:
+ "@jest/core" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ chalk "^4.0.0"
+ create-jest "^29.7.0"
+ exit "^0.1.2"
+ import-local "^3.0.2"
+ jest-config "^29.7.0"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ yargs "^17.3.1"
+
jest-config@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.2.tgz#c68723f06b31ca5e63030686e604727d406cd7c3"
@@ -6706,6 +7010,34 @@ jest-config@^29.6.2:
slash "^3.0.0"
strip-json-comments "^3.1.1"
+jest-config@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f"
+ integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==
+ dependencies:
+ "@babel/core" "^7.11.6"
+ "@jest/test-sequencer" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ babel-jest "^29.7.0"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ deepmerge "^4.2.2"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-circus "^29.7.0"
+ jest-environment-node "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-regex-util "^29.6.3"
+ jest-resolve "^29.7.0"
+ jest-runner "^29.7.0"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ micromatch "^4.0.4"
+ parse-json "^5.2.0"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ strip-json-comments "^3.1.1"
+
jest-diff@^29.2.0, jest-diff@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.2.tgz#c36001e5543e82a0805051d3ceac32e6825c1c46"
@@ -6716,6 +7048,16 @@ jest-diff@^29.2.0, jest-diff@^29.6.2:
jest-get-type "^29.4.3"
pretty-format "^29.6.2"
+jest-diff@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a"
+ integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^29.6.3"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
jest-docblock@^29.4.3:
version "29.4.3"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8"
@@ -6723,6 +7065,13 @@ jest-docblock@^29.4.3:
dependencies:
detect-newline "^3.0.0"
+jest-docblock@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a"
+ integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==
+ dependencies:
+ detect-newline "^3.0.0"
+
jest-each@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.2.tgz#c9e4b340bcbe838c73adf46b76817b15712d02ce"
@@ -6734,18 +7083,29 @@ jest-each@^29.6.2:
jest-util "^29.6.2"
pretty-format "^29.6.2"
-jest-environment-jsdom@^29.6.2:
- version "29.6.2"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.6.2.tgz#4fc68836a7774a771819a2f980cb47af3b1629da"
- integrity sha512-7oa/+266AAEgkzae8i1awNEfTfjwawWKLpiw2XesZmaoVVj9u9t8JOYx18cG29rbPNtkUlZ8V4b5Jb36y/VxoQ==
+jest-each@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1"
+ integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==
dependencies:
- "@jest/environment" "^29.6.2"
- "@jest/fake-timers" "^29.6.2"
- "@jest/types" "^29.6.1"
+ "@jest/types" "^29.6.3"
+ chalk "^4.0.0"
+ jest-get-type "^29.6.3"
+ jest-util "^29.7.0"
+ pretty-format "^29.7.0"
+
+jest-environment-jsdom@^29.6.4:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f"
+ integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
"@types/jsdom" "^20.0.0"
"@types/node" "*"
- jest-mock "^29.6.2"
- jest-util "^29.6.2"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
jsdom "^20.0.0"
jest-environment-node@^29.6.2:
@@ -6760,11 +7120,28 @@ jest-environment-node@^29.6.2:
jest-mock "^29.6.2"
jest-util "^29.6.2"
+jest-environment-node@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376"
+ integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
jest-get-type@^29.4.3:
version "29.4.3"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5"
integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==
+jest-get-type@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1"
+ integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==
+
jest-haste-map@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.2.tgz#298c25ea5255cfad8b723179d4295cf3a50a70d1"
@@ -6784,6 +7161,25 @@ jest-haste-map@^29.6.2:
optionalDependencies:
fsevents "^2.3.2"
+jest-haste-map@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104"
+ integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/graceful-fs" "^4.1.3"
+ "@types/node" "*"
+ anymatch "^3.0.3"
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-regex-util "^29.6.3"
+ jest-util "^29.7.0"
+ jest-worker "^29.7.0"
+ micromatch "^4.0.4"
+ walker "^1.0.8"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
jest-leak-detector@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz#e2b307fee78cab091c37858a98c7e1d73cdf5b38"
@@ -6792,6 +7188,14 @@ jest-leak-detector@^29.6.2:
jest-get-type "^29.4.3"
pretty-format "^29.6.2"
+jest-leak-detector@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728"
+ integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==
+ dependencies:
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
jest-matcher-utils@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz#39de0be2baca7a64eacb27291f0bd834fea3a535"
@@ -6802,6 +7206,16 @@ jest-matcher-utils@^29.6.2:
jest-get-type "^29.4.3"
pretty-format "^29.6.2"
+jest-matcher-utils@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12"
+ integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^29.7.0"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
jest-message-util@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.2.tgz#af7adc2209c552f3f5ae31e77cf0a261f23dc2bb"
@@ -6817,6 +7231,21 @@ jest-message-util@^29.6.2:
slash "^3.0.0"
stack-utils "^2.0.3"
+jest-message-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3"
+ integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^29.6.3"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
jest-mock@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.2.tgz#ef9c9b4d38c34a2ad61010a021866dad41ce5e00"
@@ -6826,6 +7255,15 @@ jest-mock@^29.6.2:
"@types/node" "*"
jest-util "^29.6.2"
+jest-mock@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347"
+ integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-util "^29.7.0"
+
jest-pnp-resolver@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e"
@@ -6836,6 +7274,11 @@ jest-regex-util@^29.4.3:
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8"
integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==
+jest-regex-util@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52"
+ integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==
+
jest-resolve-dependencies@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz#36435269b6672c256bcc85fb384872c134cc4cf2"
@@ -6844,6 +7287,14 @@ jest-resolve-dependencies@^29.6.2:
jest-regex-util "^29.4.3"
jest-snapshot "^29.6.2"
+jest-resolve-dependencies@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428"
+ integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==
+ dependencies:
+ jest-regex-util "^29.6.3"
+ jest-snapshot "^29.7.0"
+
jest-resolve@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.2.tgz#f18405fe4b50159b7b6d85e81f6a524d22afb838"
@@ -6859,6 +7310,21 @@ jest-resolve@^29.6.2:
resolve.exports "^2.0.0"
slash "^3.0.0"
+jest-resolve@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30"
+ integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==
+ dependencies:
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ jest-pnp-resolver "^1.2.2"
+ jest-util "^29.7.0"
+ jest-validate "^29.7.0"
+ resolve "^1.20.0"
+ resolve.exports "^2.0.0"
+ slash "^3.0.0"
+
jest-runner@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.2.tgz#89e8e32a8fef24781a7c4c49cd1cb6358ac7fc01"
@@ -6886,6 +7352,33 @@ jest-runner@^29.6.2:
p-limit "^3.1.0"
source-map-support "0.5.13"
+jest-runner@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e"
+ integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==
+ dependencies:
+ "@jest/console" "^29.7.0"
+ "@jest/environment" "^29.7.0"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ emittery "^0.13.1"
+ graceful-fs "^4.2.9"
+ jest-docblock "^29.7.0"
+ jest-environment-node "^29.7.0"
+ jest-haste-map "^29.7.0"
+ jest-leak-detector "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-resolve "^29.7.0"
+ jest-runtime "^29.7.0"
+ jest-util "^29.7.0"
+ jest-watcher "^29.7.0"
+ jest-worker "^29.7.0"
+ p-limit "^3.1.0"
+ source-map-support "0.5.13"
+
jest-runtime@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.2.tgz#692f25e387f982e89ab83270e684a9786248e545"
@@ -6914,6 +7407,34 @@ jest-runtime@^29.6.2:
slash "^3.0.0"
strip-bom "^4.0.0"
+jest-runtime@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817"
+ integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/globals" "^29.7.0"
+ "@jest/source-map" "^29.6.3"
+ "@jest/test-result" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ cjs-module-lexer "^1.0.0"
+ collect-v8-coverage "^1.0.0"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-mock "^29.7.0"
+ jest-regex-util "^29.6.3"
+ jest-resolve "^29.7.0"
+ jest-snapshot "^29.7.0"
+ jest-util "^29.7.0"
+ slash "^3.0.0"
+ strip-bom "^4.0.0"
+
jest-snapshot@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.2.tgz#9b431b561a83f2bdfe041e1cab8a6becdb01af9c"
@@ -6940,6 +7461,32 @@ jest-snapshot@^29.6.2:
pretty-format "^29.6.2"
semver "^7.5.3"
+jest-snapshot@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5"
+ integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==
+ dependencies:
+ "@babel/core" "^7.11.6"
+ "@babel/generator" "^7.7.2"
+ "@babel/plugin-syntax-jsx" "^7.7.2"
+ "@babel/plugin-syntax-typescript" "^7.7.2"
+ "@babel/types" "^7.3.3"
+ "@jest/expect-utils" "^29.7.0"
+ "@jest/transform" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ babel-preset-current-node-syntax "^1.0.0"
+ chalk "^4.0.0"
+ expect "^29.7.0"
+ graceful-fs "^4.2.9"
+ jest-diff "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+ natural-compare "^1.4.0"
+ pretty-format "^29.7.0"
+ semver "^7.5.3"
+
jest-util@^29.0.0, jest-util@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.2.tgz#8a052df8fff2eebe446769fd88814521a517664d"
@@ -6952,6 +7499,18 @@ jest-util@^29.0.0, jest-util@^29.6.2:
graceful-fs "^4.2.9"
picomatch "^2.2.3"
+jest-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
+ integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
jest-validate@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.2.tgz#25d972af35b2415b83b1373baf1a47bb266c1082"
@@ -6964,6 +7523,18 @@ jest-validate@^29.6.2:
leven "^3.1.0"
pretty-format "^29.6.2"
+jest-validate@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c"
+ integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^29.6.3"
+ leven "^3.1.0"
+ pretty-format "^29.7.0"
+
jest-watcher@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.2.tgz#77c224674f0620d9f6643c4cfca186d8893ca088"
@@ -6978,6 +7549,20 @@ jest-watcher@^29.6.2:
jest-util "^29.6.2"
string-length "^4.0.1"
+jest-watcher@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2"
+ integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==
+ dependencies:
+ "@jest/test-result" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.13.1"
+ jest-util "^29.7.0"
+ string-length "^4.0.1"
+
jest-websocket-mock@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/jest-websocket-mock/-/jest-websocket-mock-2.4.1.tgz#e8ed6001cbeff7739b9ee4a74f5937ec1c339408"
@@ -7005,6 +7590,16 @@ jest-worker@^29.4.3, jest-worker@^29.5.0, jest-worker@^29.6.2:
merge-stream "^2.0.0"
supports-color "^8.0.0"
+jest-worker@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a"
+ integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==
+ dependencies:
+ "@types/node" "*"
+ jest-util "^29.7.0"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
jest@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.2.tgz#3bd55b9fd46a161b2edbdf5f1d1bd0d1eab76c42"
@@ -7015,6 +7610,16 @@ jest@^29.6.2:
import-local "^3.0.2"
jest-cli "^29.6.2"
+jest@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613"
+ integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==
+ dependencies:
+ "@jest/core" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ import-local "^3.0.2"
+ jest-cli "^29.7.0"
+
joi@^17.6.4:
version "17.9.2"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.2.tgz#8b2e4724188369f55451aebd1d0b1d9482470690"
@@ -9359,6 +9964,15 @@ pretty-format@^29.0.0, pretty-format@^29.6.2:
ansi-styles "^5.0.0"
react-is "^18.0.0"
+pretty-format@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
+ integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
private@^0.1.8, private@~0.1.5:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -9512,7 +10126,7 @@ q@^1.5.1:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
-qs@^6.11.2, qs@^6.9.4:
+qs@^6.11.2:
version "6.11.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
@@ -11328,11 +11942,6 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
-tunnel@0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
- integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
-
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"