mirror of
https://github.com/strapi/strapi.git
synced 2026-01-07 12:45:45 +00:00
Add generic error handlers
This commit is contained in:
parent
af2694c639
commit
4894c9557b
@ -26,8 +26,10 @@ import type {
|
||||
StreamItem,
|
||||
SchemaDiffHandler,
|
||||
SchemaDiffHandlerContext,
|
||||
AssetsBackupErrorHandler,
|
||||
AssetsBackupErrorHandlerContext,
|
||||
ErrorHandler,
|
||||
ErrorHandlerContext,
|
||||
ErrorHandlers,
|
||||
ErrorCode,
|
||||
} from '../../types';
|
||||
import type { Diff } from '../utils/json';
|
||||
|
||||
@ -41,6 +43,7 @@ import {
|
||||
} from './diagnostic';
|
||||
import { DataTransferError } from '../errors';
|
||||
import * as utils from '../utils';
|
||||
import { ProviderTransferError } from '../errors/providers';
|
||||
|
||||
export const TRANSFER_STAGES: ReadonlyArray<TransferStage> = Object.freeze([
|
||||
'entities',
|
||||
@ -110,18 +113,31 @@ class TransferEngine<
|
||||
|
||||
#handlers: {
|
||||
schemaDiff: SchemaDiffHandler[];
|
||||
assetsBackupError: AssetsBackupErrorHandler[];
|
||||
errors: Partial<ErrorHandlers>;
|
||||
} = {
|
||||
schemaDiff: [],
|
||||
assetsBackupError: [],
|
||||
errors: {},
|
||||
};
|
||||
|
||||
onSchemaDiff(handler: SchemaDiffHandler) {
|
||||
this.#handlers?.schemaDiff?.push(handler);
|
||||
}
|
||||
|
||||
onAssetsBackupError(handler: AssetsBackupErrorHandler) {
|
||||
this.#handlers?.assetsBackupError?.push(handler);
|
||||
addErrorHandler(handlerName: ErrorCode, handler: ErrorHandler) {
|
||||
if (!this.#handlers.errors[handlerName]) {
|
||||
this.#handlers.errors[handlerName] = [];
|
||||
}
|
||||
this.#handlers.errors[handlerName]?.push(handler);
|
||||
}
|
||||
|
||||
async emitResolvableError(error: Error, context?: ErrorHandlerContext) {
|
||||
if (error instanceof ProviderTransferError && error.details?.details.code) {
|
||||
const errorCode = error.details?.details.code as ErrorCode;
|
||||
if (!this.#handlers.errors[errorCode]) {
|
||||
this.#handlers.errors[errorCode] = [];
|
||||
}
|
||||
await utils.middleware.runMiddleware(context ?? {}, this.#handlers.errors[errorCode] ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the currently open stream so that we can access it at any time
|
||||
@ -750,20 +766,17 @@ class TransferEngine<
|
||||
|
||||
async beforeTransfer(): Promise<void> {
|
||||
const runWithDiagnostic = async (provider: IProvider) => {
|
||||
const context: AssetsBackupErrorHandlerContext = {};
|
||||
const context: ErrorHandlerContext = {};
|
||||
|
||||
try {
|
||||
await provider.beforeTransfer?.();
|
||||
} catch (error) {
|
||||
await utils.middleware.runMiddleware<AssetsBackupErrorHandlerContext>(
|
||||
context,
|
||||
this.#handlers.assetsBackupError
|
||||
);
|
||||
if (context.ignore) {
|
||||
return;
|
||||
}
|
||||
// Error happening during the before transfer step should be considered fatal errors
|
||||
if (error instanceof Error) {
|
||||
await this.emitResolvableError(error, context);
|
||||
|
||||
if (context.ignore) {
|
||||
return;
|
||||
}
|
||||
this.panic(error);
|
||||
} else {
|
||||
this.panic(
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ErrorCode } from '../../types';
|
||||
import { DataTransferError } from './base';
|
||||
import { Severity, SeverityKind } from './constants';
|
||||
|
||||
@ -5,6 +6,7 @@ type ProviderStep = 'initialization' | 'validation' | 'transfer';
|
||||
|
||||
type ProviderErrorDetails<P extends ProviderStep = ProviderStep, U = never> = {
|
||||
step: P;
|
||||
code?: ErrorCode;
|
||||
} & ([U] extends [never] ? unknown : { details?: U });
|
||||
|
||||
export class ProviderError<
|
||||
|
||||
@ -195,7 +195,10 @@ class LocalStrapiDestinationProvider implements IDestinationProvider {
|
||||
await fse.outputFile(path.join(assetsDirectory, '.gitkeep'), '');
|
||||
} catch (err) {
|
||||
throw new ProviderTransferError(
|
||||
'The backup folder for the assets could not be created inside the public folder. Please ensure Strapi has write permissions on the public directory'
|
||||
'The backup folder for the assets could not be created inside the public folder. Please ensure Strapi has write permissions on the public directory',
|
||||
{
|
||||
code: 'ASSETS_DIRECTORY_ERR',
|
||||
}
|
||||
);
|
||||
}
|
||||
return backupDirectory;
|
||||
@ -306,7 +309,6 @@ class LocalStrapiDestinationProvider implements IDestinationProvider {
|
||||
});
|
||||
callback();
|
||||
} catch (error) {
|
||||
console.log('Error uploading: ', error);
|
||||
callback(new Error(`Error while uploading asset ${chunk.filename} ${error}`));
|
||||
}
|
||||
});
|
||||
|
||||
@ -2,10 +2,12 @@ import { randomUUID } from 'crypto';
|
||||
import { RawData, WebSocket } from 'ws';
|
||||
|
||||
import type { Client, Server } from '../../../types/remote/protocol';
|
||||
import { ProviderErrorDetails } from '../../../dist/errors/providers';
|
||||
import {
|
||||
ProviderError,
|
||||
ProviderTransferError,
|
||||
ProviderInitializationError,
|
||||
ProviderValidationError,
|
||||
} from '../../errors/providers';
|
||||
|
||||
interface IDispatcherState {
|
||||
@ -72,7 +74,18 @@ export const createDispatcher = (
|
||||
if (response.uuid === uuid) {
|
||||
clearInterval(interval);
|
||||
if (response.error) {
|
||||
return reject(new ProviderError('error', response.error.message));
|
||||
const message = response.error.message;
|
||||
const details = response.error.details?.details as ProviderErrorDetails;
|
||||
const step = response.error.details?.step;
|
||||
let error = new ProviderError('error', message, details);
|
||||
if (step === 'transfer') {
|
||||
error = new ProviderTransferError(message, details);
|
||||
} else if (step === 'validation') {
|
||||
error = new ProviderValidationError(message, details);
|
||||
} else if (step === 'initialization') {
|
||||
error = new ProviderInitializationError(message);
|
||||
}
|
||||
return reject(error);
|
||||
}
|
||||
resolve(response.data ?? null);
|
||||
} else {
|
||||
|
||||
@ -6,7 +6,7 @@ import { WebSocket, WebSocketServer } from 'ws';
|
||||
|
||||
import type { Handler, TransferState } from './abstract';
|
||||
import type { Protocol } from '../../../../types';
|
||||
import { ProviderTransferError } from '../../../errors/providers';
|
||||
import { ProviderError, ProviderTransferError } from '../../../errors/providers';
|
||||
import { VALID_TRANSFER_COMMANDS, ValidTransferCommand } from './constants';
|
||||
import { TransferMethod } from '../constants';
|
||||
|
||||
@ -138,16 +138,23 @@ export const handlerControllerFactory =
|
||||
},
|
||||
|
||||
respond(uuid, e, data) {
|
||||
let details = {};
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (!uuid && !e) {
|
||||
reject(new Error('Missing uuid for this message'));
|
||||
return;
|
||||
}
|
||||
|
||||
this.response = {
|
||||
uuid,
|
||||
data,
|
||||
e,
|
||||
};
|
||||
|
||||
if (e instanceof ProviderError) {
|
||||
details = e.details;
|
||||
}
|
||||
|
||||
const payload = JSON.stringify({
|
||||
uuid,
|
||||
data: data ?? null,
|
||||
@ -155,6 +162,7 @@ export const handlerControllerFactory =
|
||||
? {
|
||||
code: e?.name ?? 'ERR',
|
||||
message: e?.message,
|
||||
details,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
@ -183,10 +191,6 @@ export const handlerControllerFactory =
|
||||
const response = JSON.parse(raw.toString());
|
||||
|
||||
if (response.uuid === uuid) {
|
||||
if (response.error) {
|
||||
return reject(new Error(response.error.message));
|
||||
}
|
||||
|
||||
resolve(response.data ?? null);
|
||||
} else {
|
||||
ws.once('message', onResponse);
|
||||
|
||||
@ -18,11 +18,15 @@ export type SchemaDiffHandlerContext = {
|
||||
};
|
||||
export type SchemaDiffHandler = Middleware<SchemaDiffHandlerContext>;
|
||||
|
||||
export type AssetsBackupErrorHandlerContext = {
|
||||
export type ErrorHandlerContext = {
|
||||
ignore?: boolean;
|
||||
};
|
||||
|
||||
export type AssetsBackupErrorHandler = Middleware<AssetsBackupErrorHandlerContext>;
|
||||
export type ErrorHandler<T extends ErrorHandlerContext = ErrorHandlerContext> = Middleware<T>;
|
||||
|
||||
export type ErrorCode = 'ASSETS_DIRECTORY_ERR';
|
||||
|
||||
export type ErrorHandlers = { [k in ErrorCode]: ErrorHandler[] };
|
||||
|
||||
/**
|
||||
* Defines the capabilities and properties of the transfer engine
|
||||
|
||||
@ -151,7 +151,8 @@ module.exports = async (opts) => {
|
||||
|
||||
engine.onSchemaDiff(getDiffHandler(engine, { force: opts.force, action: 'transfer' }));
|
||||
|
||||
engine.onAssetsBackupError(
|
||||
engine.addErrorHandler(
|
||||
'ASSETS_DIRECTORY_ERR',
|
||||
getAssetsBackupHandler(engine, { force: opts.force, action: 'transfer' })
|
||||
);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user