"use strict";
/**
 * 科拓/统一API通用模块
 * @date 2022-03-04
 * @author 何华东
 */
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());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.axiosInstance = exports.Service = exports.throwIfResCodeNoSuccess = exports.ApiResponse = exports.ApiRequestBase = void 0;
var axios_1 = require("axios");
var mslib_1 = require("mslib");
var CryptoUtils_1 = require("./CryptoUtils");
var Contants_1 = require("./Contants");
var Config_1 = require("./Config");
var AxiosUtils_1 = require("./AxiosUtils");
var uuid = require("uuid");
var Errors_1 = require("./Errors");
var moment = require('moment');
/**
 * API请求基类
 */
var ApiRequestBase = /** @class */ (function () {
    function ApiRequestBase() {
    }
    return ApiRequestBase;
}());
exports.ApiRequestBase = ApiRequestBase;
/**
 * API响应类
 */
var ApiResponse = /** @class */ (function () {
    function ApiResponse(resCode) {
        this.resCode = resCode;
    }
    /**
     * 判断指定的响应码是否为成功响应码
     * @param resCode 指定的响应码
     * @returns
     */
    ApiResponse.resCodeIsSuccess = function (resCode) {
        return (resCode === null || resCode === void 0 ? void 0 : resCode.toString()) === '0';
    };
    /**
     * 创建一个失败响应对象
     * @param resMsg 失败信息
     * @returns
     */
    ApiResponse.failed = function (resMsg) {
        var apiResponse = new ApiResponse('-1');
        apiResponse.resMsg = resMsg;
        return apiResponse;
    };
    /**
     * 创建一个成功响应对象
     * @param data 数据
     * @returns
     */
    ApiResponse.successWithData = function (data) {
        var apiResponse = new ApiResponse('0');
        apiResponse.data = data;
        return apiResponse;
    };
    /**
     * 创建一个成功响应对象
     * @param resMsg 信息
     * @returns
     */
    ApiResponse.successWithMsg = function (resMsg) {
        var apiResponse = new ApiResponse('0');
        apiResponse.resMsg = resMsg;
        return apiResponse;
    };
    /**
     * 成功响应对象
     */
    ApiResponse.success = new ApiResponse('0');
    return ApiResponse;
}());
exports.ApiResponse = ApiResponse;
/**
 * 生成统一API axios实例
 *
 * 默认会对请求进行拦截，自动填充默认请求参数(appId、ts等)，并签名
 *
 * 默认会对响应进行拦截，进行日志记录
 * @type { UniteApiConfig } 用户需实现UniteApiConfig接口，并在ioc中注册
 * @returns
 */
function generateAxiosInstance(uniteApiConfig) {
    var axiosInstance = axios_1.default.create({
        baseURL: uniteApiConfig.baseUrl,
        timeout: uniteApiConfig.timeout,
    });
    axiosInstance.interceptors.request.use(function (config) {
        var _a;
        config.headers = Object.assign({
            'Content-Type': 'application/json;charset=utf-8',
            'version': ((_a = config.headers) === null || _a === void 0 ? void 0 : _a.version) || '1.0.0',
        }, config.headers);
        var dataWrap = {
            appId: uniteApiConfig.appId,
            reqId: "" + uuid.v4().replace('-', ''),
            ts: "" + moment().valueOf(),
            key: ''
        };
        dataWrap = Object.assign(dataWrap, config.data);
        var signStr = Object.keys(dataWrap).sort().filter(function (k) {
            if (['appId', 'key'].includes(k))
                return false;
            if (dataWrap[k] === undefined || dataWrap[k] === null || dataWrap[k] === '')
                return false;
            if (typeof dataWrap[k] === 'object')
                return false;
            if (Array.isArray(dataWrap[k]))
                return false;
            return true;
        }).map(function (k) { return k + "=" + dataWrap[k]; }).join('&') + ("&" + uniteApiConfig.appSecret);
        dataWrap.key = CryptoUtils_1.CryptoUtils.md5(signStr).toUpperCase();
        config.data = dataWrap;
        return config;
    }, function (error) {
        return uniteApiConfig.axiosErrorHandler(error);
    });
    axiosInstance.interceptors.response.use(function (response) {
        //生产环境不记录SQL代理日志
        if (Contants_1.Contants.IS_PROD && response.config.url.includes('/dbproxy/'))
            return response;
        mslib_1.logger.info("\u7EDF\u4E00API'" + response.config.url + "'\u8C03\u7528\u6210\u529F,\n                      requestUrl:" + (response.config.baseURL + response.config.url) + ",\n                      headers:" + JSON.stringify(response.config.headers) + ",\n                      requestData:" + response.config.data + ",\n                      response:" + JSON.stringify(response.data));
        return response;
    }, function (error) {
        return uniteApiConfig.axiosErrorHandler(error);
    });
    return axiosInstance;
}
/**
 * 判断指定的统一API响应报文中的响应码是否为非成功，如果非成功则抛出ApiError异常
 * @param axiosResponse 指定的统一API响应报文
 */
