Fix fetch (missing request headers etc.)
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
@@ -4,7 +4,7 @@ import { selectAccount } from 'soapbox/selectors';
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { getFeatures, parseVersion, PLEROMA } from 'soapbox/utils/features';
|
||||
|
||||
import api, { getLinks } from '../api';
|
||||
import api, { getLinks, type PlfeResponse } from '../api';
|
||||
|
||||
import {
|
||||
importFetchedAccount,
|
||||
@@ -117,7 +117,7 @@ const BIRTHDAY_REMINDERS_FETCH_REQUEST = 'BIRTHDAY_REMINDERS_FETCH_REQUEST';
|
||||
const BIRTHDAY_REMINDERS_FETCH_SUCCESS = 'BIRTHDAY_REMINDERS_FETCH_SUCCESS';
|
||||
const BIRTHDAY_REMINDERS_FETCH_FAIL = 'BIRTHDAY_REMINDERS_FETCH_FAIL';
|
||||
|
||||
const maybeRedirectLogin = (error: { response: Response }, history?: History) => {
|
||||
const maybeRedirectLogin = (error: { response: PlfeResponse }, history?: History) => {
|
||||
// The client is unauthorized - redirect to login.
|
||||
if (history && error?.response?.status === 401) {
|
||||
history.push('/login');
|
||||
|
||||
@@ -26,7 +26,7 @@ import { normalizeUsername } from 'soapbox/utils/input';
|
||||
import { getScopes } from 'soapbox/utils/scopes';
|
||||
import { isStandalone } from 'soapbox/utils/state';
|
||||
|
||||
import api, { getFetch } from '../api';
|
||||
import api, { type PlfeResponse, getFetch } from '../api';
|
||||
|
||||
import { importFetchedAccount } from './importer';
|
||||
|
||||
@@ -187,7 +187,7 @@ const loadCredentials = (token: string, accountUrl: string) =>
|
||||
const logIn = (username: string, password: string) =>
|
||||
(dispatch: AppDispatch) => dispatch(getAuthApp()).then(() =>
|
||||
dispatch(createUserToken(normalizeUsername(username), password)),
|
||||
).catch((error: { response: Response }) => {
|
||||
).catch((error: { response: PlfeResponse }) => {
|
||||
if ((error.response?.json as any)?.error === 'mfa_required') {
|
||||
// If MFA is required, throw the error and handle it in the component.
|
||||
throw error;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
import api, { getLinks } from 'soapbox/api';
|
||||
import api, { type PlfeResponse, getLinks } from 'soapbox/api';
|
||||
import { normalizeAccount } from 'soapbox/normalizers';
|
||||
import toast from 'soapbox/toast';
|
||||
|
||||
@@ -48,7 +48,7 @@ const fileExport = (content: string, fileName: string) => {
|
||||
document.body.removeChild(fileToDownload);
|
||||
};
|
||||
|
||||
const listAccounts = (getState: () => RootState) => async(apiResponse: Response & { json: any }) => {
|
||||
const listAccounts = (getState: () => RootState) => async(apiResponse: PlfeResponse) => {
|
||||
const followings = apiResponse.json;
|
||||
let accounts = [];
|
||||
let next = getLinks(apiResponse).refs.find(link => link.rel === 'next');
|
||||
|
||||
@@ -192,6 +192,8 @@ const expandTimeline = (timelineId: string, path: string, params: Record<string,
|
||||
const statuses = deduplicateStatuses(response.json);
|
||||
dispatch(importFetchedStatuses(statuses.filter(status => status.accounts)));
|
||||
|
||||
console.log(response);
|
||||
|
||||
dispatch(expandTimelineSuccess(
|
||||
timelineId,
|
||||
statuses,
|
||||
|
||||
@@ -11,6 +11,8 @@ import { RootState } from 'soapbox/store';
|
||||
import { getAccessToken, getAppToken, isURL, parseBaseURL } from 'soapbox/utils/auth';
|
||||
import { buildFullPath } from 'soapbox/utils/url';
|
||||
|
||||
type PlfeResponse<T = any> = Response & { data: string; json: T };
|
||||
|
||||
/**
|
||||
Parse Link headers, mostly for pagination.
|
||||
@param {object} response - Fetch API response object
|
||||
@@ -57,7 +59,7 @@ const getFetch = (accessToken?: string | null, baseURL: string = '') =>
|
||||
|
||||
// Fetch API doesn't report upload progress, use XHR
|
||||
if (init?.onUploadProgress) {
|
||||
return new Promise<Response & { data: string; json: T }>((resolve, reject) => {
|
||||
return new Promise<PlfeResponse<T>>((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.addEventListener('progress', init.onUploadProgress!);
|
||||
@@ -72,7 +74,7 @@ const getFetch = (accessToken?: string | null, baseURL: string = '') =>
|
||||
}
|
||||
|
||||
if (xhr.status >= 400) reject({ response: { status: xhr.status, data, json } });
|
||||
resolve({ status: xhr.status, data, json } as any);
|
||||
resolve({ status: xhr.status, data, json } as any as PlfeResponse<T>);
|
||||
});
|
||||
|
||||
xhr.open(init?.method || 'GET', fullPath, true);
|
||||
@@ -85,8 +87,8 @@ const getFetch = (accessToken?: string | null, baseURL: string = '') =>
|
||||
return fetch(fullPath, {
|
||||
...init,
|
||||
headers,
|
||||
}).then(async (response) => {
|
||||
const data = await response.text();
|
||||
}).then(async (res) => {
|
||||
const data = await res.text();
|
||||
let json: T = undefined!;
|
||||
|
||||
try {
|
||||
@@ -95,11 +97,14 @@ const getFetch = (accessToken?: string | null, baseURL: string = '') =>
|
||||
//
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const { headers, ok, redirected, status, statusText, type, url } = response;
|
||||
throw { response: { headers, ok, redirected, status, statusText, type, url, data, json } };
|
||||
const { headers, ok, redirected, status, statusText, type, url } = res;
|
||||
|
||||
const response = { headers, ok, redirected, status, statusText, type, url, data, json };
|
||||
|
||||
if (!ok) {
|
||||
throw { response };
|
||||
}
|
||||
return { ...response, data, json };
|
||||
return response as any as PlfeResponse<T>;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -120,7 +125,10 @@ const staticFetch = (input: URL | RequestInfo, init?: RequestInit | undefined) =
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
return { ...response, data, json };
|
||||
|
||||
const { headers, ok, redirected, status, statusText, type, url } = response;
|
||||
|
||||
return { headers, ok, redirected, status, statusText, type, url, data, json } as any as PlfeResponse;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -141,6 +149,7 @@ const api = (getState: () => RootState, authType: string = 'user') => {
|
||||
};
|
||||
|
||||
export {
|
||||
type PlfeResponse,
|
||||
getLinks,
|
||||
getNextLink,
|
||||
getPrevLink,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Entity } from '../types';
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
import type z from 'zod';
|
||||
|
||||
type EntitySchema<TEntity extends Entity = Entity> = z.ZodType<TEntity, z.ZodTypeDef, any>;
|
||||
@@ -32,9 +33,9 @@ interface EntityCallbacks<Value, Error = unknown> {
|
||||
|
||||
/**
|
||||
* Passed into hooks to make requests.
|
||||
* Must return an Axios response.
|
||||
* Must return a response.
|
||||
*/
|
||||
type EntityFn<T> = (value: T) => Promise<Response>
|
||||
type EntityFn<T> = (value: T) => Promise<PlfeResponse>
|
||||
|
||||
export type {
|
||||
EntitySchema,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { parseEntitiesPath } from './utils';
|
||||
|
||||
import type { EntityCallbacks, EntityFn, EntitySchema, ExpandedEntitiesPath } from './types';
|
||||
import type { Entity } from '../types';
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
interface UseCreateEntityOpts<TEntity extends Entity = Entity> {
|
||||
schema?: EntitySchema<TEntity>;
|
||||
@@ -26,7 +27,7 @@ const useCreateEntity = <TEntity extends Entity = Entity, Data = unknown>(
|
||||
|
||||
const createEntity = async (
|
||||
data: Data,
|
||||
callbacks: EntityCallbacks<TEntity, { response?: Response & { json: any } }> = {},
|
||||
callbacks: EntityCallbacks<TEntity, { response?: PlfeResponse }> = {},
|
||||
): Promise<void> => {
|
||||
const result = await setPromise(entityFn(data));
|
||||
const schema = opts.schema || z.custom<TEntity>();
|
||||
|
||||
@@ -10,6 +10,7 @@ import { selectEntity } from '../selectors';
|
||||
|
||||
import type { EntitySchema, EntityPath, EntityFn } from './types';
|
||||
import type { Entity } from '../types';
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
/** Additional options for the hook. */
|
||||
interface UseEntityOpts<TEntity extends Entity> {
|
||||
@@ -66,8 +67,8 @@ const useEntity = <TEntity extends Entity>(
|
||||
isLoading,
|
||||
isLoaded,
|
||||
error,
|
||||
isUnauthorized: (error as { response?: Response })?.response?.status === 401,
|
||||
isForbidden: (error as { response?: Response })?.response?.status === 403,
|
||||
isUnauthorized: (error as { response?: PlfeResponse })?.response?.status === 401,
|
||||
isForbidden: (error as { response?: PlfeResponse })?.response?.status === 403,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -7,10 +7,11 @@ import { useLoading } from 'soapbox/hooks/useLoading';
|
||||
|
||||
import { importEntities } from '../actions';
|
||||
import { findEntity } from '../selectors';
|
||||
import { Entity } from '../types';
|
||||
|
||||
import { EntityFn } from './types';
|
||||
import { type UseEntityOpts } from './useEntity';
|
||||
import type { EntityFn } from './types';
|
||||
import type { UseEntityOpts } from './useEntity';
|
||||
import type { Entity } from '../types';
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
/** Entities will be filtered through this function until it returns true. */
|
||||
type LookupFn<TEntity extends Entity> = (entity: TEntity) => boolean
|
||||
@@ -56,8 +57,8 @@ const useEntityLookup = <TEntity extends Entity>(
|
||||
fetchEntity,
|
||||
isFetching,
|
||||
isLoading,
|
||||
isUnauthorized: (error as { response?: Response })?.response?.status === 401,
|
||||
isForbidden: (error as { response?: Response })?.response?.status === 403,
|
||||
isUnauthorized: (error as { response?: PlfeResponse })?.response?.status === 401,
|
||||
isForbidden: (error as { response?: PlfeResponse })?.response?.status === 403,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ import { isDefaultHeader } from 'soapbox/utils/accounts';
|
||||
import copy from 'soapbox/utils/copy';
|
||||
import { MASTODON, parseVersion } from 'soapbox/utils/features';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
|
||||
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
|
||||
@@ -93,7 +95,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
||||
|
||||
const createAndNavigateToChat = useMutation({
|
||||
mutationFn: (accountId: string) => getOrCreateChatByAccountId(accountId),
|
||||
onError: (error: { response: Response }) => {
|
||||
onError: (error: { response: PlfeResponse }) => {
|
||||
const data = error.response?.json as any;
|
||||
toast.error(data?.error);
|
||||
},
|
||||
|
||||
@@ -15,6 +15,8 @@ import ConsumersList from './consumers-list';
|
||||
import LoginForm from './login-form';
|
||||
import OtpAuthForm from './otp-auth-form';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const LoginPage = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -49,7 +51,7 @@ const LoginPage = () => {
|
||||
} else {
|
||||
setShouldRedirect(true);
|
||||
}
|
||||
}).catch((error: { response: Response }) => {
|
||||
}).catch((error: { response: PlfeResponse }) => {
|
||||
const data: any = error.response?.json;
|
||||
if (data?.error === 'mfa_required') {
|
||||
setMfaAuthNeeded(true);
|
||||
|
||||
@@ -15,6 +15,8 @@ import Blankslate from './blankslate';
|
||||
import EmptyResultsBlankslate from './empty-results-blankslate';
|
||||
import Results from './results';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: { id: 'chat_search.placeholder', defaultMessage: 'Type a name' },
|
||||
});
|
||||
@@ -44,7 +46,7 @@ const ChatSearch = (props: IChatSearch) => {
|
||||
|
||||
const handleClickOnSearchResult = useMutation({
|
||||
mutationFn: (accountId: string) => getOrCreateChatByAccountId(accountId),
|
||||
onError: (error: { response: Response }) => {
|
||||
onError: (error: { response: PlfeResponse }) => {
|
||||
const data = error.response?.json as any;
|
||||
toast.error(data?.error);
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ import toast from 'soapbox/toast';
|
||||
import ChatComposer from './chat-composer';
|
||||
import ChatMessageList from './chat-message-list';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
import type { Attachment } from 'soapbox/types/entities';
|
||||
|
||||
const fileKeyGen = (): number => Math.floor((Math.random() * 0x10000));
|
||||
@@ -69,7 +70,7 @@ const Chat: React.FC<ChatInterface> = ({ chat, inputRef, className }) => {
|
||||
onSuccess: () => {
|
||||
setErrorMessage(undefined);
|
||||
},
|
||||
onError: (error: { response: Response & { json: any } }, _variables, context) => {
|
||||
onError: (error: { response: PlfeResponse }, _variables, context) => {
|
||||
const message = error.response?.json?.error;
|
||||
setErrorMessage(message || intl.formatMessage(messages.failedToSend));
|
||||
setContent(context.prevContent as string);
|
||||
|
||||
@@ -11,6 +11,7 @@ import toast from 'soapbox/toast';
|
||||
|
||||
import ColumnForbidden from '../ui/components/column-forbidden';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
import type { Account as AccountEntity } from 'soapbox/schemas';
|
||||
|
||||
type RouteParams = { groupId: string };
|
||||
@@ -80,7 +81,7 @@ const GroupMembershipRequests: React.FC<IGroupMembershipRequests> = ({ params })
|
||||
const handleAuthorize = async (account: AccountEntity) =>
|
||||
authorize(account.id)
|
||||
.then(() => Promise.resolve())
|
||||
.catch((error: { response: Response }) => {
|
||||
.catch((error: { response: PlfeResponse }) => {
|
||||
refetch();
|
||||
|
||||
let message = intl.formatMessage(messages.authorizeFail, { name: account.username });
|
||||
@@ -95,7 +96,7 @@ const GroupMembershipRequests: React.FC<IGroupMembershipRequests> = ({ params })
|
||||
const handleReject = async (account: AccountEntity) =>
|
||||
reject(account.id)
|
||||
.then(() => Promise.resolve())
|
||||
.catch((error: { response: Response }) => {
|
||||
.catch((error: { response: PlfeResponse }) => {
|
||||
refetch();
|
||||
|
||||
let message = intl.formatMessage(messages.rejectFail, { name: account.username });
|
||||
|
||||
@@ -10,6 +10,8 @@ import toast from 'soapbox/toast';
|
||||
import { isDefaultAvatar } from 'soapbox/utils/accounts';
|
||||
import resizeImage from 'soapbox/utils/resize-image';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
|
||||
});
|
||||
@@ -48,7 +50,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||
setDisabled(false);
|
||||
setSubmitting(false);
|
||||
onNext();
|
||||
}).catch((error: { response: Response }) => {
|
||||
}).catch((error: { response: PlfeResponse }) => {
|
||||
setSubmitting(false);
|
||||
setDisabled(false);
|
||||
setSelectedFile(null);
|
||||
|
||||
@@ -7,6 +7,8 @@ import { Button, FormGroup, Stack, Textarea } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
||||
import toast from 'soapbox/toast';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
bioPlaceholder: { id: 'onboarding.bio.placeholder', defaultMessage: 'Tell the world a little about yourself…' },
|
||||
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
|
||||
@@ -30,7 +32,7 @@ const BioStep = ({ onNext }: { onNext: () => void }) => {
|
||||
.then(() => {
|
||||
setSubmitting(false);
|
||||
onNext();
|
||||
}).catch((error: { response: Response }) => {
|
||||
}).catch((error: { response: PlfeResponse }) => {
|
||||
setSubmitting(false);
|
||||
|
||||
if (error.response?.status === 422) {
|
||||
|
||||
@@ -11,6 +11,8 @@ import toast from 'soapbox/toast';
|
||||
import { isDefaultHeader } from 'soapbox/utils/accounts';
|
||||
import resizeImage from 'soapbox/utils/resize-image';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
header: { id: 'account.header.alt', defaultMessage: 'Profile header' },
|
||||
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
|
||||
@@ -51,7 +53,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => {
|
||||
setDisabled(false);
|
||||
setSubmitting(false);
|
||||
onNext();
|
||||
}).catch((error: { response: Response }) => {
|
||||
}).catch((error: { response: PlfeResponse }) => {
|
||||
setSubmitting(false);
|
||||
setDisabled(false);
|
||||
setSelectedFile(null);
|
||||
|
||||
@@ -7,6 +7,8 @@ import { Button, FormGroup, Input, Stack } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
||||
import toast from 'soapbox/toast';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
usernamePlaceholder: { id: 'onboarding.display_name.placeholder', defaultMessage: 'Eg. John Smith' },
|
||||
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
|
||||
@@ -41,7 +43,7 @@ const DisplayNameStep = ({ onNext }: { onNext: () => void }) => {
|
||||
.then(() => {
|
||||
setSubmitting(false);
|
||||
onNext();
|
||||
}).catch((error: { response: Response }) => {
|
||||
}).catch((error: { response: PlfeResponse }) => {
|
||||
setSubmitting(false);
|
||||
|
||||
if (error.response?.status === 422) {
|
||||
|
||||
@@ -11,6 +11,8 @@ import ConfirmationStep from './steps/confirmation-step';
|
||||
import DetailsStep from './steps/details-step';
|
||||
import PrivacyStep from './steps/privacy-step';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
next: { id: 'manage_group.next', defaultMessage: 'Next' },
|
||||
create: { id: 'manage_group.create', defaultMessage: 'Create Group' },
|
||||
@@ -64,7 +66,7 @@ const CreateGroupModal: React.FC<ICreateGroupModal> = ({ onClose }) => {
|
||||
setCurrentStep(Steps.THREE);
|
||||
setGroup(group);
|
||||
},
|
||||
onError(error: { response?: Response }) {
|
||||
onError(error: { response?: PlfeResponse }) {
|
||||
const msg = z.object({ error: z.string() }).safeParse(error?.response?.json);
|
||||
if (msg.success) {
|
||||
toast.error(msg.data.error);
|
||||
|
||||
@@ -13,6 +13,8 @@ import { useAppDispatch, useFeatures, useOwnAccount, useRegistrationStatus } fro
|
||||
|
||||
import ProfileDropdown from './profile-dropdown';
|
||||
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
|
||||
const messages = defineMessages({
|
||||
login: { id: 'navbar.login.action', defaultMessage: 'Log in' },
|
||||
username: { id: 'navbar.login.username.placeholder', defaultMessage: 'Email or username' },
|
||||
@@ -50,7 +52,7 @@ const Navbar = () => {
|
||||
.then(() => dispatch(fetchInstance()))
|
||||
);
|
||||
})
|
||||
.catch((error: { response: Response }) => {
|
||||
.catch((error: { response: PlfeResponse }) => {
|
||||
setLoading(false);
|
||||
|
||||
const data: any = error.response?.json;
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { ME_FETCH_SKIP } from '../actions/me';
|
||||
|
||||
import type { AnyAction } from 'redux';
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
import type { APIEntity, Account as AccountEntity } from 'soapbox/types/entities';
|
||||
|
||||
const AuthAppRecord = ImmutableRecord({
|
||||
@@ -282,7 +283,7 @@ const persistAuthAccount = (account: APIEntity) => {
|
||||
}
|
||||
};
|
||||
|
||||
const deleteForbiddenToken = (state: State, error: { response: Response }, token: string) => {
|
||||
const deleteForbiddenToken = (state: State, error: { response: PlfeResponse }, token: string) => {
|
||||
if ([401, 403].includes(error.response?.status!)) {
|
||||
return deleteToken(state, token);
|
||||
} else {
|
||||
|
||||
@@ -11,11 +11,12 @@ import {
|
||||
} from '../actions/me';
|
||||
|
||||
import type { AnyAction } from 'redux';
|
||||
import type { PlfeResponse } from 'soapbox/api';
|
||||
import type { Me } from 'soapbox/types/soapbox';
|
||||
|
||||
const initialState: Me = null;
|
||||
|
||||
const handleForbidden = (state: Me, error: { response: Response }) => {
|
||||
const handleForbidden = (state: Me, error: { response: PlfeResponse }) => {
|
||||
if (([401, 403] as any[]).includes(error.response?.status)) {
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { defineMessages, MessageDescriptor } from 'react-intl';
|
||||
import { Toast } from './components/ui';
|
||||
import { httpErrorMessages } from './utils/errors';
|
||||
|
||||
import type { PlfeResponse } from './api';
|
||||
|
||||
type ToastText = string | MessageDescriptor
|
||||
type ToastType = 'success' | 'error' | 'info'
|
||||
|
||||
@@ -39,7 +41,7 @@ const messages = defineMessages({
|
||||
unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'Something went wrong.' },
|
||||
});
|
||||
|
||||
const showAlertForError = (networkError: { response: Response & { json: any } }) => {
|
||||
const showAlertForError = (networkError: { response: PlfeResponse }) => {
|
||||
if (networkError?.response) {
|
||||
const { json, status, statusText } = networkError.response;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user