Handle @woocommerce/data api error types properly
This commit is contained in:
parent
e179f8d1fe
commit
5e0be91e9c
|
@ -16,14 +16,15 @@ import { controls } from '@wordpress/data';
|
|||
import { STORE_NAME } from './constants';
|
||||
import { ACTION_TYPES as TYPES } from './action-types';
|
||||
import { WC_ADMIN_NAMESPACE } from '../constants';
|
||||
import { WPError } from '../types';
|
||||
import { isRestApiError } from '../types';
|
||||
import {
|
||||
PaypalOnboardingStatus,
|
||||
PluginNames,
|
||||
SelectorKeysWithActions,
|
||||
RecommendedTypes,
|
||||
InstallPluginsResponse,
|
||||
ActivatePluginsResponse,
|
||||
PluginsResponse,
|
||||
PluginNames,
|
||||
} from './types';
|
||||
|
||||
// Can be removed in WP 5.9, wp.data is supported in >5.7.
|
||||
|
@ -38,8 +39,16 @@ class PluginError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
type PluginResponseErrors = PluginsResponse< unknown >[ 'errors' ][ 'errors' ];
|
||||
|
||||
const isPluginResponseError = (
|
||||
plugins: Partial< PluginNames >[],
|
||||
error: unknown
|
||||
): error is PluginResponseErrors =>
|
||||
typeof error === 'object' && error !== null && plugins[ 0 ] in error;
|
||||
|
||||
const formatErrorMessage = (
|
||||
pluginErrors: Record< PluginNames, string[] >,
|
||||
pluginErrors: PluginResponseErrors,
|
||||
actionType = 'install'
|
||||
) => {
|
||||
return sprintf(
|
||||
|
@ -92,10 +101,7 @@ export function setIsRequesting(
|
|||
};
|
||||
}
|
||||
|
||||
export function setError(
|
||||
selector: SelectorKeysWithActions,
|
||||
error: Partial< Record< PluginNames, string[] > >
|
||||
) {
|
||||
export function setError( selector: SelectorKeysWithActions, error: unknown ) {
|
||||
return {
|
||||
type: TYPES.SET_ERROR as const,
|
||||
selector,
|
||||
|
@ -157,8 +163,40 @@ export function setRecommendedPlugins(
|
|||
};
|
||||
}
|
||||
|
||||
function* handlePluginAPIError(
|
||||
actionType: string,
|
||||
plugins: Partial< PluginNames >[],
|
||||
error: unknown
|
||||
) {
|
||||
yield setError( 'installPlugins', error );
|
||||
|
||||
let pluginResponseError = error;
|
||||
if (
|
||||
( error instanceof Error || isRestApiError( error ) ) &&
|
||||
plugins[ 0 ]
|
||||
) {
|
||||
pluginResponseError = {
|
||||
[ plugins[ 0 ] ]: [ error.message ],
|
||||
};
|
||||
}
|
||||
|
||||
if ( isPluginResponseError( plugins, pluginResponseError ) ) {
|
||||
throw new PluginError(
|
||||
formatErrorMessage( pluginResponseError, actionType ),
|
||||
pluginResponseError
|
||||
);
|
||||
} else {
|
||||
throw new PluginError(
|
||||
`Unexpected Plugin Error: ${ JSON.stringify(
|
||||
pluginResponseError
|
||||
) }`,
|
||||
pluginResponseError
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Action Creator Generators
|
||||
export function* installPlugins( plugins: string[] ) {
|
||||
export function* installPlugins( plugins: Partial< PluginNames >[] ) {
|
||||
yield setIsRequesting( 'installPlugins', true );
|
||||
|
||||
try {
|
||||
|
@ -171,26 +209,18 @@ export function* installPlugins( plugins: string[] ) {
|
|||
if ( results.data.installed.length ) {
|
||||
yield updateInstalledPlugins( results.data.installed );
|
||||
}
|
||||
|
||||
if ( Object.keys( results.errors.errors ).length ) {
|
||||
throw results.errors.errors;
|
||||
}
|
||||
|
||||
yield setIsRequesting( 'installPlugins', false );
|
||||
|
||||
return results;
|
||||
} catch ( error ) {
|
||||
if ( error instanceof Error && plugins.length === 1 ) {
|
||||
// Incase of a network error
|
||||
error = { [ plugins[ 0 ] ]: error.message };
|
||||
}
|
||||
const errors = error as WPError[ 'errors' ];
|
||||
yield setError( 'installPlugins', errors );
|
||||
throw new PluginError( formatErrorMessage( errors ), errors );
|
||||
yield handlePluginAPIError( 'install', plugins, error );
|
||||
}
|
||||
}
|
||||
|
||||
export function* activatePlugins( plugins: string[] ) {
|
||||
export function* activatePlugins( plugins: Partial< PluginNames >[] ) {
|
||||
yield setIsRequesting( 'activatePlugins', true );
|
||||
|
||||
try {
|
||||
|
@ -212,13 +242,7 @@ export function* activatePlugins( plugins: string[] ) {
|
|||
|
||||
return results;
|
||||
} catch ( error ) {
|
||||
if ( error instanceof Error && plugins.length === 1 ) {
|
||||
// Incase of a network error
|
||||
error = { [ plugins[ 0 ] ]: error.message };
|
||||
}
|
||||
const errors = error as WPError[ 'errors' ];
|
||||
yield setError( 'installPlugins', errors );
|
||||
throw new PluginError( formatErrorMessage( errors ), errors );
|
||||
yield handlePluginAPIError( 'activate', plugins, error );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import {
|
|||
setRecommendedPlugins,
|
||||
} from './actions';
|
||||
import { PaypalOnboardingStatus, RecommendedTypes } from './types';
|
||||
import { WPError } from '../types';
|
||||
|
||||
// Can be removed in WP 5.9, wp.data is supported in >5.7.
|
||||
const resolveSelect =
|
||||
|
@ -52,7 +51,7 @@ export function* getActivePlugins() {
|
|||
|
||||
yield updateActivePlugins( results.plugins, true );
|
||||
} catch ( error ) {
|
||||
yield setError( 'getActivePlugins', error as WPError[ 'errors' ] );
|
||||
yield setError( 'getActivePlugins', error );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +67,7 @@ export function* getInstalledPlugins() {
|
|||
|
||||
yield updateInstalledPlugins( results.plugins, true );
|
||||
} catch ( error ) {
|
||||
yield setError( 'getInstalledPlugins', error as WPError[ 'errors' ] );
|
||||
yield setError( 'getInstalledPlugins', error );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +83,7 @@ export function* isJetpackConnected() {
|
|||
|
||||
yield updateIsJetpackConnected( results.isActive );
|
||||
} catch ( error ) {
|
||||
yield setError( 'isJetpackConnected', error as WPError[ 'errors' ] );
|
||||
yield setError( 'isJetpackConnected', error );
|
||||
}
|
||||
|
||||
yield setIsRequesting( 'isJetpackConnected', false );
|
||||
|
@ -108,7 +107,7 @@ export function* getJetpackConnectUrl( query: { redirect_url: string } ) {
|
|||
results.connectAction
|
||||
);
|
||||
} catch ( error ) {
|
||||
yield setError( 'getJetpackConnectUrl', error as WPError[ 'errors' ] );
|
||||
yield setError( 'getJetpackConnectUrl', error );
|
||||
}
|
||||
|
||||
yield setIsRequesting( 'getJetpackConnectUrl', false );
|
||||
|
@ -162,10 +161,7 @@ export function* getPaypalOnboardingStatus() {
|
|||
yield setPaypalOnboardingStatus( results );
|
||||
} catch ( error ) {
|
||||
yield setOnboardingStatusWithOptions();
|
||||
yield setError(
|
||||
'getPaypalOnboardingStatus',
|
||||
error as WPError[ 'errors' ]
|
||||
);
|
||||
yield setError( 'getPaypalOnboardingStatus', error );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +184,7 @@ export function* getRecommendedPlugins( type: RecommendedTypes ) {
|
|||
|
||||
yield setRecommendedPlugins( type, results );
|
||||
} catch ( error ) {
|
||||
yield setError( 'getRecommendedPlugins', error as WPError[ 'errors' ] );
|
||||
yield setError( 'getRecommendedPlugins', error );
|
||||
}
|
||||
|
||||
yield setIsRequesting( 'getRecommendedPlugins', false );
|
||||
|
|
|
@ -63,9 +63,9 @@ export type PaypalOnboardingStatus = {
|
|||
};
|
||||
};
|
||||
|
||||
type PluginsResponse< PluginData > = {
|
||||
export type PluginsResponse< PluginData > = {
|
||||
data: PluginData;
|
||||
errors: WPError< PluginNames >;
|
||||
errors: WPError< Partial< PluginNames > >;
|
||||
success: boolean;
|
||||
message: string;
|
||||
} & Response;
|
||||
|
|
|
@ -1,4 +1,19 @@
|
|||
export type RestApiError = {
|
||||
type WPApiFetchError = {
|
||||
code: string;
|
||||
message: string;
|
||||
};
|
||||
|
||||
type WPInternalServerError = {
|
||||
code: string;
|
||||
message: string;
|
||||
additional_errors: unknown[];
|
||||
data: {
|
||||
status: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type RestApiError = WPApiFetchError | WPInternalServerError;
|
||||
|
||||
export const isRestApiError = ( error: unknown ): error is RestApiError =>
|
||||
( error as RestApiError ).code !== undefined &&
|
||||
( error as RestApiError ).message !== undefined;
|
||||
|
|
Loading…
Reference in New Issue