Skip to content

Commit

Permalink
FEATURE: Use custom transformer for flow exceptions
Browse files Browse the repository at this point in the history
The t3n GraphQL package includes a transformer that bypasses Flow Framework exceptions in GraphQL error handling. The error currently lacks the exception code as part of the information. By including this code (often a timestamp), we can render custom error messages in the backend and support localization.
  • Loading branch information
markusguenther committed Nov 2, 2024
1 parent f236534 commit f100b66
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 22 deletions.
49 changes: 49 additions & 0 deletions Classes/Transform/FlowErrorTransform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Flowpack\Media\Ui\Transform;

use GraphQL\Error\Error;
use GraphQL\Executor\ExecutionResult;
use GraphQLTools\Transforms\Transform;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Log\ThrowableStorageInterface;

/**
* This transform is used to convert exceptions to errors in the GraphQL response.
* To be able to localize error messages we extend the FlowErrorTransform from the t3n.GraphQL package.
*/
class FlowErrorTransform extends \t3n\GraphQL\Transform\FlowErrorTransform
{
public function transformResult(ExecutionResult $result): ExecutionResult
{
$result->errors = array_map(function (Error $error) {
$previousError = $error->getPrevious();
if (!$previousError instanceof Error) {
$message = $this->throwableStorage->logThrowable($previousError);

if (!$this->includeExceptionMessageInOutput) {
$message = preg_replace('/.* - See also: (.+)\.txt$/s', 'Internal error ($1)', $message);
}

$errorExtendedInformation = $error->getExtensions();
$errorExtendedInformation['errorCode'] = $previousError->getCode();

return new Error(
$message,
$error->getNodes(),
$error->getSource(),
$error->getPositions(),
$error->getPath(),
$previousError,
$errorExtendedInformation
);
}

return $error;
}, $result->errors);

return $result;
}
}
1 change: 1 addition & 0 deletions Configuration/Settings.GraphQL.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ t3n:
'media-assets':
logRequests: false
context: 'Flowpack\Media\Ui\GraphQL\Context\AssetSourceContext'
errorTransform: 'Flowpack\Media\Ui\Transform\FlowErrorTransform'
schemas:
root:
typeDefs: 'resource://Flowpack.Media.Ui/Private/GraphQL/schema.root.graphql'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { onError } from '@apollo/client/link/error';

const createErrorHandler = (notify: NeosNotification) => {
const translate = (id, value = null, args = {}, packageKey = 'Flowpack.Media.Ui', source = 'Main') => {
return window.NeosCMS.I18n.translate(id, value, packageKey, source, args);
};

return onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.map((data) => {
const isInternalError = data.extensions.code === 'INTERNAL_SERVER_ERROR';

console.error(
data.extensions.code === isInternalError ? '[Internal server error]' : '[GraphQL error]',
data.path,
data
);
const isInternalError = data.extensions.category === 'internal';
let errorTitleLabel = isInternalError ? 'errors.internal.title' : 'errors.graphql.title';
let errorMessageLabel = '';
if (data.extensions.errorCode) {
errorTitleLabel = `errors.${data.extensions.errorCode}.title`;
errorMessageLabel = `errors.${data.extensions.errorCode}.message`;
}

notify.error(
data.extensions.code === isInternalError ? 'Internal server error' : 'Communication error',
data.message
translate(errorTitleLabel),
errorMessageLabel.length ? translate(errorMessageLabel) : data.message
);
});
}
Expand Down
15 changes: 15 additions & 0 deletions Resources/Private/Translations/en/Main.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,21 @@
<source>Go to next page</source>
</trans-unit>

<!-- error handling -->

<trans-unit id="errors.internal.title" xml:space="preserve" approved="yes">
<source>Internal server error</source>
</trans-unit>
<trans-unit id="errors.graphql.title" xml:space="preserve" approved="yes">
<source>Communication error</source>
</trans-unit>
<trans-unit id="errors.1603921233.title" xml:space="preserve" approved="yes">
<source>Failed to create tag</source>
</trans-unit>
<trans-unit id="errors.1603921233.message" xml:space="preserve" approved="yes">
<source>This tag is already exists. Please choose a different one.</source>
</trans-unit>

</body>
</file>
</xliff>
2 changes: 1 addition & 1 deletion Resources/Public/AssetEditor/Plugin.js

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Resources/Public/Assets/main.bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Resources/Public/Assets/main.bundle.js.map

Large diffs are not rendered by default.

0 comments on commit f100b66

Please sign in to comment.