UNPKG

bump-cli

Version:

The Bump CLI is used to interact with your API documentation hosted on Bump.sh by using the API of developers.bump.sh

161 lines (160 loc) 5.9 kB
import { Config } from '@oclif/core'; import { CLIError } from '@oclif/core/errors'; import debug from 'debug'; import { resolve } from 'node:path'; import { BumpApi } from '../api/index.js'; import { API } from '../definition.js'; export class Diff { // 120 seconds = 2 minutes static TIMEOUT = 120; _bump; _config; constructor(config) { if (config) { this._config = config; } } get bumpClient() { if (!this._bump) this._bump = new BumpApi(this._config); return this._bump; } get pollingPeriod() { return process.env.BUMP_POLLING_PERIOD ? Number(process.env.BUMP_POLLING_PERIOD) : 1000; } async createDiff(file1, file2, expires, overlays) { const api = await API.load(file1); const [previous_definition, previous_references] = await api.extractDefinition(undefined, overlays); const api2 = await API.load(file2); const [definition, references] = await api2.extractDefinition(undefined, overlays); const request = { definition, expires_at: expires, previous_definition, previous_references, references, }; const response = await this.bumpClient.postDiff(request); switch (response.status) { case 201: { this.d(`Diff created with ID ${response.data.id}`); this.d(response.data); return response.data; break; } case 204: { break; } } } async createVersion(file, documentation, token, hub, branch_name, previous_version_id = undefined, overlays) { const api = await API.load(file); const [definition, references] = await api.extractDefinition(undefined, overlays); const request = { branch_name, definition, documentation, hub, previous_version_id, references, unpublished: true, }; const response = await this.bumpClient.postVersion(request, token); switch (response.status) { case 201: { this.d(`Unpublished version created with ID ${response.data.id}`); return response.data; break; } case 204: { break; } } } // Function signature type taken from @types/debug // Debugger(formatter: any, ...args: any[]): void; /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ d(formatter, ...args) { return debug(`bump-cli:core:diff`)(formatter, ...args); } extractDiff(versionWithDiff) { // TODO: return a real diff_id in the GET /version API return { breaking: versionWithDiff.diff_breaking, details: versionWithDiff.diff_details, id: versionWithDiff.id, markdown: versionWithDiff.diff_markdown, public_url: versionWithDiff.diff_public_url, text: versionWithDiff.diff_summary, }; } isVersion(result) { return result.doc_public_url !== undefined; } isVersionWithDiff(result) { const { diff_details, diff_markdown, diff_summary } = result; return (diff_summary || diff_markdown || diff_details) !== undefined; } async pollingDelay() { await this.delay(this.pollingPeriod); } async run(file1, file2, documentation, hub, branch, token, format, expires, overlays) { if (!this._config) this._config = await Config.load(resolve(import.meta.dirname, './../../')); let diffVersion; if (file2 && (!documentation || !token)) { diffVersion = await this.createDiff(file1, file2, expires, overlays); } else { if (!documentation || !token) { throw new Error('Please login to bump (with documentation & token) when using a single file argument'); } diffVersion = await this.createVersion(file1, documentation, token, hub, branch, undefined, overlays); if (file2) { diffVersion = await this.createVersion(file2, documentation, token, hub, branch, diffVersion && diffVersion.id, overlays); } } if (diffVersion) { return this.waitResult(diffVersion, token, { format, timeout: Diff.TIMEOUT, }); } return undefined; } async waitResult(result, token, opts) { const pollingResponse = await (this.isVersion(result) && token ? this.bumpClient.getVersion(result.id, token) : this.bumpClient.getDiff(result.id, opts.format)); if (opts.timeout <= 0) { throw new CLIError('We were unable to compute your documentation diff. Sorry about that. Please try again later. If the error persists, please contact support at https://bump.sh.'); } switch (pollingResponse.status) { case 200: { let diff = pollingResponse.data; if (this.isVersionWithDiff(diff)) { diff = this.extractDiff(diff); } this.d('Received diff:'); this.d(diff); return diff; break; } case 202: { this.d('Waiting 1 sec before next poll'); await this.pollingDelay(); return this.waitResult(result, token, { format: opts.format, timeout: opts.timeout - 1, }); break; } } return {}; } async delay(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } }