Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 2x 2x 2x 2x 2x 5x 5x 7x 7x 1x 1x 6x 6x 6x 6x 1x 1x 5x 5x 5x 1x 1x 4x 4x 4x | import { ClientInterface } from '@Application/Shared/Translator/ClientInterface';
import { Result } from '@Domain/Types/Result';
import { HttpError } from '@Domain/Errors/HttpError';
import { ValidationError } from '@Domain/Errors/ValidationError';
import { LoggerInterface } from '@Application/Shared/Monitoring/LoggerInterface';
import { TranslationResponseSchema } from './types';
import config from '@Infrastructure/Environments/config';
/**
* HTTP client for communicating with the Translation API
*/
export class HttpClient implements ClientInterface {
private readonly baseUrl = config.translatorClient.baseUrl;
constructor(private readonly logger: LoggerInterface) { }
/**
* Retrieves a translation for the given text
* @param translationType The type of translation to use (e.g., 'yoda', 'shakespeare')
* @param text The text to translate
* @returns A promise resolving to a Result containing either the translated text or an Error
*/
async getTranslation(translationType: string, text: string): Promise<Result<Error, string>> {
this.logger.info(`Fetching translation`, { translationType, text });
if (!text || !translationType) {
this.logger.error(`Text or translation type are required`, {
translationType,
text,
});
return {
success: false,
error: new ValidationError('Text or translation type are required'),
};
}
const body = new URLSearchParams({ text });
let response: Response;
try {
response = await fetch(`${this.baseUrl}/${translationType}.json`, {
method: 'POST',
headers: {
...(config.translatorClient.apiKey.length > 0 ? { 'X-Funtranslations-Api-Secret': config.translatorClient.apiKey } : {}),
},
body: body,
});
} catch (error) {
this.logger.error(`Failed to fetch translation`, {
translationType,
text,
body: error,
});
return {
success: false,
error: new HttpError(500, `Failed to fetch '${translationType}' translation for '${text}'`),
};
}
if (!response.ok) {
this.logger.error(`Failed to fetch translation`, {
translationType,
text,
status: response.status,
body: await response.text(),
});
return {
success: false,
error: new HttpError(response.status, `Failed to fetch '${translationType}' translation for '${text}'`),
};
}
const data = await response.json();
const result = TranslationResponseSchema.safeParse(data);
if (!result.success) {
this.logger.error(`Failed to parse translation`, {
translationType,
text,
body: data,
error: result.error.message,
});
return {
success: false,
error: new ValidationError(result.error.message),
};
} else {
this.logger.info(`Translation fetched successfully`, {
translationType,
text,
});
this.logger.debug(`Translation fetched successfully: body`, {
translationType,
text,
body: data,
});
return {
success: true,
data: result.data.contents.translated,
};
}
}
}
|