@qrvey/fetch
Version:
 
263 lines (255 loc) • 9.01 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
// src/helpers/constants.ts
var HTTPAction = {
GET: "GET",
POST: "POST",
PATCH: "PATCH",
DELETE: "DELETE",
PUT: "PUT"
};
// src/helpers/errors/customError.ts
var CustomError = class extends Error {
constructor(message, errorDetails, stack, context = process.env.SERVICE_NAME || "QrveyCustomError") {
super(message);
this.errorDetails = errorDetails;
this.context = context;
this.name = "ERROR in " + this.context;
this.stack = stack;
}
toJSON() {
return {
name: this.name,
message: this.message,
stack: this.stack,
details: this.errorDetails
};
}
};
// src/helpers/errors/restClientError.ts
var RestClientError = class extends CustomError {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(url, restError = {}) {
const message = `REST Client Error at ${url}${(restError == null ? void 0 : restError.message) ? `: ${restError == null ? void 0 : restError.message}` : ""}`;
super(message, restError, restError.stack);
}
};
// src/helpers/errors/restBadHttpActionParams.ts
var RestBadHttpActionParams = class extends CustomError {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(url, message, error = {}) {
const errorMessage = `Bad RestHttpAction params at ${url}: ${message}`;
super(errorMessage, error.message || error, error.stack);
}
};
// src/services/fetchClient.service.ts
var FetchClientService = class {
static validateEndpoint(endpoint) {
if (endpoint.startsWith("/")) return;
const errorMessage = `Invalid endpoint "${endpoint}". Please replace with "/${endpoint}"`;
throw new RestBadHttpActionParams(endpoint, errorMessage);
}
static buildUrl(endpoint, options) {
var _a, _b;
const baseDomain = (_a = process.env.DOMAIN) != null ? _a : "";
const privateDomain = (_b = process.env.PRIVATE_DOMAIN) != null ? _b : "";
const defaultDomain = options.privateDomain === false ? baseDomain : privateDomain;
return `${options.baseDomain || defaultDomain}${endpoint}`;
}
static baseHeaders(options) {
var _a, _b;
const baseHeaders = {
"Content-Type": "application/json"
};
const customContentTypeHeader = ((_a = options.headers) == null ? void 0 : _a["content-type"]) || ((_b = options.headers) == null ? void 0 : _b["Content-Type"]);
if (customContentTypeHeader) {
baseHeaders["Content-Type"] = customContentTypeHeader;
}
if (options.useApiKey && process.env.API_KEY)
baseHeaders["x-api-key"] = process.env.API_KEY;
return baseHeaders;
}
static customHeaders(options) {
const _a = options.headers || {}, {
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
"Content-Type": _ContentType,
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
"content-type": _contentType
} = _a, customHeadersObject = __objRest(_a, [
"Content-Type",
"content-type"
]);
return customHeadersObject;
}
static buildFetchOptions(method, body, options) {
const headers = __spreadValues(__spreadValues({}, this.baseHeaders(options)), this.customHeaders(options));
const filteredHeaders = Object.fromEntries(
Object.entries(headers).filter(
([, value]) => value !== null && value !== void 0
)
);
const requestOptions = {
headers: filteredHeaders,
method
};
if (body) requestOptions["body"] = JSON.stringify(body);
return requestOptions;
}
static isValidUrl(url) {
return !!(url.protocol && url.hostname && url.pathname);
}
static hasValidProtocol(url) {
const secureProtocols = ["http:", "https:"];
return secureProtocols.includes(url.protocol);
}
static verifyUrl(urlObj) {
if (!this.isValidUrl(urlObj)) {
throw new RestBadHttpActionParams(
"Invalid URL",
`URL details: Protocol: ${urlObj.protocol}, Hostname: ${urlObj.hostname}, Pathname: ${urlObj.pathname}`
);
}
if (!this.hasValidProtocol(urlObj)) {
throw new RestBadHttpActionParams(
"Invalid URL",
`URL protocol [${urlObj.protocol}] is not secure`
);
}
}
static toHttpUrl(url) {
try {
const urlObj = new URL(url);
this.verifyUrl(urlObj);
return urlObj.href;
} catch (error) {
throw new RestBadHttpActionParams(
`Invalid URL [${url}]`,
"URL is not valid.",
error
);
}
}
static async getResponseData(isJsonResponse, response) {
const clonedResponse = response.clone();
let responseData = null;
try {
if (isJsonResponse) {
responseData = await response.json();
} else {
responseData = await response.text();
}
await clonedResponse.text();
} catch (_) {
responseData = await clonedResponse.text();
}
return responseData;
}
static async handleResponse(response) {
const responseContentType = response.headers.get("content-type");
const isJsonResponse = responseContentType && responseContentType.includes("application/json");
const responseData = await this.getResponseData(
!!isJsonResponse,
response
);
if (response.ok) {
return responseData;
}
throw new RestClientError(response.url, responseData);
}
static fetchData(url, requestOptions) {
return fetch(url, requestOptions).then(this.handleResponse.bind(this)).catch((error) => {
if (error instanceof RestClientError) throw error;
throw new RestClientError(url, error);
});
}
static queryParamsToQueryString(queryParameters) {
const queryParamsArray = Object.entries(queryParameters).map(
([queryName, queryValue]) => {
const isArrayValue = Array.isArray(queryValue);
if (isArrayValue)
return queryValue.map((val) => `${queryName}=${val}`).join("&");
else return `${queryName}=${queryValue}`;
}
);
return queryParamsArray.join("&");
}
static httpAction(method, endpoint, body, options = {}) {
this.validateEndpoint(endpoint);
const url = this.buildUrl(endpoint, options);
const queryParamsString = options.queryParameters ? `?${this.queryParamsToQueryString(options.queryParameters)}` : "";
const httpUrl = this.toHttpUrl(`${url}${queryParamsString}`);
return this.fetchData(
httpUrl,
this.buildFetchOptions(method.toUpperCase(), body, options)
);
}
};
// src/services/fetch.service.ts
var FetchService = class _FetchService {
static sendRequest(endpoint, body, options) {
return FetchClientService.httpAction(
options.method,
endpoint,
body,
options
);
}
static get(endpoint, options) {
return _FetchService.sendRequest(endpoint, null, __spreadProps(__spreadValues({}, options), {
method: HTTPAction.GET
}));
}
static post(endpoint, body, options) {
return _FetchService.sendRequest(endpoint, body, __spreadProps(__spreadValues({}, options), {
method: HTTPAction.POST
}));
}
static put(endpoint, body, options) {
return _FetchService.sendRequest(endpoint, body, __spreadProps(__spreadValues({}, options), {
method: HTTPAction.PUT
}));
}
static patch(endpoint, body, options) {
return _FetchService.sendRequest(endpoint, body, __spreadProps(__spreadValues({}, options), {
method: HTTPAction.PATCH
}));
}
static delete(endpoint, body, options) {
return _FetchService.sendRequest(endpoint, body, __spreadProps(__spreadValues({}, options), {
method: HTTPAction.DELETE
}));
}
};
exports.FetchService = FetchService;
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map