function throwIfResCodeNoSuccess(axiosResponse) {
    var _a;
    if (!ApiResponse.resCodeIsSuccess((_a = axiosResponse.data) === null || _a === void 0 ? void 0 : _a.resCode)) {
        throw AxiosUtils_1.generateApiErrorFromAxiosResponse(axiosResponse, '统一API返回错误');
    }
}
exports.throwIfResCodeNoSuccess = throwIfResCodeNoSuccess;
/**
 * 统一API上行API装饰器
 *
 * 自动验签，异常捕获，日志记录，发生异常自动返回错误报文等
 * @param description 服务描述
 * @returns
 */
// export function Service(description?: string): MethodDecorator {
//     return function (target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
//         logger.info(`${Contants.SS_SERVICE_BASE_URL}${getBasicConfig()?.projectId}.${target.constructor.name}/1.0`, description);
//         let method = descriptor.value;
//         descriptor.value = async function () {
//             let response;
//             let _error;
//             try {
//                 if (Contants.IS_PROD) {
//                     if (!arguments || !arguments[0] || !arguments[0].key) throw new ParamEmptyError();
//                     let input = arguments[0];
//                     let signStr = Object.keys(input).sort().filter(k => {
//                         if (['appId', 'key'].includes(k)) return false;
//                         if (input[k] === undefined || input[k] === null || input[k] === '') return false;
//                         if (typeof input[k] === 'object') return false;
//                         if (Array.isArray(input[k])) return false;
//                         return true;
//                     }).map(k => `${k}=${input[k]}`).join('&') + `&${getUniteApiConfig().appSecret}`;
//                     let new_sign = CryptoUtils.md5(signStr).toUpperCase();
//                     if (new_sign !== input.key) throw new ValidateSignFailedError();
//                 }
//                 response = await method.apply(this, arguments);
//             } catch (error) {
//                 response = ApiResponse.failed(error instanceof Error ? error.message : error.toString());
//                 _error = error;
//             }
//             logger[_error ? 'error' : 'info'](`${target.constructor.name},input:${JSON.stringify(arguments)},response:${JSON.stringify(response)}`, _error);
//             return response;
//         }
//     }
// }
function Service(description) {
    return function (target, propertyKey, descriptor) {
        var _a;
        mslib_1.logger.info("" + Contants_1.Contants.SS_SERVICE_BASE_URL + ((_a = Config_1.getBasicConfig()) === null || _a === void 0 ? void 0 : _a.projectId) + "." + target.constructor.name + "/1.0", description);
        var method = descriptor.value;
        descriptor.value = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            return __awaiter(this, arguments, void 0, function () {
                var response, _error, input_1, signStr, new_sign, error_1;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            _a.trys.push([0, 2, , 3]);
                            if (Contants_1.Contants.IS_PROD) {
                                if (!args || !args[0] || !args[0].key)
                                    throw new Errors_1.ParamEmptyError();
                                input_1 = args[0];
                                signStr = Object.keys(input_1).sort().filter(function (k) {
                                    if (['appId', 'key'].includes(k))
                                        return false;
                                    if (input_1[k] === undefined || input_1[k] === null || input_1[k] === '')
                                        return false;
                                    if (typeof input_1[k] === 'object')
                                        return false;
                                    if (Array.isArray(input_1[k]))
                                        return false;
                                    return true;
                                }).map(function (k) { return k + "=" + input_1[k]; }).join('&') + ("&" + Config_1.getUniteApiConfig().appSecret);
                                new_sign = CryptoUtils_1.CryptoUtils.md5(signStr).toUpperCase();
                                if (new_sign !== input_1.key)
                                    throw new Errors_1.ValidateSignFailedError();
                            }
                            return [4 /*yield*/, method.apply(this, args)];
                        case 1:
                            response = _a.sent();
                            mslib_1.logger.info('method.apply...');
                            return [3 /*break*/, 3];
                        case 2:
                            error_1 = _a.sent();
                            response = ApiResponse.failed(error_1 instanceof Error ? error_1.message : error_1.toString());
                            _error = error_1;
                            return [3 /*break*/, 3];
                        case 3:
                            mslib_1.logger[_error ? 'error' : 'info'](target.constructor.name + ",input:" + JSON.stringify(arguments) + ",response:" + JSON.stringify(response), _error);
                            return [2 /*return*/, response];
                    }
                });
            });
        };
    };
}
exports.Service = Service;
var defaults = {
    baseUrl: Contants_1.Contants.UNITE_API_BASE_URL,
    timeout: 10000,
    axiosErrorHandler: AxiosUtils_1.throwApiError
};
/**
 * 统一API axios实例
 */
