UNPKG

@redocly/cli

Version:

[@Redocly](https://redocly.com) CLI is your all-in-one OpenAPI utility. It builds, manages, improves, and quality-checks your OpenAPI descriptions, all of which comes in handy for various phases of the API Lifecycle. Create your own rulesets to make API g

155 lines (137 loc) โ€ข 4.61 kB
import { performance } from 'perf_hooks'; import { blue, gray, green, yellow } from 'colorette'; import { writeFileSync } from 'fs'; import { formatProblems, getTotals, getMergedConfig, bundle } from '@redocly/openapi-core'; import { dumpBundle, getExecutionTime, getFallbackApisOrExit, getOutputFileName, handleError, printUnusedWarnings, saveBundle, sortTopLevelKeysForOas, checkForDeprecatedOptions, formatPath, } from '../utils/miscellaneous'; import type { OutputExtensions, Skips, Totals, VerifyConfigOptions } from '../types'; import type { CommandArgs } from '../wrapper'; export type BundleOptions = { apis?: string[]; extends?: string[]; output?: string; ext?: OutputExtensions; dereferenced?: boolean; force?: boolean; metafile?: string; 'remove-unused-components'?: boolean; 'keep-url-references'?: boolean; } & Skips & VerifyConfigOptions; export async function handleBundle({ argv, config, version, collectSpecData, }: CommandArgs<BundleOptions>) { const removeUnusedComponents = argv['remove-unused-components'] || config.rawConfig?.styleguide?.decorators?.hasOwnProperty('remove-unused-components'); const apis = await getFallbackApisOrExit(argv.apis, config); const totals: Totals = { errors: 0, warnings: 0, ignored: 0 }; const deprecatedOptions: Array<keyof BundleOptions> = []; checkForDeprecatedOptions(argv, deprecatedOptions); for (const { path, alias, output } of apis) { try { const startedAt = performance.now(); const resolvedConfig = getMergedConfig(config, alias); const { styleguide } = resolvedConfig; styleguide.skipPreprocessors(argv['skip-preprocessor']); styleguide.skipDecorators(argv['skip-decorator']); process.stderr.write(gray(`bundling ${formatPath(path)}...\n`)); const { bundle: result, problems, ...meta } = await bundle({ config: resolvedConfig, ref: path, dereference: argv.dereferenced, removeUnusedComponents, keepUrlRefs: argv['keep-url-references'], collectSpecData, }); const fileTotals = getTotals(problems); const { outputFile, ext } = getOutputFileName({ entrypoint: path, output, argvOutput: argv.output, ext: argv.ext, entries: argv?.apis?.length || 0, }); if (fileTotals.errors === 0 || argv.force) { if (!outputFile) { const bundled = dumpBundle( sortTopLevelKeysForOas(result.parsed), argv.ext || 'yaml', argv.dereferenced ); process.stdout.write(bundled); } else { const bundled = dumpBundle(sortTopLevelKeysForOas(result.parsed), ext, argv.dereferenced); saveBundle(outputFile, bundled); } } totals.errors += fileTotals.errors; totals.warnings += fileTotals.warnings; totals.ignored += fileTotals.ignored; formatProblems(problems, { format: 'codeframe', totals: fileTotals, version, }); if (argv.metafile) { if (apis.length > 1) { process.stderr.write( yellow(`[WARNING] "--metafile" cannot be used with multiple apis. Skipping...`) ); } { writeFileSync(argv.metafile, JSON.stringify(meta), 'utf-8'); } } const elapsed = getExecutionTime(startedAt); if (fileTotals.errors > 0) { if (argv.force) { process.stderr.write( `โ“ Created a bundle for ${blue(formatPath(path))} at ${blue( outputFile || 'stdout' )} with errors ${green(elapsed)}.\n${yellow('Errors ignored because of --force')}.\n` ); } else { process.stderr.write( `โŒ Errors encountered while bundling ${blue( formatPath(path) )}: bundle not created (use --force to ignore errors).\n` ); } } else { process.stderr.write( `๐Ÿ“ฆ Created a bundle for ${blue(formatPath(path))} at ${blue( outputFile || 'stdout' )} ${green(elapsed)}.\n` ); } const removedCount = meta.visitorsData?.['remove-unused-components']?.removedCount; if (removedCount) { process.stderr.write(gray(`๐Ÿงน Removed ${removedCount} unused components.\n`)); } } catch (e) { handleError(e, path); } } printUnusedWarnings(config.styleguide); if (!(totals.errors === 0 || argv.force)) { throw new Error('Bundle failed.'); } }