Skip to content

Commit

Permalink
refactor: remove axios dependency (#1424)
Browse files Browse the repository at this point in the history
  • Loading branch information
vtsvetkov-splunk authored Nov 12, 2024
1 parent 26a1b21 commit 1b43267
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 201 deletions.
1 change: 0 additions & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"@splunk/ui-utils": "^1.7.1",
"@splunk/visualization-context": "^26.4.1",
"@storybook/test": "^8.4.2",
"axios": "^1.7.7",
"immutability-helper": "^3.1.1",
"license-webpack-plugin": "^4.0.2",
"lodash": "^4.17.21",
Expand Down
28 changes: 13 additions & 15 deletions ui/src/components/BaseFormView/BaseFormView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Validator, { SaveValidator } from '../../util/Validator';
import { getUnifiedConfigs, generateToast } from '../../util/util';
import { MODE_CLONE, MODE_CREATE, MODE_EDIT, MODE_CONFIG } from '../../constants/modes';
import { PAGE_INPUT, PAGE_CONF } from '../../constants/pages';
import { axiosCallWrapper, generateEndPointUrl } from '../../util/axiosCallWrapper';
import { generateEndPointUrl, postRequest } from '../../util/api';
import { parseErrorMsg, getFormattedMessage } from '../../util/messageUtil';
import { getBuildDirPath } from '../../util/script';

Expand Down Expand Up @@ -863,15 +863,14 @@ class BaseFormView extends PureComponent<BaseFormProps, BaseFormState> {
body.delete('name');
}

axiosCallWrapper({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
postRequest<{ entry: [any] }>({
endpointUrl: generateEndPointUrl(this.endpoint),
body,
customHeaders: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'post',
handleError: false,
})
.then((response) => {
const val = response?.data?.entry[0];
.then((data) => {
const val = data?.entry[0];
if (this.props.mode !== MODE_CONFIG) {
const tmpObj: Record<string, Record<string, AcceptableFormValueOrNull>> = {};

Expand Down Expand Up @@ -1167,26 +1166,25 @@ class BaseFormView extends PureComponent<BaseFormProps, BaseFormState> {

const OAuthEndpoint = `${encodeURIComponent(this.appName)}_oauth/oauth`;
// Internal handler call to get the access token and other values
axiosCallWrapper({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
postRequest<{ entry: [{ content: any }] }>({
endpointUrl: OAuthEndpoint,
body,
customHeaders: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'post',
handleError: false,
})
.then((response) => {
if (response.data.entry[0].content.error === undefined) {
const accessToken = response.data.entry[0].content.access_token;
const instanceUrl = response.data.entry[0].content.instance_url;
const refreshToken = response.data.entry[0].content.refresh_token;
.then((responseData) => {
if (responseData.entry[0].content.error === undefined) {
const accessToken = responseData.entry[0].content.access_token;
const instanceUrl = responseData.entry[0].content.instance_url;
const refreshToken = responseData.entry[0].content.refresh_token;
// TODO refactor those variables
this.datadict.instance_url = instanceUrl;
this.datadict.refresh_token = refreshToken;
this.datadict.access_token = accessToken;
this.isResponse = true;
return true;
}
this.setErrorMsg(response.data.entry[0].content.error);
this.setErrorMsg(responseData.entry[0].content.error);
this.isError = true;
this.isResponse = true;
return false;
Expand Down
13 changes: 6 additions & 7 deletions ui/src/components/ConfigurationFormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import { _ } from '@splunk/ui-utils/i18n';
import styled from 'styled-components';
import WaitSpinner from '@splunk/react-ui/WaitSpinner';

import axios from 'axios';
import BaseFormView from './BaseFormView/BaseFormView';
import { StyledButton } from '../pages/EntryPageStyle';
import { axiosCallWrapper, generateEndPointUrl } from '../util/axiosCallWrapper';
import { getRequest, generateEndPointUrl } from '../util/api';
import { MODE_CONFIG } from '../constants/modes';
import { WaitSpinnerWrapper } from './table/CustomTableStyle';
import { PAGE_CONF } from '../constants/pages';
Expand All @@ -27,7 +26,7 @@ function ConfigurationFormView({ serviceName }) {

useEffect(() => {
const abortController = new AbortController();
axiosCallWrapper({
getRequest({
endpointUrl: generateEndPointUrl(`settings/${encodeURIComponent(serviceName)}`),
handleError: true,
signal: abortController.signal,
Expand All @@ -39,16 +38,16 @@ function ConfigurationFormView({ serviceName }) {
},
})
.catch((caughtError) => {
if (axios.isCancel(caughtError)) {
if (abortController.signal.aborted) {
return null;
}
throw caughtError;
})
.then((response) => {
if (!response) {
.then((data) => {
if (!data) {
return;
}
setCurrentServiceState(response.data.entry[0].content);
setCurrentServiceState(data.entry[0].content);
});

return () => {
Expand Down
6 changes: 2 additions & 4 deletions ui/src/components/DeleteModal/DeleteModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { _ } from '@splunk/ui-utils/i18n';
import { generateToast } from '../../util/util';
import { StyledButton } from '../../pages/EntryPageStyle';

import { axiosCallWrapper, generateEndPointUrl } from '../../util/axiosCallWrapper';
import { deleteRequest, generateEndPointUrl } from '../../util/api';
import TableContext from '../../context/TableContext';
import { parseErrorMsg, getFormattedMessage } from '../../util/messageUtil';
import { PAGE_INPUT } from '../../constants/pages';
Expand Down Expand Up @@ -51,14 +51,12 @@ class DeleteModal extends Component<DeleteModalProps, DeleteModalState> {
this.setState(
(prevState) => ({ ...prevState, isDeleting: true, ErrorMsg: '' }),
() => {
axiosCallWrapper({
deleteRequest({
endpointUrl: generateEndPointUrl(
`${encodeURIComponent(this.props.serviceName)}/${encodeURIComponent(
this.props.stanzaName
)}`
),
customHeaders: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'delete',
handleError: false,
})
.then(() => {
Expand Down
15 changes: 7 additions & 8 deletions ui/src/components/MultiInputComponent/MultiInputComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import styled from 'styled-components';
import WaitSpinner from '@splunk/react-ui/WaitSpinner';
import { z } from 'zod';

import { AxiosCallType, axiosCallWrapper, generateEndPointUrl } from '../../util/axiosCallWrapper';
import { filterResponse } from '../../util/util';
import { RequestParams, generateEndPointUrl, getRequest } from '../../util/api';
import { filterResponse, FilterResponseParams } from '../../util/util';
import { MultipleSelectCommonOptions } from '../../types/globalConfig/entities';
import { invariant } from '../../util/invariant';
import { AcceptableFormValue } from '../../types/components/shareableTypes';
Expand Down Expand Up @@ -94,30 +94,29 @@ function MultiInputComponent(props: MultiInputComponentProps) {
handleError: true,
params: { count: -1 },
endpointUrl: url,
} satisfies AxiosCallType;
} satisfies RequestParams;
if (dependencyValues) {
apiCallOptions.params = { ...apiCallOptions.params, ...dependencyValues };
}
if (!dependencies || dependencyValues) {
setLoading(true);
axiosCallWrapper(apiCallOptions)
.then((response) => {
getRequest<{ entry: FilterResponseParams }>(apiCallOptions)
.then((data) => {
if (current) {
setOptions(
generateOptions(
filterResponse(
response.data.entry,
data.entry,
labelField,
valueField,
allowList,
denyList
)
)
);
setLoading(false);
}
})
.catch(() => {
.finally(() => {
if (current) {
setLoading(false);
}
Expand Down
18 changes: 6 additions & 12 deletions ui/src/components/SingleInputComponent/SingleInputComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import styled from 'styled-components';
import WaitSpinner from '@splunk/react-ui/WaitSpinner';
import { z } from 'zod';

import { AxiosCallType, axiosCallWrapper, generateEndPointUrl } from '../../util/axiosCallWrapper';
import { RequestParams, generateEndPointUrl, getRequest } from '../../util/api';
import { SelectCommonOptions } from '../../types/globalConfig/entities';
import { filterResponse } from '../../util/util';
import { filterResponse, FilterResponseParams } from '../../util/util';
import { getValueMapTruthyFalse } from '../../util/considerFalseAndTruthy';
import { AcceptableFormValue, StandardPages } from '../../types/components/shareableTypes';

Expand Down Expand Up @@ -136,25 +136,19 @@ function SingleInputComponent(props: SingleInputComponentProps) {
endpointUrl: url,
handleError: true,
params: { count: -1 },
} satisfies AxiosCallType;
} satisfies RequestParams;

if (dependencyValues) {
backendCallOptions.params = { ...backendCallOptions.params, ...dependencyValues };
}

setLoading(true);
axiosCallWrapper(backendCallOptions)
.then((response) => {
getRequest<{ entry: FilterResponseParams }>(backendCallOptions)
.then((data) => {
if (current) {
setOptions(
generateOptions(
filterResponse(
response.data.entry,
labelField,
valueField,
allowList,
denyList
)
filterResponse(data.entry, labelField, valueField, allowList, denyList)
)
);
setLoading(false);
Expand Down
27 changes: 13 additions & 14 deletions ui/src/components/table/TableWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { useState, useEffect, memo, useCallback, useMemo, useRef } from 'react';
import update from 'immutability-helper';
import axios from 'axios';

import { WaitSpinnerWrapper } from './CustomTableStyle';
import { axiosCallWrapper, generateEndPointUrl } from '../../util/axiosCallWrapper';
import { generateEndPointUrl, getRequest, postRequest } from '../../util/api';
import { getUnifiedConfigs, generateToast } from '../../util/util';
import CustomTable from './CustomTable';
import TableHeader from './TableHeader';
Expand Down Expand Up @@ -142,31 +141,32 @@ const TableWrapper: React.FC<ITableWrapperProps> = ({
function fetchInputs() {
const requests =
services?.map((service) =>
axiosCallWrapper({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getRequest<{ entry: [any] }>({
endpointUrl: generateEndPointUrl(encodeURIComponent(service.name)),
params: { count: -1 },
signal: abortController.signal,
handleError: false,
})
) || [];

axios
.all(requests)
Promise.all(requests)
.catch((caughtError) => {
if (axios.isCancel(caughtError)) {
if (abortController.signal.aborted) {
return;
}
const message = parseErrorMsg(caughtError);

generateToast(message, 'error');
setError(caughtError);
})
.then((response) => {
if (!response) {
.then((responsesData) => {
if (!responsesData) {
return;
}
const data = getRowDataFromApiResponse(
services,
response.map((res) => res.data.entry)
responsesData.map((responseData) => responseData.entry)
);
setRowData(data);
})
Expand Down Expand Up @@ -203,13 +203,12 @@ const TableWrapper: React.FC<ITableWrapperProps> = ({
);
const body = new URLSearchParams();
body.append('disabled', String(!row.disabled));
axiosCallWrapper({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
postRequest<{ entry: [any] }>({
endpointUrl: generateEndPointUrl(
`${encodeURIComponent(row.serviceName)}/${encodeURIComponent(row.name)}`
),
body,
customHeaders: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'post',
handleError: true,
callbackOnError: () => {
setRowData((currentRowData: RowDataType) =>
Expand All @@ -222,13 +221,13 @@ const TableWrapper: React.FC<ITableWrapperProps> = ({
})
);
},
}).then((response) => {
}).then((data) => {
setRowData((currentRowData: RowDataType) =>
update(currentRowData, {
[row.serviceName]: {
[row.name]: {
// ADDON-39125: isTrue required if splunktaucclib resthandlers' super() is not invoked
disabled: { $set: isTrue(response.data.entry[0].content.disabled) },
disabled: { $set: isTrue(data.entry[0].content.disabled) },
__toggleShowSpinner: { $set: false },
},
},
Expand Down
8 changes: 8 additions & 0 deletions ui/src/util/ResponseError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class ResponseError extends Error {
response: Response;

constructor(params: { response: Response; message: string }) {
super(params.message);
this.response = params.response;
}
}
63 changes: 63 additions & 0 deletions ui/src/util/api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { http, HttpResponse } from 'msw';
import { generateEndPointUrl, getRequest } from './api';
import { getGlobalConfigMock } from '../mocks/globalConfigMock';
import { setUnifiedConfig } from './util';
import { server } from '../mocks/server';

describe('generateEndPointUrl', () => {
it('should return the correct endpoint URL', () => {
const mockConfig = getGlobalConfigMock();
setUnifiedConfig({
...mockConfig,
meta: {
...mockConfig.meta,
restRoot: 'testing_name',
},
});
const name = 'testing_endpoint';

const result = generateEndPointUrl(name);

expect(result).toMatchInlineSnapshot(`"testing_name_testing_endpoint"`);
});
});

describe('getRequest', () => {
beforeEach(() => {
const mockConfig = getGlobalConfigMock();
setUnifiedConfig({
...mockConfig,
meta: {
...mockConfig.meta,
restRoot: 'testing_name',
},
});
server.use(http.get('*', () => HttpResponse.json({}, { status: 500 })));
});
it('should call callbackOnError if handleError is true', async () => {
const callbackOnError = jest.fn();

await expect(() =>
getRequest({
endpointUrl: 'testing_endpoint',
handleError: true,
callbackOnError,
})
).rejects.toThrow();

expect(callbackOnError).toHaveBeenCalled();
});
it('should not call callbackOnError if handleError is false', async () => {
const callbackOnError = jest.fn();

await expect(() =>
getRequest({
endpointUrl: 'testing_endpoint',
handleError: false,
callbackOnError,
})
).rejects.toThrow();

expect(callbackOnError).not.toHaveBeenCalled();
});
});
Loading

0 comments on commit 1b43267

Please sign in to comment.