retrofit-axios-ts
Version:
A declarative and axios based retrofit implementation for JavaScript and TypeScript.
520 lines (519 loc) • 22 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseService = void 0;
/* eslint-disable @typescript-eslint/no-this-alias */
const qs = __importStar(require("qs"));
const constants_1 = require("../constants");
const httpClient_1 = require("./httpClient");
const nonHTTPRequestMethod_1 = require("./helpers/nonHTTPRequestMethod");
const utils_1 = require("../utils");
const Data_1 = __importDefault(require("../resolvers/Data"));
class BaseService {
constructor(serviceBuilder) {
this._endpoint = serviceBuilder.endpoint;
this._httpClient = new httpClient_1.HttpClient(serviceBuilder);
this._methodMap = new Map();
this._timeout = serviceBuilder.timeout;
this._logCallback = serviceBuilder.logCallback;
const methodNames = this._getInstanceMethodNames();
methodNames.forEach((methodName) => {
this._methodMap[methodName] = this[methodName];
});
const self = this;
for (const methodName of methodNames) {
const descriptor = {
enumerable: true,
configurable: true,
get() {
const method = self._methodMap[methodName];
const methodOriginalDescriptor = Object.getOwnPropertyDescriptor(method, constants_1.NON_HTTP_REQUEST_PROPERTY_NAME);
if (methodOriginalDescriptor &&
methodOriginalDescriptor.value === true) {
return method;
}
if (methodName === "_logCallback") {
return method;
}
return (...args) => __awaiter(this, void 0, void 0, function* () {
return yield self._wrap(methodName, args);
});
},
set: (newValue) => {
self._methodMap[methodName] = newValue;
},
};
Object.defineProperty(this, methodName, descriptor);
}
}
isClientStandalone() {
return this._httpClient.isStandalone();
}
useRequestInterceptor(interceptor) {
return this._httpClient.useRequestInterceptor(interceptor);
}
useResponseInterceptor(interceptor) {
return this._httpClient.useResponseInterceptor(interceptor);
}
ejectRequestInterceptor(id) {
this._httpClient.ejectRequestInterceptor(id);
}
ejectResponseInterceptor(id) {
this._httpClient.ejectResponseInterceptor(id);
}
setEndpoint(endpoint) {
this._endpoint = endpoint;
}
setLogCallback(logCallback) {
this._logCallback = logCallback;
}
setTimeout(timeout) {
this._timeout = timeout;
}
_getInstanceMethodNames() {
let properties = [];
let obj = this;
do {
properties = properties.concat(Object.getOwnPropertyNames(obj));
obj = Object.getPrototypeOf(obj);
} while (obj);
return properties.sort().filter((e, i, arr) => {
return e !== arr[i + 1] && this[e] && typeof this[e] === "function";
});
}
_wrap(methodName, args) {
return __awaiter(this, void 0, void 0, function* () {
const { url, method, headers, query, data, requestConfigParameters } = this._resolveParameters(methodName, args);
const config = this._makeConfig(methodName, url, method, headers, query, data, requestConfigParameters);
let error;
let response;
try {
response = yield this._httpClient.sendRequest(config);
}
catch (err) {
error = err;
response = err.response;
}
if (this._logCallback) {
this._logCallback(config, response);
}
if (error) {
throw error;
}
return response;
});
}
_resolveParameters(methodName, args) {
const url = this._resolveUrl(methodName, args);
const method = this._resolveHttpMethod(methodName);
let headers = this._resolveHeaders(methodName, args);
const query = this._resolveQuery(methodName, args);
const data = this._resolveData(methodName, headers, args);
const signal = this._resolveSignal(methodName, args);
const uploadProgressCallback = this._resolveUploadProgress(methodName, args);
const downloadProgressCallback = this._resolveDownloadProgress(methodName, args);
const requestConfigParameters = {
signal,
uploadProgress: uploadProgressCallback,
downloadProgress: downloadProgressCallback,
};
if (headers["content-type"] &&
headers["content-type"].indexOf("multipart/form-data") !== -1 &&
utils_1.isNode) {
headers = Object.assign(Object.assign({}, headers), data.getHeaders());
}
return { url, method, headers, query, data, requestConfigParameters };
}
_makeConfig(methodName, url, method, headers, query, data, requestConfigParameters) {
const { signal, uploadProgress, downloadProgress } = requestConfigParameters;
let config = {
url,
method,
headers,
params: query,
data,
signal,
onUploadProgress: uploadProgress,
onDownloadProgress: downloadProgress,
};
// response type
if (this.__meta__[methodName].responseType) {
config.responseType = this.__meta__[methodName].responseType;
}
// request transformer
if (this.__meta__[methodName].requestTransformer) {
config.transformRequest = this.__meta__[methodName].requestTransformer;
}
// response transformer
if (this.__meta__[methodName].responseTransformer) {
config.transformResponse = this.__meta__[methodName].responseTransformer;
}
// timeout
config.timeout = this.__meta__[methodName].timeout || this._timeout;
// deprecated
if (this.__meta__[methodName].deprecated) {
let hint = `[warning] Deprecated method: "${methodName}". `;
if (this.__meta__[methodName].deprecatedHint) {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
hint += this.__meta__[methodName].deprecatedHint;
}
// tslint:disable-next-line:no-console
console.warn(hint);
}
// query array format
if (this.__meta__[methodName].queryArrayFormat) {
config.paramsSerializer = {};
config.paramsSerializer.serialize = (params) => {
/* config.paramsSerializer.serialize = (params: any): string => { */
return qs.stringify(params, {
arrayFormat: this.__meta__[methodName].queryArrayFormat,
});
};
}
// mix in config set by @Config
config = Object.assign(Object.assign({}, config), this.__meta__[methodName].config);
return config;
}
_resolveUrl(methodName, args) {
const meta = this.__meta__;
const endpoint = this._endpoint;
const basePath = meta.basePath;
const path = meta[methodName].path;
const pathParams = meta[methodName].pathParams;
const options = meta[methodName].options || {};
let url = this.makeURL(endpoint, basePath, path, options);
for (const pos in pathParams) {
if (pathParams[pos]) {
url = url.replace(new RegExp(`\{${pathParams[pos]}}`), args[pos]);
}
}
return url;
}
makeURL(endpoint, basePath, path, options) {
const isAbsoluteURL = /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(path);
if (isAbsoluteURL) {
return path;
}
if (options.ignoreBasePath) {
return [endpoint, path].join("");
}
return [endpoint, basePath, path].join("");
}
_resolveHttpMethod(methodName) {
const meta = this.__meta__;
return meta[methodName].method;
}
_resolveHeaders(methodName, args) {
const meta = this.__meta__;
const headers = meta[methodName].headers || {};
const headerParams = meta[methodName].headerParams;
for (const pos in headerParams) {
if (headerParams[pos]) {
headers[headerParams[pos]] = args[pos];
}
}
const headerMapIndex = meta[methodName].headerMapIndex;
if (headerMapIndex >= 0) {
for (const key in args[headerMapIndex]) {
if (args[headerMapIndex][key]) {
headers[key] = args[headerMapIndex][key];
}
}
}
return headers;
}
_resolveQuery(methodName, args) {
const meta = this.__meta__;
const query = meta[methodName].query || {};
const queryParams = meta[methodName].queryParams;
for (const pos in queryParams) {
if (queryParams[pos]) {
query[queryParams[pos]] = args[pos];
}
}
const queryMapIndex = meta[methodName].queryMapIndex;
if (queryMapIndex >= 0) {
for (const key in args[queryMapIndex]) {
if (args[queryMapIndex][key]) {
query[key] = args[queryMapIndex][key];
}
}
}
return query;
}
_resolveSignal(methodName, args) {
const meta = this.__meta__;
let signal;
const abortSignal = meta[methodName].signal;
if (abortSignal >= 0) {
signal = args[abortSignal];
}
return signal;
}
_resolveUploadProgress(methodName, args) {
const meta = this.__meta__;
let _uploadProgress;
const uploadProgressIndex = meta[methodName].uploadProgressIndex;
if (uploadProgressIndex >= 0) {
_uploadProgress = args[uploadProgressIndex];
}
return _uploadProgress;
}
_resolveDownloadProgress(methodName, args) {
const meta = this.__meta__;
let _downloadProgress;
const downloadProgressIndex = meta[methodName].downloadProgressIndex;
if (downloadProgressIndex >= 0) {
_downloadProgress = args[downloadProgressIndex];
}
return _downloadProgress;
}
_resolveData(methodName, headers, args) {
const meta = this.__meta__;
const bodyIndex = meta[methodName].bodyIndex;
const fields = meta[methodName].fields || {};
const parts = meta[methodName].parts || {};
const fieldMapIndex = meta[methodName].fieldMapIndex;
const gqlQuery = meta[methodName].gqlQuery;
const gqlOperationName = meta[methodName].gqlOperationName;
const gqlVariablesIndex = meta[methodName].gqlVariablesIndex;
let data = {};
// @Body
if (bodyIndex >= 0) {
try {
if (Array.isArray(args[bodyIndex])) {
data = args[bodyIndex];
}
else if (args[bodyIndex] instanceof File) {
data = args[bodyIndex];
}
else {
data = Object.assign(Object.assign({}, data), args[bodyIndex]);
}
}
catch (error) {
data = Object.assign(Object.assign({}, data), args[bodyIndex]);
}
/* if (Array.isArray(args[bodyIndex])) {
data = args[bodyIndex];
} else {
data = { ...data, ...args[bodyIndex] };
} */
}
// @Field
if (Object.keys(fields).length > 0) {
const reqData = {};
for (const pos in fields) {
if (fields[pos]) {
reqData[fields[pos]] = args[pos];
}
}
data = Object.assign(Object.assign({}, data), reqData);
}
// @FieldMap
if (fieldMapIndex >= 0) {
const reqData = {};
for (const key in args[fieldMapIndex]) {
if (args[fieldMapIndex][key]) {
reqData[key] = args[fieldMapIndex][key];
}
}
data = Object.assign(Object.assign({}, data), reqData);
}
// @MultiPart
if (Object.keys(parts).length > 0) {
const reqData = {};
for (const pos in parts) {
if (parts[pos]) {
reqData[parts[pos]] = args[pos];
}
}
data = Object.assign(Object.assign({}, data), reqData);
}
// @GraphQL
if (gqlQuery) {
data.query = gqlQuery;
if (gqlOperationName) {
data.operationName = gqlOperationName;
}
// @GraphQLVariables
if (gqlVariablesIndex >= 0) {
data.variables = args[gqlVariablesIndex];
}
}
const contentType = headers["content-type"] || "application/json";
const dataResolverFactory = new Data_1.default();
const dataResolver = dataResolverFactory.createDataResolver(contentType);
return dataResolver.resolve(headers, data);
}
}
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Boolean)
], BaseService.prototype, "isClientStandalone", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Function]),
__metadata("design:returntype", Number)
], BaseService.prototype, "useRequestInterceptor", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Function]),
__metadata("design:returntype", Number)
], BaseService.prototype, "useResponseInterceptor", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", void 0)
], BaseService.prototype, "ejectRequestInterceptor", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", void 0)
], BaseService.prototype, "ejectResponseInterceptor", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", void 0)
], BaseService.prototype, "setEndpoint", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], BaseService.prototype, "setLogCallback", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", void 0)
], BaseService.prototype, "setTimeout", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Array)
], BaseService.prototype, "_getInstanceMethodNames", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Promise)
], BaseService.prototype, "_wrap", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveParameters", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, String, Object, Object, Object, Object]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_makeConfig", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", String)
], BaseService.prototype, "_resolveUrl", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, String, Object]),
__metadata("design:returntype", String)
], BaseService.prototype, "makeURL", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", String)
], BaseService.prototype, "_resolveHttpMethod", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveHeaders", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveQuery", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveSignal", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveUploadProgress", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveDownloadProgress", null);
__decorate([
nonHTTPRequestMethod_1.nonHTTPRequestMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object, Array]),
__metadata("design:returntype", Object)
], BaseService.prototype, "_resolveData", null);
exports.BaseService = BaseService;