From 7da9cca90e38dfa0e2a45e3b0a3785513ca9e06f Mon Sep 17 00:00:00 2001 From: Ian Saultz <52051793+atierian@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:49:04 -0400 Subject: [PATCH] fix(predictions): new error handling and tests (#3257) --- .../AWSTranscribeStreamingAdapter.swift | 4 +- .../AWSPredictionsService+Comprehend.swift | 4 +- .../AWSPredictionsService+Polly.swift | 18 ++- .../AWSPredictionsService+Rekognition.swift | 42 +++--- .../AWSPredictionsService+Textract.swift | 4 +- .../AWSPredictionsService+Translate.swift | 4 +- .../Predictions/AWSPredictionsService.swift | 22 +-- ...mprehend+PredictionsErrorConvertible.swift | 31 +++++ ...ng+DetectDominantLanguageOutputError.swift | 24 ---- .../Polly+PredictionsErrorConvertible.swift | 93 +++++++++++++ ...rMapping+SynthesizeSpeechOutputError.swift | 66 --------- ...ognition+PredictionsErrorConvertible.swift | 121 ++++++++++++++++ .../RekognitionCommonExceptions.swift | 75 ---------- ...eErrorMapping+DetectFacesOutputError.swift | 48 ------- ...ErrorMapping+DetectLabelsOutputError.swift | 48 ------- ...ng+DetectModerationLabelsOutputError.swift | 57 -------- ...ceErrorMapping+DetectTextOutputError.swift | 48 ------- ...ping+RekognizeCelebritiesOutputError.swift | 42 ------ ...apping+SearchFacesByImageOutputError.swift | 49 ------- .../ErrorHandling/ServiceErrorMapping.swift | 16 --- ...Textract+PredictionsErrorConvertible.swift | 130 ++++++++++++++++++ ...orMapping+AnalyzeDocumentOutputError.swift | 61 -------- ...apping+DetectDocumentTextOutputError.swift | 51 ------- .../Textract/TextractCommonException.swift | 60 -------- ...ranslate+PredictionsErrorConvertible.swift | 52 +++++++ ...rrorMapping+TranslateTextOutputError.swift | 32 ----- .../PollyErrorMappingTestCase.swift | 34 +++-- .../TextractErrorMappingTestCase.swift | 31 +++-- .../Service/MockRekognitionBehavior.swift | 9 ++ .../Mocks/Service/MockTranslateBehavior.swift | 1 + 30 files changed, 524 insertions(+), 753 deletions(-) create mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend+PredictionsErrorConvertible.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend/ServiceErrorMapping+DetectDominantLanguageOutputError.swift create mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly+PredictionsErrorConvertible.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly/ServiceErrorMapping+SynthesizeSpeechOutputError.swift create mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition+PredictionsErrorConvertible.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/RekognitionCommonExceptions.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectFacesOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectLabelsOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectModerationLabelsOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectTextOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+RekognizeCelebritiesOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+SearchFacesByImageOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/ServiceErrorMapping.swift create mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract+PredictionsErrorConvertible.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+AnalyzeDocumentOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+DetectDocumentTextOutputError.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/TextractCommonException.swift create mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate+PredictionsErrorConvertible.swift delete mode 100644 AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate/ServiceErrorMapping+TranslateTextOutputError.swift diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Dependency/AWSTranscribeStreamingAdapter.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Dependency/AWSTranscribeStreamingAdapter.swift index ada2ff5135..97aed80ff8 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Dependency/AWSTranscribeStreamingAdapter.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Dependency/AWSTranscribeStreamingAdapter.swift @@ -22,10 +22,10 @@ class AWSTranscribeStreamingAdapter: AWSTranscribeStreamingBehavior { let mediaSampleRateHertz: Int } - let credentialsProvider: CredentialsProvider + let credentialsProvider: CredentialsProviding let region: String - init(credentialsProvider: CredentialsProvider, region: String) { + init(credentialsProvider: CredentialsProviding, region: String) { self.credentialsProvider = credentialsProvider self.region = region } diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Comprehend.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Comprehend.swift index ed04516078..d44e7729f3 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Comprehend.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Comprehend.swift @@ -38,8 +38,8 @@ extension AWSPredictionsService: AWSComprehendServiceBehavior { .map(Predictions.Language.init(locale:)) ?? .undetermined return (predictionsLanguage, dominantLanguage?.score.map(Double.init)) - } catch let error as DetectDominantLanguageOutputError { - throw ServiceErrorMapping.detectDominantLanguage.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Polly.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Polly.swift index ef070be2e2..507e968448 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Polly.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Polly.swift @@ -34,12 +34,18 @@ extension AWSPredictionsService: AWSPollyServiceBehavior { ) } - let textToSpeechResult = Predictions.Convert.TextToSpeech.Result( - audioData: speech.toBytes().getData() - ) - return textToSpeechResult - } catch let error as SynthesizeSpeechOutputError { - throw ServiceErrorMapping.synthesizeSpeech.map(error) + switch speech { + case .data(let data?): + let textToSpeechResult = Predictions.Convert.TextToSpeech.Result( + audioData: data + ) + return textToSpeechResult + // TODO: figure out what to throw here + default: throw PredictionsError.unknown("Missing respose", "", nil) + } + + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Rekognition.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Rekognition.swift index 8a67da343b..0846015c48 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Rekognition.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Rekognition.swift @@ -24,8 +24,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let labelsResult = try await detectLabels(image: imageData) let newLabels = IdentifyLabelsResultTransformers.processLabels(labelsResult.labels ?? []) return Predictions.Identify.Labels.Result(labels: newLabels, unsafeContent: nil) - } catch let error as DetectLabelsOutputError { - throw ServiceErrorMapping.detectLabels.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -35,8 +35,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let unsafeContent = !moderationLabels.isEmpty let labels = IdentifyLabelsResultTransformers.processModerationLabels(moderationLabels) return Predictions.Identify.Labels.Result(labels: labels, unsafeContent: unsafeContent) - } catch let error as DetectModerationLabelsOutputError { - throw ServiceErrorMapping.detectModerationLabels.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) @@ -67,8 +67,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let newCelebs = IdentifyCelebritiesResultTransformers.processCelebs(celebrities) return Predictions.Identify.Celebrities.Result(celebrities: newCelebs) - } catch let error as RecognizeCelebritiesOutputError { - throw ServiceErrorMapping.detectCelebrities.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -94,8 +94,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { .searchFacesByImage(input: input).faceMatches ?? [] let faceMatches = IdentifyEntitiesResultTransformers.processCollectionFaces(faces) return Predictions.Identify.EntityMatches.Result(entities: faceMatches) - } catch let error as SearchFacesByImageOutputError { - throw ServiceErrorMapping.searchFacesByImage.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -112,8 +112,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let faces = try await awsRekognition.detectFaces(input: input).faceDetails ?? [] let newFaces = IdentifyEntitiesResultTransformers.processFaces(faces) return Predictions.Identify.Entities.Result(entities: newFaces) - } catch let error as DetectFacesOutputError { - throw ServiceErrorMapping.detectFaces.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unknownServiceError(error) } @@ -128,8 +128,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { do { textResult = try await awsRekognition.detectText(input: request) - } catch let error as DetectTextOutputError { - throw ServiceErrorMapping.detectText.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -147,8 +147,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let documentTextResult: DetectDocumentTextOutputResponse do { documentTextResult = try await detectDocumentText(image: imageData) - } catch let error as DetectDocumentTextOutputError { - throw ServiceErrorMapping.detectDocumentText.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -200,8 +200,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let textResult: DetectTextOutputResponse do { textResult = try await awsRekognition.detectText(input: request) - } catch let error as DetectTextOutputError { - throw ServiceErrorMapping.detectText.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -220,8 +220,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let documentTextResult: DetectDocumentTextOutputResponse do { documentTextResult = try await detectDocumentText(image: imageData) - } catch let error as DetectDocumentTextOutputError { - throw ServiceErrorMapping.detectDocumentText.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } @@ -275,10 +275,8 @@ extension AWSPredictionsService: AWSRekognitionServiceBehavior { let moderationLabels = moderationLabelsOutput.moderationLabels ?? [] let unsafeContent = !moderationLabels.isEmpty return Predictions.Identify.Labels.Result(labels: allLabels, unsafeContent: unsafeContent) - } catch let error as DetectLabelsOutputError { - throw ServiceErrorMapping.detectLabels.map(error) - } catch let error as DetectModerationLabelsOutputError { - throw ServiceErrorMapping.detectModerationLabels.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Textract.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Textract.swift index ec1e1b70ce..fd882740d9 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Textract.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Textract.swift @@ -41,8 +41,8 @@ extension AWSPredictionsService: AWSTextractServiceBehavior { let documentResult: AnalyzeDocumentOutputResponse do { documentResult = try await awsTextract.analyzeDocument(input: request) - } catch let error as AnalyzeDocumentOutputError { - throw ServiceErrorMapping.analyzeDocument.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Translate.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Translate.swift index a09318f4ed..81d3a47d20 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Translate.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService+Translate.swift @@ -35,8 +35,8 @@ extension AWSPredictionsService: AWSTranslateServiceBehavior { let textTranslateResult: TranslateTextOutputResponse do { textTranslateResult = try await awsTranslate.translateText(input: request) - } catch let error as TranslateTextOutputError { - throw ServiceErrorMapping.translateText.map(error) + } catch let error as PredictionsErrorConvertible { + throw error.predictionsError } catch { throw PredictionsError.unexpectedServiceErrorType(error) } diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService.swift index 08a3336789..9d87be3f5f 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Service/Predictions/AWSPredictionsService.swift @@ -31,12 +31,12 @@ class AWSPredictionsService { convenience init( configuration: PredictionsPluginConfiguration, - credentialsProvider: CredentialsProvider, + credentialsProvider: CredentialsProviding, identifier: String ) throws { let translateClientConfiguration = try TranslateClient.TranslateClientConfiguration( - credentialsProvider: credentialsProvider, - region: configuration.convert.region + region: configuration.convert.region, + credentialsProvider: credentialsProvider ) #if os(iOS) || os(macOS) // no-op #else @@ -47,8 +47,8 @@ class AWSPredictionsService { let awsTranslateClient = TranslateClient(config: translateClientConfiguration) let pollyClientConfiguration = try PollyClient.PollyClientConfiguration( - credentialsProvider: credentialsProvider, - region: configuration.convert.region + region: configuration.convert.region, + credentialsProvider: credentialsProvider ) #if os(iOS) || os(macOS) // no-op #else @@ -59,8 +59,8 @@ class AWSPredictionsService { let awsPollyClient = PollyClient(config: pollyClientConfiguration) let comprehendClientConfiguration = try ComprehendClient.ComprehendClientConfiguration( - credentialsProvider: credentialsProvider, - region: configuration.convert.region + region: configuration.convert.region, + credentialsProvider: credentialsProvider ) #if os(iOS) || os(macOS) // no-op #else @@ -71,8 +71,8 @@ class AWSPredictionsService { let awsComprehendClient = ComprehendClient(config: comprehendClientConfiguration) let rekognitionClientConfiguration = try RekognitionClient.RekognitionClientConfiguration( - credentialsProvider: credentialsProvider, - region: configuration.identify.region + region: configuration.identify.region, + credentialsProvider: credentialsProvider ) #if os(iOS) || os(macOS) // no-op #else @@ -83,8 +83,8 @@ class AWSPredictionsService { let awsRekognitionClient = RekognitionClient(config: rekognitionClientConfiguration) let textractClientConfiguration = try TextractClient.TextractClientConfiguration( - credentialsProvider: credentialsProvider, - region: configuration.identify.region + region: configuration.identify.region, + credentialsProvider: credentialsProvider ) #if os(iOS) || os(macOS) // no-op #else diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend+PredictionsErrorConvertible.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend+PredictionsErrorConvertible.swift new file mode 100644 index 0000000000..d1ad4a9911 --- /dev/null +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend+PredictionsErrorConvertible.swift @@ -0,0 +1,31 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import AWSComprehend +import Amplify + +protocol PredictionsErrorConvertible { + var predictionsError: PredictionsError { get } +} + +extension AWSComprehend.InternalServerException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.internalServerError) + } +} + +extension AWSComprehend.InvalidRequestException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.invalidRequest) + } +} + +extension AWSComprehend.TextSizeLimitExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.textSizeLimitExceeded) + } +} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend/ServiceErrorMapping+DetectDominantLanguageOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend/ServiceErrorMapping+DetectDominantLanguageOutputError.swift deleted file mode 100644 index de5b76f695..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Comprehend/ServiceErrorMapping+DetectDominantLanguageOutputError.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSComprehend -import Amplify - -extension ServiceErrorMapping where T == DetectDominantLanguageOutputError { - static let detectDominantLanguage: Self = .init { error in - switch error { - case .internalServerException: - return PredictionsError.service(.internalServerError) - case .invalidRequestException: - return PredictionsError.service(.invalidRequest) - case .textSizeLimitExceededException: - return PredictionsError.service(.textSizeLimitExceeded) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly+PredictionsErrorConvertible.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly+PredictionsErrorConvertible.swift new file mode 100644 index 0000000000..78796e95ce --- /dev/null +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly+PredictionsErrorConvertible.swift @@ -0,0 +1,93 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import AWSPolly +import Amplify + +extension AWSPolly.InvalidSampleRateException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.invalidSampleRate) + } +} + +extension AWSPolly.LanguageNotSupportedException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.unsupportedLanguage) + } +} + +extension AWSPolly.ServiceFailureException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.internalServerError) + } +} + +extension AWSPolly.TextLengthExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.textSizeLimitExceeded) + } +} + +extension AWSPolly.LexiconNotFoundException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "Amazon Polly can't find the specified lexicon. This could be caused by a lexicon that is missing, its name is misspelled or specifying a lexicon that is in a different region.", + recoverySuggestion: "Verify that the lexicon exists, is in the region (see ListLexicons) and that you spelled its name is spelled correctly. Then try again.", + underlyingError: self + ) + ) + } +} + +extension AWSPolly.MarksNotSupportedForFormatException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "Speech marks are not supported for the OutputFormat selected.", + recoverySuggestion: "Speech marks are only available for content in json format.", + underlyingError: self + ) + ) + } +} + +extension AWSPolly.InvalidSsmlException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The SSML you provided is invalid.", + recoverySuggestion: "Verify the SSML syntax, spelling of tags and values, and then try again.", + underlyingError: self + ) + ) + } +} + +extension AWSPolly.SsmlMarksNotSupportedForTextTypeException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "SSML speech marks are not supported for plain text-type input.", + recoverySuggestion: "", + underlyingError: self + ) + ) + } +} + +extension AWSPolly.EngineNotSupportedException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "This engine is not compatible with the voice that you have designated.", + recoverySuggestion: "Choose a new voice that is compatible with the engine or change the engine and restart the operation.", + underlyingError: self + ) + ) + } +} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly/ServiceErrorMapping+SynthesizeSpeechOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly/ServiceErrorMapping+SynthesizeSpeechOutputError.swift deleted file mode 100644 index 60688eb7cd..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Polly/ServiceErrorMapping+SynthesizeSpeechOutputError.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSPolly -import Amplify - -extension ServiceErrorMapping where T == SynthesizeSpeechOutputError { - static let synthesizeSpeech: Self = .init { error in - switch error { - case .invalidSampleRateException: - return PredictionsError.service(.invalidSampleRate) - case .languageNotSupportedException: - return PredictionsError.service(.unsupportedLanguage) - case .serviceFailureException: - return PredictionsError.service(.internalServerError) - case .textLengthExceededException: - return PredictionsError.service(.textSizeLimitExceeded) - case .lexiconNotFoundException: - return PredictionsError.service( - .init( - description: "Amazon Polly can't find the specified lexicon. This could be caused by a lexicon that is missing, its name is misspelled or specifying a lexicon that is in a different region.", - recoverySuggestion: "Verify that the lexicon exists, is in the region (see ListLexicons) and that you spelled its name is spelled correctly. Then try again.", - underlyingError: error - ) - ) - case .marksNotSupportedForFormatException: - return PredictionsError.service( - .init( - description: "Speech marks are not supported for the OutputFormat selected.", - recoverySuggestion: "Speech marks are only available for content in json format.", - underlyingError: error - ) - ) - case .invalidSsmlException: - return PredictionsError.service( - .init( - description: "The SSML you provided is invalid.", - recoverySuggestion: "Verify the SSML syntax, spelling of tags and values, and then try again.", - underlyingError: error - ) - ) - case .ssmlMarksNotSupportedForTextTypeException: - return PredictionsError.service( - .init( - description: "SSML speech marks are not supported for plain text-type input.", - recoverySuggestion: "", - underlyingError: error - ) - ) - case .engineNotSupportedException: - return PredictionsError.service( - .init( - description: "This engine is not compatible with the voice that you have designated.", - recoverySuggestion: "Choose a new voice that is compatible with the engine or change the engine and restart the operation.", - underlyingError: error - ) - ) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition+PredictionsErrorConvertible.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition+PredictionsErrorConvertible.swift new file mode 100644 index 0000000000..464060e9da --- /dev/null +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition+PredictionsErrorConvertible.swift @@ -0,0 +1,121 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import AWSRekognition +import Amplify +import ClientRuntime + + +extension AWSRekognition.HumanLoopQuotaExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The number of in-progress human reviews you have has exceeded the number allowed.", + recoverySuggestion: "Try again later.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSRekognition.ResourceNotFoundException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.resourceNotFound) + } +} + +extension AWSRekognition.ThrottlingException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.throttling) + } +} + +extension AWSRekognition.InternalServerError: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.internalServerError) + } +} + +extension AWSRekognition.AccessDeniedException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.accessDenied) + } +} + +extension AWSRekognition.ImageTooLargeException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The image you sent was too large.", + recoverySuggestion: "Try downsizing the image and sending it again.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSRekognition.InvalidImageFormatException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The provided image format isn't supported.", + recoverySuggestion: "Use a supported image format (.JPEG and .PNG) and try again.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSRekognition.InvalidParameterException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "An input parameter violated a constraint.", + recoverySuggestion: "Validate your parameters before calling the API operation again.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSRekognition.InvalidS3ObjectException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The number of requests exceeded your throughput limit.", + recoverySuggestion: """ + Decrease the number of calls you are making until it is below the limit for your region. + Check the limits here: + https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_rekognition + """, + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSRekognition.ProvisionedThroughputExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The number of requests exceeded your throughput limit.", + recoverySuggestion: """ + Decrease the number of calls you are making until it is below the limit for your region. + Check the limits here: + https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_rekognition + """, + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/RekognitionCommonExceptions.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/RekognitionCommonExceptions.swift deleted file mode 100644 index 3f7933a26c..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/RekognitionCommonExceptions.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify -import ClientRuntime - -enum RekognitionCommonExceptions { - static func imageTooLarge(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - return .service( - .init( - description: "The image you sent was too large.", - recoverySuggestion: "Try downsizing the image and sending it again.", - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func invalidImageFormat(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - return .service( - .init( - description: "The provided image format isn't supported.", - recoverySuggestion: "Use a supported image format (.JPEG and .PNG) and try again.", - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func invalidParameter(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - return .service( - .init( - description: "An input parameter violated a constraint.", - recoverySuggestion: "Validate your parameters before calling the API operation again.", - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func invalidS3Object(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - .service( - .init( - description: "The number of requests exceeded your throughput limit.", - recoverySuggestion: """ - Decrease the number of calls you are making until it is below the limit for your region. - Check the limits here: - https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_rekognition - """, - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func provisionedThroughputExceeded(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - .service( - .init( - description: "The number of requests exceeded your throughput limit.", - recoverySuggestion: """ - Decrease the number of calls you are making until it is below the limit for your region. - Check the limits here: - https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_rekognition - """, - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectFacesOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectFacesOutputError.swift deleted file mode 100644 index 4b79ce1683..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectFacesOutputError.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify - -extension ServiceErrorMapping where T == DetectFacesOutputError { - static let detectFaces: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .imageTooLargeException(let imageTooLargeException): - return RekognitionCommonExceptions.imageTooLarge( - error, statusCode: imageTooLargeException._statusCode - ) - case .internalServerError: - return PredictionsError.service(.internalServerError) - case .invalidImageFormatException(let invalidImageFormatException): - return RekognitionCommonExceptions.invalidImageFormat( - error, - statusCode: invalidImageFormatException._statusCode - ) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException: - return PredictionsError.service(.throttling) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectLabelsOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectLabelsOutputError.swift deleted file mode 100644 index be00516c14..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectLabelsOutputError.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify - -extension ServiceErrorMapping where T == DetectLabelsOutputError { - static let detectLabels: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .imageTooLargeException(let imageTooLargeException): - return RekognitionCommonExceptions.imageTooLarge( - error, statusCode: imageTooLargeException._statusCode - ) - case .internalServerError: - return PredictionsError.service(.internalServerError) - case .invalidImageFormatException(let invalidImageFormatException): - return RekognitionCommonExceptions.invalidImageFormat( - error, - statusCode: invalidImageFormatException._statusCode - ) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException: - return PredictionsError.service(.throttling) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectModerationLabelsOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectModerationLabelsOutputError.swift deleted file mode 100644 index 37d855ae67..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectModerationLabelsOutputError.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify - -extension ServiceErrorMapping where T == DetectModerationLabelsOutputError { - static let detectModerationLabels: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .imageTooLargeException(let imageTooLargeException): - return RekognitionCommonExceptions.imageTooLarge( - error, statusCode: imageTooLargeException._statusCode - ) - case .internalServerError: - return PredictionsError.service(.internalServerError) - case .invalidImageFormatException(let invalidImageFormatException): - return RekognitionCommonExceptions.invalidImageFormat( - error, - statusCode: invalidImageFormatException._statusCode - ) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException: - return PredictionsError.service(.throttling) - case .humanLoopQuotaExceededException(let humanLoopQuotaExceededException): - return .service( - .init( - description: "", - recoverySuggestion: "", - httpStatusCode: humanLoopQuotaExceededException._statusCode?.rawValue, - underlyingError: error - ) - ) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectTextOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectTextOutputError.swift deleted file mode 100644 index 0e76a4a4b9..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+DetectTextOutputError.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify - -extension ServiceErrorMapping where T == DetectTextOutputError { - static let detectText: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .imageTooLargeException(let imageTooLargeException): - return RekognitionCommonExceptions.imageTooLarge( - error, statusCode: imageTooLargeException._statusCode - ) - case .internalServerError: - return PredictionsError.service(.internalServerError) - case .invalidImageFormatException(let invalidImageFormatException): - return RekognitionCommonExceptions.invalidImageFormat( - error, - statusCode: invalidImageFormatException._statusCode - ) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException: - return PredictionsError.service(.throttling) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+RekognizeCelebritiesOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+RekognizeCelebritiesOutputError.swift deleted file mode 100644 index 0faa619191..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+RekognizeCelebritiesOutputError.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify - -extension ServiceErrorMapping where T == RecognizeCelebritiesOutputError { - static let detectCelebrities: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .imageTooLargeException(let imageTooLargeException): - return RekognitionCommonExceptions.imageTooLarge(error, statusCode: imageTooLargeException._statusCode) - case .internalServerError(let internalServerError): - return PredictionsError.service(.internalServerError) - case .invalidImageFormatException(let invalidImageFormatException): - return RekognitionCommonExceptions.invalidImageFormat( - error, statusCode: invalidImageFormatException._statusCode - ) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException(let throttlingException): - return PredictionsError.service(.throttling) - case .unknown(let unknown): - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+SearchFacesByImageOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+SearchFacesByImageOutputError.swift deleted file mode 100644 index 9205f15493..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Rekognition/ServiceErrorMapping+SearchFacesByImageOutputError.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSRekognition -import Amplify - -extension ServiceErrorMapping where T == SearchFacesByImageOutputError { - static let searchFacesByImage: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .imageTooLargeException(let imageTooLargeException): - return RekognitionCommonExceptions.imageTooLarge( - error, statusCode: imageTooLargeException._statusCode - ) - case .internalServerError(let internalServerError): - return PredictionsError.service(.internalServerError) - case .invalidImageFormatException(let invalidImageFormatException): - return RekognitionCommonExceptions.invalidImageFormat( - error, statusCode: invalidImageFormatException._statusCode - ) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .resourceNotFoundException(let resourceNotFoundException): - return PredictionsError.service(.resourceNotFound) - case .throttlingException(let throttlingException): - return PredictionsError.service(.throttling) - case .unknown(let unknownAWSHttpServiceError): - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/ServiceErrorMapping.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/ServiceErrorMapping.swift deleted file mode 100644 index 5fec8447cf..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/ServiceErrorMapping.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import Amplify - -struct ServiceErrorMapping { - let map: (T) -> PredictionsError - - static func map(_ error: T, with rule: ServiceErrorMapping) -> PredictionsError { - rule.map(error) - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract+PredictionsErrorConvertible.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract+PredictionsErrorConvertible.swift new file mode 100644 index 0000000000..9aa5908460 --- /dev/null +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract+PredictionsErrorConvertible.swift @@ -0,0 +1,130 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import AWSTextract +import Amplify +import ClientRuntime + + +extension AWSTextract.HumanLoopQuotaExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The number of in-progress human reviews you have has exceeded the number allowed.", + recoverySuggestion: "Try again later.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSTextract.ThrottlingException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.throttling) + } +} + +extension AWSTextract.InternalServerError: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.internalServerError) + } +} + +extension AWSTextract.AccessDeniedException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.accessDenied) + } +} + +extension AWSTextract.InvalidParameterException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "An input parameter violated a constraint.", + recoverySuggestion: "Validate your parameters before calling the API operation again.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSTextract.InvalidS3ObjectException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The number of requests exceeded your throughput limit.", + recoverySuggestion: """ + Decrease the number of calls you are making until it is below the limit for your region. + Check the limits here: + https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_rekognition + """, + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSTextract.ProvisionedThroughputExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The number of requests exceeded your throughput limit.", + recoverySuggestion: """ + Decrease the number of calls you are making until it is below the limit for your region. + Check the limits here: + https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_rekognition + """, + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + + +extension AWSTextract.BadDocumentException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The image sent over was corrupt or malformed.", + recoverySuggestion: "Please double check the image sent over and try again.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + +extension AWSTextract.DocumentTooLargeException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The image sent over was too large.", + recoverySuggestion: "Please decrease the size of the image sent over and try again.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} + + +extension AWSTextract.UnsupportedDocumentException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service( + .init( + description: "The document type sent over is unsupported", + recoverySuggestion: "The formats supported are PNG or JPEG format.", + httpStatusCode: httpResponse.statusCode.rawValue, + underlyingError: self + ) + ) + } +} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+AnalyzeDocumentOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+AnalyzeDocumentOutputError.swift deleted file mode 100644 index 6312a60644..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+AnalyzeDocumentOutputError.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSTextract -import Amplify -import ClientRuntime - -extension ServiceErrorMapping where T == AnalyzeDocumentOutputError { - static let analyzeDocument: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .badDocumentException(let badDocumentException): - return TextractCommonException.badDocument( - error, statusCode: badDocumentException._statusCode - ) - case .documentTooLargeException(let documentTooLargeException): - return TextractCommonException.documentTooLarge( - error, statusCode: documentTooLargeException._statusCode - ) - case .humanLoopQuotaExceededException(let humanLoopQuotaExceededException): - return .service( - .init( - description: "", - recoverySuggestion: "", - httpStatusCode: humanLoopQuotaExceededException._statusCode?.rawValue, - underlyingError: error - ) - ) - case .internalServerError: - return PredictionsError.service(.internalServerError) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return TextractCommonException.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException: - return PredictionsError.service(.throttling) - case .unsupportedDocumentException(let unsupportedDocumentException): - return TextractCommonException.unsupportedDocument( - error, statusCode: unsupportedDocumentException._statusCode - ) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+DetectDocumentTextOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+DetectDocumentTextOutputError.swift deleted file mode 100644 index d6d48521d9..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/ServiceErrorMapping+DetectDocumentTextOutputError.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSTextract -import Amplify - -extension ServiceErrorMapping where T == DetectDocumentTextOutputError { - static let detectDocumentText: Self = .init { error in - switch error { - case .accessDeniedException(let accessDeniedException): - return PredictionsError.service(.accessDenied) - case .internalServerError: - return PredictionsError.service(.internalServerError) - case .invalidParameterException(let invalidParameterException): - return RekognitionCommonExceptions.invalidParameter( - error, - statusCode: invalidParameterException._statusCode - ) - case .invalidS3ObjectException(let invalidS3ObjectException): - return RekognitionCommonExceptions.invalidS3Object( - error, - statusCode: invalidS3ObjectException._statusCode - ) - case .provisionedThroughputExceededException(let provisionedThroughputExceededException): - return RekognitionCommonExceptions.provisionedThroughputExceeded( - error, - statusCode: provisionedThroughputExceededException._statusCode - ) - case .throttlingException: - return PredictionsError.service(.throttling) - case .unknown: - return PredictionsError.unknownServiceError(error) - case .badDocumentException(let badDocumentException): - return TextractCommonException.badDocument( - error, statusCode: badDocumentException._statusCode - ) - case .documentTooLargeException(let documentTooLargeException): - return TextractCommonException.documentTooLarge( - error, statusCode: documentTooLargeException._statusCode - ) - case .unsupportedDocumentException(let unsupportedDocumentException): - return TextractCommonException.unsupportedDocument( - error, statusCode: unsupportedDocumentException._statusCode - ) - } - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/TextractCommonException.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/TextractCommonException.swift deleted file mode 100644 index 415284f354..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Textract/TextractCommonException.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSTextract -import Amplify -import ClientRuntime - -enum TextractCommonException { - static func badDocument(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - return .service( - .init( - description: "The image sent over was corrupt or malformed.", - recoverySuggestion: "Please double check the image sent over and try again.", - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func documentTooLarge(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - return .service( - .init( - description: "The image sent over was too large.", - recoverySuggestion: "Please decrease the size of the image sent over and try again.", - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func unsupportedDocument(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - return .service( - .init( - description: "The document type sent over is unsupported", - recoverySuggestion: "The formats supported are PNG or JPEG format.", - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } - - static func provisionedThroughputExceeded(_ error: Error, statusCode: HttpStatusCode?) -> PredictionsError { - .service( - .init( - description: "The number of requests exceeded your throughput limit.", - recoverySuggestion: """ - Decrease the number of calls you are making until it is below the limit for your region. - Check the limits here: - https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_textract - """, - httpStatusCode: statusCode?.rawValue, - underlyingError: error - ) - ) - } -} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate+PredictionsErrorConvertible.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate+PredictionsErrorConvertible.swift new file mode 100644 index 0000000000..aeb5897aac --- /dev/null +++ b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate+PredictionsErrorConvertible.swift @@ -0,0 +1,52 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import AWSTranslate +import Amplify + +extension AWSTranslate.DetectedLanguageLowConfidenceException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.detectedLanguageLowConfidence) + } +} + +extension AWSTranslate.InternalServerException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.internalServerError) + } +} + + +extension AWSTranslate.InvalidRequestException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.invalidRequest) + } +} + +extension AWSTranslate.ResourceNotFoundException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.resourceNotFound) + } +} + +extension AWSTranslate.TextSizeLimitExceededException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.textSizeLimitExceeded) + } +} + +extension AWSTranslate.TooManyRequestsException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.throttling) + } +} + +extension AWSTranslate.UnsupportedLanguagePairException: PredictionsErrorConvertible { + var predictionsError: PredictionsError { + .service(.unsupportedLanguagePair) + } +} diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate/ServiceErrorMapping+TranslateTextOutputError.swift b/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate/ServiceErrorMapping+TranslateTextOutputError.swift deleted file mode 100644 index 15706934c4..0000000000 --- a/AmplifyPlugins/Predictions/AWSPredictionsPlugin/Support/Internal/ErrorHandling/Translate/ServiceErrorMapping+TranslateTextOutputError.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import AWSTranslate -import Amplify - -extension ServiceErrorMapping where T == TranslateTextOutputError { - static let translateText: Self = .init { error in - switch error { - case .detectedLanguageLowConfidenceException(let detectedLanguageLowConfidenceException): - return PredictionsError.service(.detectedLanguageLowConfidence) - case .internalServerException(let internalServerException): - return PredictionsError.service(.internalServerError) - case .invalidRequestException(let invalidRequestException): - return PredictionsError.service(.invalidRequest) - case .resourceNotFoundException, .serviceUnavailableException: - return PredictionsError.service(.resourceNotFound) - case .textSizeLimitExceededException(let textSizeLimitExceededException): - return PredictionsError.service(.textSizeLimitExceeded) - case .tooManyRequestsException(let tooManyRequestsException): - return PredictionsError.service(.throttling) - case .unsupportedLanguagePairException(let unsupportedLanguagePairException): - return PredictionsError.service(.unsupportedLanguagePair) - case .unknown: - return PredictionsError.unknownServiceError(error) - } - } -} diff --git a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/PollyErrorMappingTestCase.swift b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/PollyErrorMappingTestCase.swift index c9576ca6a5..62133dac70 100644 --- a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/PollyErrorMappingTestCase.swift +++ b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/PollyErrorMappingTestCase.swift @@ -12,37 +12,41 @@ import Amplify final class PollyErrorMappingTestCase: XCTestCase { private func assertCatchVariations( - for sdkError: SynthesizeSpeechOutputError, + for sdkError: Error, expecting expectedServiceError: PredictionsError.ServiceError, label: String ) { - let predictionsError = ServiceErrorMapping.synthesizeSpeech.map(sdkError) let unexpected: (Error) -> String = { "Expected PredictionsError.service(.\(label), received \($0)" } + // catch variation 1. - do { throw predictionsError } - catch PredictionsError.service(expectedServiceError) {} + do { throw sdkError } + catch let error as PredictionsErrorConvertible { + guard case .service(expectedServiceError) = error.predictionsError else { + return XCTFail(unexpected(error.predictionsError)) + } + } catch { XCTFail(unexpected(error)) } // catch variation 2. - do { throw predictionsError } - catch let error as PredictionsError { - guard case .service(expectedServiceError) = error else { - return XCTFail(unexpected(error)) + do { throw sdkError } + catch let error as PredictionsErrorConvertible { + guard case .service(expectedServiceError) = error.predictionsError else { + return XCTFail(unexpected(error.predictionsError)) } } catch { XCTFail(unexpected(error)) } // catch variation 3. - do { throw predictionsError } + do { throw sdkError } catch { - guard let error = error as? PredictionsError, - case .service(expectedServiceError) = error + guard let error = error as? PredictionsErrorConvertible, + case .service(expectedServiceError) = error.predictionsError else { return XCTFail(unexpected(error)) } @@ -51,7 +55,7 @@ final class PollyErrorMappingTestCase: XCTestCase { func testSynthesizeSpeech_invalidSampleRateException() throws { assertCatchVariations( - for: .invalidSampleRateException(.init()), + for: InvalidSampleRateException(), expecting: .invalidSampleRate, label: "invalidSampleRate" ) @@ -59,7 +63,7 @@ final class PollyErrorMappingTestCase: XCTestCase { func testSynthesizeSpeech_languageNotSupportedException() throws { assertCatchVariations( - for: .languageNotSupportedException(.init()), + for: LanguageNotSupportedException(), expecting: .unsupportedLanguage, label: "unsupportedLanguage" ) @@ -67,7 +71,7 @@ final class PollyErrorMappingTestCase: XCTestCase { func testSynthesizeSpeech_serviceFailureException() throws { assertCatchVariations( - for: .serviceFailureException(.init()), + for: ServiceFailureException(), expecting: .internalServerError, label: "internalServerError" ) @@ -75,7 +79,7 @@ final class PollyErrorMappingTestCase: XCTestCase { func testSynthesizeSpeech_textLengthExceededException() throws { assertCatchVariations( - for: .textLengthExceededException(.init()), + for: TextLengthExceededException(), expecting: .textSizeLimitExceeded, label: "textSizeLimitExceeded" ) diff --git a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/TextractErrorMappingTestCase.swift b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/TextractErrorMappingTestCase.swift index bafe9a75ce..526b3d37ae 100644 --- a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/TextractErrorMappingTestCase.swift +++ b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/ErrorMapping/TextractErrorMappingTestCase.swift @@ -12,37 +12,40 @@ import Amplify final class TextractErrorMappingTestCase: XCTestCase { private func assertCatchVariations( - for sdkError: AnalyzeDocumentOutputError, + for sdkError: Error, expecting expectedServiceError: PredictionsError.ServiceError, label: String ) { - let predictionsError = ServiceErrorMapping.analyzeDocument.map(sdkError) let unexpected: (Error) -> String = { "Expected PredictionsError.service(.\(label), received \($0)" } // catch variation 1. - do { throw predictionsError } - catch PredictionsError.service(expectedServiceError) {} + do { throw sdkError } + catch let error as PredictionsErrorConvertible { + guard case .service(expectedServiceError) = error.predictionsError else { + return XCTFail(unexpected(error.predictionsError)) + } + } catch { XCTFail(unexpected(error)) } // catch variation 2. - do { throw predictionsError } - catch let error as PredictionsError { - guard case .service(expectedServiceError) = error else { - return XCTFail(unexpected(error)) + do { throw sdkError } + catch let error as PredictionsErrorConvertible { + guard case .service(expectedServiceError) = error.predictionsError else { + return XCTFail(unexpected(error.predictionsError)) } } catch { XCTFail(unexpected(error)) } // catch variation 3. - do { throw predictionsError } + do { throw sdkError } catch { - guard let error = error as? PredictionsError, - case .service(expectedServiceError) = error + guard let error = error as? PredictionsErrorConvertible, + case .service(expectedServiceError) = error.predictionsError else { return XCTFail(unexpected(error)) } @@ -51,7 +54,7 @@ final class TextractErrorMappingTestCase: XCTestCase { func testAnalyzeDocument_internalServerError() throws { assertCatchVariations( - for: .internalServerError(.init()), + for: InternalServerError(), expecting: .internalServerError, label: "internalServerError" ) @@ -59,7 +62,7 @@ final class TextractErrorMappingTestCase: XCTestCase { func testAnalyzeDocument_accessDeniedException() throws { assertCatchVariations( - for: .accessDeniedException(.init()), + for: AccessDeniedException(), expecting: .accessDenied, label: "accessDenied" ) @@ -67,7 +70,7 @@ final class TextractErrorMappingTestCase: XCTestCase { func testAnalyzeDocument_throttlingException() throws { assertCatchVariations( - for: .throttlingException(.init()), + for: ThrottlingException(), expecting: .throttling, label: "throttling" ) diff --git a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockRekognitionBehavior.swift b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockRekognitionBehavior.swift index 9dcd814c82..ffcb4cdfb7 100644 --- a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockRekognitionBehavior.swift +++ b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockRekognitionBehavior.swift @@ -112,4 +112,13 @@ extension MockRekognitionBehavior { func untagResource(input: AWSRekognition.UntagResourceInput) async throws -> AWSRekognition.UntagResourceOutputResponse { fatalError() } func updateDatasetEntries(input: AWSRekognition.UpdateDatasetEntriesInput) async throws -> AWSRekognition.UpdateDatasetEntriesOutputResponse { fatalError() } func updateStreamProcessor(input: AWSRekognition.UpdateStreamProcessorInput) async throws -> AWSRekognition.UpdateStreamProcessorOutputResponse { fatalError() } + func associateFaces(input: AWSRekognition.AssociateFacesInput) async throws -> AWSRekognition.AssociateFacesOutputResponse { fatalError() } + func createFaceLivenessSession(input: AWSRekognition.CreateFaceLivenessSessionInput) async throws -> AWSRekognition.CreateFaceLivenessSessionOutputResponse { fatalError() } + func createUser(input: AWSRekognition.CreateUserInput) async throws -> AWSRekognition.CreateUserOutputResponse { fatalError() } + func deleteUser(input: AWSRekognition.DeleteUserInput) async throws -> AWSRekognition.DeleteUserOutputResponse { fatalError() } + func disassociateFaces(input: AWSRekognition.DisassociateFacesInput) async throws -> AWSRekognition.DisassociateFacesOutputResponse { fatalError() } + func getFaceLivenessSessionResults(input: AWSRekognition.GetFaceLivenessSessionResultsInput) async throws -> AWSRekognition.GetFaceLivenessSessionResultsOutputResponse { fatalError() } + func listUsers(input: AWSRekognition.ListUsersInput) async throws -> AWSRekognition.ListUsersOutputResponse { fatalError() } + func searchUsers(input: AWSRekognition.SearchUsersInput) async throws -> AWSRekognition.SearchUsersOutputResponse { fatalError() } + func searchUsersByImage(input: AWSRekognition.SearchUsersByImageInput) async throws -> AWSRekognition.SearchUsersByImageOutputResponse { fatalError() } } diff --git a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockTranslateBehavior.swift b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockTranslateBehavior.swift index 5a1b1e86c2..ec91544aaa 100644 --- a/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockTranslateBehavior.swift +++ b/AmplifyPlugins/Predictions/Tests/AWSPredictionsPluginUnitTests/Mocks/Service/MockTranslateBehavior.swift @@ -41,4 +41,5 @@ extension MockTranslateBehavior { func tagResource(input: AWSTranslate.TagResourceInput) async throws -> AWSTranslate.TagResourceOutputResponse { fatalError() } func untagResource(input: AWSTranslate.UntagResourceInput) async throws -> AWSTranslate.UntagResourceOutputResponse { fatalError() } func updateParallelData(input: AWSTranslate.UpdateParallelDataInput) async throws -> AWSTranslate.UpdateParallelDataOutputResponse { fatalError() } + func translateDocument(input: AWSTranslate.TranslateDocumentInput) async throws -> AWSTranslate.TranslateDocumentOutputResponse { fatalError() } }