@chevre/domain
Version:
Chevre Domain Library for Node.js
228 lines (227 loc) • 10.9 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MOVIE_TICKET_RESERVE_REQUEST_ERROR_NAME = exports.MongoErrorCode = void 0;
exports.isMongoError = isMongoError;
exports.handleMongoError = handleMongoError;
exports.handleCOAError = handleCOAError;
exports.handleCOAReserveTemporarilyError = handleCOAReserveTemporarilyError;
exports.handlePecorinoError = handlePecorinoError;
exports.handleMvtkReserveError = handleMvtkReserveError;
exports.handleAWSError = handleAWSError;
/**
* エラーハンドラー
* 外部サービスと連携している場合に、サービス(API)のエラーを本ドメインのエラーに変換する責任を担います。
*/
const http_status_1 = require("http-status");
const factory_1 = require("./factory");
let mongo;
var MongoErrorCode;
(function (MongoErrorCode) {
MongoErrorCode[MongoErrorCode["DuplicateKey"] = 11000] = "DuplicateKey";
MongoErrorCode[MongoErrorCode["MaxTimeMSExpired"] = 50] = "MaxTimeMSExpired";
MongoErrorCode[MongoErrorCode["ExceededTimeLimit"] = 262] = "ExceededTimeLimit";
})(MongoErrorCode || (exports.MongoErrorCode = MongoErrorCode = {}));
function isMongoError(error) {
return __awaiter(this, void 0, void 0, function* () {
if (mongo === undefined) {
mongo = (yield Promise.resolve().then(() => require('mongoose'))).mongo;
}
return (error instanceof mongo.MongoError || error instanceof mongo.MongoServerError);
});
}
function handleMongoError(error) {
return __awaiter(this, void 0, void 0, function* () {
if (mongo === undefined) {
mongo = (yield Promise.resolve().then(() => require('mongoose'))).mongo;
}
let handledError = error;
if (handledError instanceof mongo.MongoError || handledError instanceof mongo.MongoServerError) {
switch (handledError.code) {
case MongoErrorCode.DuplicateKey:
handledError = new factory_1.errors.AlreadyInUse('', [], `Some fields already in use. code:${handledError.code} message:${handledError.message}`);
// no op
break;
case MongoErrorCode.MaxTimeMSExpired:
case MongoErrorCode.ExceededTimeLimit:
handledError = new factory_1.errors.GatewayTimeout(`Gateway Timeout. name:${handledError.name} code:${handledError.code} message:${handledError.message}`);
break;
default:
}
}
if (mongo.BSON.BSONError.isBSONError(handledError)) {
handledError = new factory_1.errors.Argument('', handledError.message);
}
return handledError;
});
}
/**
* 汎用的なCOAエラーハンドリング
*/
// tslint:disable-next-line:no-any
function handleCOAError(error) {
var _a;
let handledError = error;
if (error.name === 'AbortError') {
handledError = new factory_1.errors.GatewayTimeout(`Gateway Timeout. name:${error.name} code:${error.code} message:${error.message}`);
}
if (error.name === 'COAServiceError') {
// error.requestOptions.uriを処理
const uri = (_a = error.requestOptions) === null || _a === void 0 ? void 0 : _a.uri;
if (error.message === 'ETIMEDOUT' || error.message === 'ESOCKETTIMEDOUT') {
handledError = new factory_1.errors.GatewayTimeout(`Timeout. name:${error.name} code:${error.code} message:${error.message} uri:${uri}`);
}
else {
handledError = new factory_1.errors.Internal(`Service Unavailable. name:${error.name} code:${error.code} message:${error.message} uri:${uri}`);
}
}
return handledError;
}
/**
* COA仮予約エラーハンドリング
*/
// tslint:disable-next-line:no-any
function handleCOAReserveTemporarilyError(error) {
var _a;
let handledError = error;
// if (error.message === '座席取得失敗') {
// }
// メッセージ「既に予約済みです」の場合は、座席の重複とみなす
if (error.message === '既に予約済みです') {
handledError = new factory_1.errors.AlreadyInUse('offer', ['seatNumber'], 'Seat not available');
}
// Chevreが500未満であればクライアントエラーとみなす
const reserveServiceHttpStatusCode = error.code;
if (Number.isInteger(reserveServiceHttpStatusCode)) {
if (reserveServiceHttpStatusCode < http_status_1.INTERNAL_SERVER_ERROR) {
handledError = new factory_1.errors.Argument('Event', error.message);
}
else {
const uri = (_a = error.requestOptions) === null || _a === void 0 ? void 0 : _a.uri;
if (error.message === 'ETIMEDOUT' || error.message === 'ESOCKETTIMEDOUT') {
handledError = new factory_1.errors.GatewayTimeout(`Timeout. name:${error.name} code:${error.code} message:${error.message} uri:${uri}`);
}
else {
handledError = new factory_1.errors.Internal(`Reserve service unavailable. name:${error.name} code:${error.code} message:${error.message} uri:${uri}`);
}
}
}
return handledError;
}
/**
* Pecorinoサービスエラーをハンドリングする
* 可能であればChevreエラーへ変換します
*/
// tslint:disable-next-line:no-any
function handlePecorinoError(error) {
let handledError = error;
if (error.name === 'ChevreRequestError' || error.name === 'PecorinoRequestError') {
// Pecorino APIのステータスコード4xxをハンドリング
// PecorinoAPIのレスポンスステータスコードが4xxであればクライアントエラー
const message = `${error.name}:${error.message}`;
switch (error.code) {
case http_status_1.BAD_REQUEST: // 400
handledError = new factory_1.errors.Argument((typeof error.argumentName === 'string' && error.argumentName.length > 0) ? error.argumentName : 'PecorinoArgument', message);
break;
case http_status_1.UNAUTHORIZED: // 401
handledError = new factory_1.errors.Unauthorized(message);
break;
case http_status_1.FORBIDDEN: // 403
handledError = new factory_1.errors.Forbidden(message);
break;
case http_status_1.NOT_FOUND: // 404
handledError = new factory_1.errors.NotFound(message);
break;
case http_status_1.TOO_MANY_REQUESTS: // 429
handledError = new factory_1.errors.RateLimitExceeded(message);
break;
default:
handledError = new factory_1.errors.Internal(message);
}
}
return handledError;
}
exports.MOVIE_TICKET_RESERVE_REQUEST_ERROR_NAME = 'MovieticketReserveRequestError';
/**
* ムビチケ着券サービスエラーをハンドリングする
* 可能であればChevreエラーへ変換します
*/
// tslint:disable-next-line:no-any
function handleMvtkReserveError(error) {
let handledError = error;
if (error.name === exports.MOVIE_TICKET_RESERVE_REQUEST_ERROR_NAME) {
// ムビチケAPIのステータスコード4xxをハンドリング
// ムビチケAPIのレスポンスステータスコードが4xxであればクライアントエラー
const message = `${error.name}:${error.message}`;
switch (error.code) {
case http_status_1.BAD_REQUEST: // 400
handledError = new factory_1.errors.Argument((typeof error.argumentName === 'string' && error.argumentName.length > 0) ? error.argumentName : 'MovieticketReserveArgument', message);
break;
case http_status_1.UNAUTHORIZED: // 401
handledError = new factory_1.errors.Unauthorized(message);
break;
case http_status_1.FORBIDDEN: // 403
handledError = new factory_1.errors.Forbidden(message);
break;
case http_status_1.NOT_FOUND: // 404
handledError = new factory_1.errors.NotFound(message);
break;
case http_status_1.TOO_MANY_REQUESTS: // 429
handledError = new factory_1.errors.RateLimitExceeded(message);
break;
// handle 504(2025-04-25~)
case http_status_1.GATEWAY_TIMEOUT: // 504
handledError = new factory_1.errors.GatewayTimeout(message);
break;
default:
handledError = new factory_1.errors.Internal(message);
}
}
// タイムアウト設定によって中止されたリクエストの場合
// const uri: string | undefined = error.requestOptions?.uri;
if (error.name === 'AbortError') {
handledError = new factory_1.errors.GatewayTimeout(`Gateway Timeout. name:${error.name} type:${error.type} message:${error.message}`);
}
return handledError;
}
/**
* AWSエラーハンドリング
*/
// tslint:disable-next-line:no-any
function handleAWSError(error) {
let handledError = error;
const message = `${error.name}:${error.message}`;
switch (error.name) {
case 'InternalErrorException':
handledError = new factory_1.errors.Internal(message);
break;
case 'MissingRequiredParameter':
handledError = new factory_1.errors.ArgumentNull('AWSArgument', message);
break;
case 'InvalidParameterException':
handledError = new factory_1.errors.Argument('AWSArgument', message);
break;
case 'NotAuthorizedException':
handledError = new factory_1.errors.Forbidden(message);
break;
case 'TooManyRequestsException':
handledError = new factory_1.errors.RateLimitExceeded(message);
break;
case 'ResourceNotFoundException':
handledError = new factory_1.errors.NotFound('Resource', message);
break;
case 'UserNotFoundException':
handledError = new factory_1.errors.NotFound('User', message);
break;
default:
}
return handledError;
}
;