exports.axiosInstance = generateAxiosInstance(Object.assign(defaults, Config_1.getUniteApiConfig())); /**
 * 科拓/统一API通用模块
 * @date 2022-03-04
 * @author 何华东
 */
var moment = require('moment');
/**
 * API请求基类
 */
var ApiRequestBase = /** @class */ (function () {
    function ApiRequestBase() {
    }
    return ApiRequestBase;
}());
exports.ApiRequestBase = ApiRequestBase;
/**
 * API响应类
 */
var ApiResponse = /** @class */ (function () {
    function ApiResponse(resCode) {
        this.resCode = resCode;
    }
    /**
     * 判断指定的响应码是否为成功响应码
     * @param resCode 指定的响应码
     * @returns
     */
    ApiResponse.resCodeIsSuccess = function (resCode) {
        return (resCode === null || resCode === void 0 ? void 0 : resCode.toString()) === '0';
    };
    /**
     * 创建一个失败响应对象
     * @param resMsg 失败信息
     * @returns
     */
    ApiResponse.failed = function (resMsg) {
        var apiResponse = new ApiResponse('-1');
        apiResponse.resMsg = resMsg;
        return apiResponse;
    };
    /**
     * 创建一个成功响应对象
     * @param data 数据
     * @returns
     */
    ApiResponse.successWithData = function (data) {
        var apiResponse = new ApiResponse('0');
        apiResponse.data = data;
        return apiResponse;
    };
    /**
     * 创建一个成功响应对象
     * @param resMsg 信息
     * @returns
     */
    ApiResponse.successWithMsg = function (resMsg) {
        var apiResponse = new ApiResponse('0');
        apiResponse.resMsg = resMsg;
        return apiResponse;
    };
    /**
     * 成功响应对象
     */
    ApiResponse.success = new ApiResponse('0');
    return ApiResponse;
}());
exports.ApiResponse = ApiResponse;
/**
 * 生成统一API axios实例
 *
 * 默认会对请求进行拦截，自动填充默认请求参数(appId、ts等)，并签名
 *
 * 默认会对响应进行拦截，进行日志记录
 * @type { UniteApiConfig } 用户需实现UniteApiConfig接口，并在ioc中注册
 * @returns
 */
function generateAxiosInstance(uniteApiConfig) {
    var axiosInstance = axios_1.default.create({
        baseURL: uniteApiConfig.baseUrl,
        timeout: uniteApiConfig.timeout,
    });
    axiosInstance.interceptors.request.use(function (config) {
        var _a;
        config.headers = Object.assign({
            'Content-Type': 'application/json;charset=utf-8',
            'version': ((_a = config.headers) === null || _a === void 0 ? void 0 : _a.version) || '1.0.0',
        }, config.headers);
        var dataWrap = {
            appId: uniteApiConfig.appId,
            reqId: "" + uuid.v4().replace('-', ''),
            ts: "" + moment().valueOf(),
            key: ''
        };
        dataWrap = Object.assign(dataWrap, config.data);
        var signStr = Object.keys(dataWrap).sort().filter(function (k) {
            if (['appId', 'key'].includes(k))
                return false;
            if (dataWrap[k] === undefined || dataWrap[k] === null || dataWrap[k] === '')
                return false;
            if (typeof dataWrap[k] === 'object')
                return false;
            if (Array.isArray(dataWrap[k]))
                return false;
            return true;
        }).map(function (k) { return k + "=" + dataWrap[k]; }).join('&') + ("&" + uniteApiConfig.appSecret);
        dataWrap.key = CryptoUtils_1.CryptoUtils.md5(signStr).toUpperCase();
        config.data = dataWrap;
        return config;
    }, function (error) {
        return uniteApiConfig.axiosErrorHandler(error);
    });
    axiosInstance.interceptors.response.use(function (response) {
        //生产环境不记录SQL代理日志
        if (Contants_1.Contants.IS_PROD && response.config.url.includes('/dbproxy/'))
            return response;
        mslib_1.logger.info("\u7EDF\u4E00API'" + response.config.url + "'\u8C03\u7528\u6210\u529F,\n                      requestUrl:" + (response.config.baseURL + response.config.url) + ",\n                      headers:" + JSON.stringify(response.config.headers) + ",\n                      requestData:" + response.config.data + ",\n                      response:" + JSON.stringify(response.data));
        return response;
    }, function (error) {
        return uniteApiConfig.axiosErrorHandler(error);
    });
    return axiosInstance;
}
/**
 * 判断指定的统一API响应报文中的响应码是否为非成功，如果非成功则抛出ApiError异常
 * @param axiosResponse 指定的统一API响应报文
 */
