gitlab-api-async-iterator
Version:
Async iterator for GitLab API based on axios
136 lines (111 loc) • 3.06 kB
JavaScript
const _defaultAxios = require("axios");
const timeout = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const requestMethods = [
"request",
"get",
"delete",
"head",
"options",
"post",
"put",
"patch",
];
const waitBeforeRetry = async (error, retries, logger) => {
// Be forgiving if we hit server errors or rate limits and retry after some time
if (
error &&
error.response &&
[429, 500, 502, 503, 504].includes(error.response.status)
) {
let wait;
const log = [`Got a status code of ${error.response.status}.`];
if (error.response.headers) {
try {
const {
"ratelimit-reset": rateLimitReset,
"ratelimit-resettime": rateLimitResetTime,
"retry-after": retryAfter,
} = error.response.headers;
if (rateLimitReset) {
wait = parseInt(rateLimitReset, 10) * 1000 - new Date().getTime();
log.push(
`Found a ratelimit-reset header, waiting until ${rateLimitResetTime}.`
);
}
if (retryAfter) {
wait = parseInt(retryAfter, 10) * 1000;
log.push(`Found a retry-after header (${retryAfter}).`);
}
} catch (e) {}
}
if (!wait) {
wait = 2 ** retries * 100;
}
log.push(`Waiting ${wait} ms`);
if (logger) {
logger(log.join(" "));
}
await timeout(wait);
return retries + 1;
} else {
throw error;
}
};
const getTokenFromProcess = () =>
process &&
process.env &&
(process.env.GITLAB_TOKEN || process.env.DANGER_GITLAB_API_TOKEN);
const GitLabAPIFactory = (axiosInstance, options = {}) => {
const {
maxRetries = 5,
baseURL = "https://gitlab.com/api/v4/",
privateToken,
logger,
} = options;
const token = privateToken || getTokenFromProcess();
if (!token) {
throw new Error(
"Please provide a GitLab token as an ENV variable via GITLAB_TOKEN or DANGER_GITLAB_API_TOKEN"
);
}
axiosInstance.defaults.baseURL = baseURL;
axiosInstance.defaults.headers.common["PRIVATE-TOKEN"] = token;
return new Proxy(axiosInstance, {
get(target, prop) {
if (requestMethods.includes(prop)) {
return async (...args) => {
let retries = 0;
do {
try {
return await target[prop](...args);
} catch (e) {
if (retries >= maxRetries) {
throw e;
}
retries = await waitBeforeRetry(e, retries, logger);
}
} while (true);
};
}
return target[prop];
},
});
};
/**
* @deprecated
* @param options
*/
const deprecatedFactory = (options = {}) => {
const { maxRetries, baseURL, privateToken, ...axiosOptions } = options;
const _gitlabAPI = _defaultAxios.create({
...axiosOptions,
});
return GitLabAPIFactory(_gitlabAPI, {
maxRetries,
baseURL,
privateToken,
logger: console.warn,
});
};
module.exports = deprecatedFactory;
module.exports.setupGitLabAPI = GitLabAPIFactory;