UNPKG

@contentstack/cli-cm-seed

Version:

create a Stack from existing content types, entries, assets, etc.

141 lines (140 loc) 5.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tar = require("tar"); const zlib = require("zlib"); const https = require("https"); const mkdirp = require("mkdirp"); const cli_utilities_1 = require("@contentstack/cli-utilities"); const error_1 = require("./error"); class GitHubClient { static parsePath(path) { const result = { username: '', repo: '', }; if (path) { const parts = path.split('/'); result.username = parts[0]; if (parts.length === 2) { result.repo = parts[1]; } } return result; } constructor(username, defaultStackPattern) { this.username = username; this.gitHubRepoUrl = `https://api.github.com/repos/${username}`; this.gitHubUserUrl = `https://api.github.com/search/repositories?q=org%3A${username}+in:name+${defaultStackPattern}`; this.httpClient = cli_utilities_1.HttpClient.create(); } async getAllRepos(count = 100) { try { const response = await this.httpClient.get(`${this.gitHubUserUrl}&per_page=${count}`); return response.data.items; } catch (error) { throw this.buildError(error); } } async getLatest(repo, destination) { const tarballUrl = await this.getLatestTarballUrl(repo); const releaseStream = await this.streamRelease(tarballUrl); await mkdirp(destination); return this.extract(destination, releaseStream); } makeHeadApiCall(repo) { return new Promise((resolve, reject) => { const { host, pathname } = new URL(this.gitHubRepoUrl); const options = { host, method: 'HEAD', path: `${pathname}/${repo}/contents`, headers: { 'user-agent': 'node.js' }, }; https.request(options, resolve).on('error', reject).end(); }); } makeGetApiCall(repo) { return new Promise((resolve, reject) => { const { host, pathname } = new URL(this.gitHubRepoUrl); const options = { host, method: 'GET', path: `${pathname}/${repo}/contents`, headers: { 'user-agent': 'node.js' }, }; https.request(options, (response) => { let responseBody = ''; const data = { statusCode: response.statusCode, }; if (data.statusCode === 403) { const xRateLimitReset = response.rawHeaders[response.rawHeaders.indexOf('X-RateLimit-Reset') + 1]; const startDate = (new Date()).getTime() / 1000; const diffInSeconds = Number(xRateLimitReset) - startDate; data.statusMessage = `Exceeded requests limit. Please try again after ${(diffInSeconds / 60).toFixed(1)} minutes.`; } response.on('data', (chunk) => { responseBody += chunk.toString(); }); response.on('end', () => { const body = JSON.parse(responseBody); resolve(Object.assign(Object.assign({}, data), { data: body })); }); }).on('error', reject).end(); }); } async checkIfRepoExists(repo) { try { /** * Old code. Keeping it for reference. * * `const response: any = await this.httpClient.send('HEAD', `${this.gitHubRepoUrl}/${repo}/contents`);` * * `return response.status === 200;` */ const response = await this.makeHeadApiCall(repo); return response.statusCode === 200; } catch (error) { console.log(error); // do nothing } return false; } async getLatestTarballUrl(repo) { try { const response = await this.httpClient.get(`${this.gitHubRepoUrl}/${repo}/releases/latest`); return response.data.tarball_url; } catch (error) { throw this.buildError(error); } } async streamRelease(url) { const response = await this.httpClient .options({ responseType: 'stream', }) .get(url); this.httpClient.resetConfig(); return response.data; } async extract(destination, stream) { return new Promise((resolve, reject) => { stream .pipe(zlib.createUnzip()) .pipe(tar.extract({ cwd: destination, strip: 1, })) .on('end', () => resolve()) .on('error', reject); }); } buildError(error) { var _a; const message = ((_a = error.response.data) === null || _a === void 0 ? void 0 : _a.error_message) || error.response.statusText; const status = error.response.status; return new error_1.default(message, status); } } exports.default = GitHubClient;