function throwIfResCodeNoSuccess(axiosResponse) {
    var _a;
    if (!ApiResponse.resCodeIsSuccess((_a = axiosResponse.data) === null || _a === void 0 ? void 0 : _a.resCode)) {
        throw AxiosUtils_1.generateApiErrorFromAxiosResponse(axiosResponse, '统一API返回错误');
    }
}
exports.throwIfResCodeNoSuccess = throwIfResCodeNoSuccess;
/**
 * 统一API上行API装饰器
 *
 * 自动验签，异常捕获，日志记录，发生异常自动返回错误报文等
 * @param description 服务描述
 * @returns
 */
// export function Service(description?: string): MethodDecorator {
//     return function (target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
//         logger.info(`${Contants.SS_SERVICE_BASE_URL}${getBasicConfig()?.projectId}.${target.constructor.name}/1.0`, description);
//         let method = descriptor.value;
//         descriptor.value = async function () {
//             let response;
//             let _error;
//             try {
//                 if (Contants.IS_PROD) {
//                     if (!arguments || !arguments[0] || !arguments[0].key) throw new ParamEmptyError();
//                     let input = arguments[0];
//                     let signStr = Object.keys(input).sort().filter(k => {
//                         if (['appId', 'key'].includes(k)) return false;
//                         if (input[k] === undefined || input[k] === null || input[k] === '') return false;
//                         if (typeof input[k] === 'object') return false;
//                         if (Array.isArray(input[k])) return false;
//                         return true;
//                     }).map(k => `${k}=${input[k]}`).join('&') + `&${getUniteApiConfig().appSecret}`;
//                     let new_sign = CryptoUtils.md5(signStr).toUpperCase();
//                     if (new_sign !== input.key) throw new ValidateSignFailedError();
//                 }
//                 response = await method.apply(this, arguments);
//             } catch (error) {
//                 response = ApiResponse.failed(error instanceof Error ? error.message : error.toString());
//                 _error = error;
//             }
//             logger[_error ? 'error' : 'info'](`${target.constructor.name},input:${JSON.stringify(arguments)},response:${JSON.stringify(response)}`, _error);
//             return response;
//         }
//     }
// }
function Service(description) {
    return function (target, propertyKey, descriptor) {
        var _a;
        mslib_1.logger.info("" + Contants_1.Contants.SS_SERVICE_BASE_URL + ((_a = Config_1.getBasicConfig()) === null || _a === void 0 ? void 0 : _a.projectId) + "." + target.constructor.name + "/1.0", description);
        var method = descriptor.value;
        descriptor.value = function (input) {
            return __awaiter(this, void 0, void 0, function () {
                var response, _error, error_2;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            _a.trys.push([0, 2, , 3]);
                            return [4 /*yield*/, method.apply(this, input)];
                        case 1:
                            response = _a.sent();
                            return [3 /*break*/, 3];
                        case 2:
                            error_2 = _a.sent();
                            response = ApiResponse.failed(error_2 instanceof Error ? error_2.message : error_2.toString());
                            _error = error_2;
                            return [3 /*break*/, 3];
                        case 3:
                            mslib_1.logger[_error ? 'error' : 'info'](target.constructor.name + ",input:" + JSON.stringify(input) + ",response:" + JSON.stringify(response), _error);
                            return [2 /*return*/, response];
                    }
                });
            });
        };
    };
}
exports.Service = Service;
var defaults = {
    baseUrl: Contants_1.Contants.UNITE_API_BASE_URL,
    timeout: 10000,
    axiosErrorHandler: AxiosUtils_1.throwApiError
};
/**
 * 统一API axios实例
 */
exports.axiosInstance = generateAxiosInstance(Object.assign(defaults, Config_1.getUniteApiConfig()));
//# sourceMappingURL=KTApiCommon.js.map