@redocly/cli
Version:
[@Redocly](https://redocly.com) CLI is your all-in-one API documentation utility. It builds, manages, improves, and quality-checks your API descriptions, all of which comes in handy for various phases of the API Lifecycle. Create your own rulesets to make
124 lines • 4.61 kB
JavaScript
import { logger } from '@redocly/openapi-core';
import { exitWithError } from '../../../utils/error.js';
export async function fetchRemoteScorecardAndPlugins({ projectUrl, auth, isApiKey = false, verbose = false, }) {
if (verbose) {
logger.info(`Starting fetch for remote scorecard configuration...\n`);
}
const parsedProjectUrl = parseProjectUrl(projectUrl);
if (!parsedProjectUrl) {
exitWithError(`Invalid project URL format: ${projectUrl}`);
}
const { residency, orgSlug, projectSlug } = parsedProjectUrl;
try {
const project = await fetchProjectConfigBySlugs({
residency,
orgSlug,
projectSlug,
auth,
isApiKey,
verbose,
});
const scorecard = project?.config.scorecardClassic || project?.config.scorecard;
if (!scorecard) {
throw new Error('No scorecard configuration found.');
}
if (verbose) {
logger.info(`Successfully fetched scorecard configuration.\n`);
logger.info(`Scorecard levels found: ${scorecard.levels?.length || 0}\n`);
}
const plugins = project.config.pluginsUrl
? await fetchPlugins(project.config.pluginsUrl, verbose)
: undefined;
if (verbose) {
if (plugins) {
logger.info(`Successfully fetched plugins from ${project.config.pluginsUrl}\n`);
}
else if (project.config.pluginsUrl) {
logger.info(`No plugins were loaded from ${project.config.pluginsUrl}\n`);
}
else {
logger.info(`No custom plugins configured for this scorecard.\n`);
}
}
return {
scorecard: scorecard,
plugins,
};
}
catch (error) {
if (verbose) {
logger.error(`❌ Failed to fetch remote scorecard configuration.\n`);
logger.error(`Error details: ${error.message}\n`);
if (error.stack) {
logger.error(`Stack trace:\n${error.stack}\n`);
}
}
exitWithError(error.message);
}
}
function parseProjectUrl(projectUrl) {
const url = new URL(projectUrl);
const match = url.pathname.match(/\/org\/(?<orgSlug>[^/]+)\/project\/(?<projectSlug>[^/]+)/);
if (!match?.groups) {
return;
}
const { orgSlug, projectSlug } = match.groups;
return {
residency: url.origin,
orgSlug,
projectSlug,
};
}
async function fetchProjectConfigBySlugs({ residency, orgSlug, projectSlug, auth, isApiKey, verbose = false, }) {
const authHeaders = createAuthHeaders(auth, isApiKey);
const projectUrl = new URL(`${residency}/api/orgs/${orgSlug}/projects/${projectSlug}`);
const projectResponse = await fetch(projectUrl, { headers: authHeaders });
if (verbose) {
logger.info(`Project fetch response status: ${projectResponse.status}\n`);
}
if (projectResponse.status === 401 || projectResponse.status === 403) {
if (verbose) {
logger.error(`Authentication failed with status ${projectResponse.status}.\n`);
logger.error(`Check that your credentials are valid and have the necessary permissions.\n`);
}
throw new Error(`Unauthorized access to project: ${projectSlug}. Please check your credentials.`);
}
if (projectResponse.status !== 200) {
throw new Error(`Failed to fetch project: ${projectSlug}. Status: ${projectResponse.status}`);
}
if (verbose) {
logger.info(`Successfully received project configuration.\n`);
}
return projectResponse.json();
}
async function fetchPlugins(pluginsUrl, verbose = false) {
if (verbose) {
logger.info(`Fetching plugins from: ${pluginsUrl}\n`);
}
try {
const pluginsResponse = await fetch(pluginsUrl);
if (verbose) {
logger.info(`Plugins fetch response status: ${pluginsResponse.status}\n`);
}
if (pluginsResponse.status !== 200) {
if (verbose) {
logger.error(`Failed to fetch plugins\n`);
}
return;
}
return pluginsResponse.text();
}
catch (error) {
if (verbose) {
logger.error(`Error fetching plugins: ${error.message}\n`);
}
return;
}
}
function createAuthHeaders(auth, isApiKey) {
if (isApiKey) {
return { Authorization: `Bearer ${auth}` };
}
return { Cookie: `accessToken=${auth}` };
}
//# sourceMappingURL=fetch-scorecard.js.map