-
Notifications
You must be signed in to change notification settings - Fork 48
refactor(openapi): cleaner approach to prepareOas helper
#1312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,13 @@ | ||
| import type { OpenAPI } from 'openapi-types'; | ||
| import type { CommandIdForTopic } from '../index.js'; | ||
| import type { CommandIdForTopic, OpenAPICommands } from '../index.js'; | ||
|
|
||
| import chalk from 'chalk'; | ||
| import OASNormalize from 'oas-normalize'; | ||
| import { getAPIDefinitionType } from 'oas-normalize/lib/utils'; | ||
| import ora from 'ora'; | ||
|
|
||
| import isCI from './isCI.js'; | ||
| import { debug, info, oraOptions } from './logger.js'; | ||
| import { oraOptions } from './logger.js'; | ||
| import promptTerminal from './promptWrapper.js'; | ||
| import readdirRecursive from './readdirRecursive.js'; | ||
|
|
||
|
|
@@ -49,26 +49,9 @@ function capitalizeSpecType<T extends 'openapi' | 'postman' | 'swagger' | 'unkno | |
| /** | ||
| * Normalizes, validates, and (optionally) bundles an OpenAPI definition. | ||
| */ | ||
| export default async function prepareOas( | ||
| /** | ||
| * Path to a spec file. If this is missing, the current directory is searched for | ||
| * certain file names. | ||
| */ | ||
| path: string | undefined, | ||
| /** | ||
| * The command context in which this is being run within (uploading a spec, | ||
| * validation, or reducing one). | ||
| */ | ||
| command: `openapi ${OpenAPIAction}`, | ||
| opts: { | ||
| /** | ||
| * An optional title to replace the value in the `info.title` field. | ||
| * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#info-object} | ||
| */ | ||
| title?: string; | ||
| } = {}, | ||
| ) { | ||
| let specPath = path; | ||
| export default async function prepareOas(this: OpenAPICommands) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. args are no longer required since we can grab all of it from the |
||
| let specPath = this.args.spec; | ||
| const command = this.id satisfies `openapi ${OpenAPIAction}`; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this allows us to assert that the command |
||
|
|
||
| if (!specPath) { | ||
| /** | ||
|
|
@@ -97,31 +80,31 @@ export default async function prepareOas( | |
| file.toLowerCase().endsWith('.yml'), | ||
| ); | ||
|
|
||
| debug(`number of JSON or YAML files found: ${jsonAndYamlFiles.length}`); | ||
| this.debug(`number of JSON or YAML files found: ${jsonAndYamlFiles.length}`); | ||
|
|
||
| const possibleSpecFiles: FoundSpecFile[] = ( | ||
| await Promise.all( | ||
| jsonAndYamlFiles.map(file => { | ||
| debug(`attempting to oas-normalize ${file}`); | ||
| this.debug(`attempting to oas-normalize ${file}`); | ||
| const oas = new OASNormalize(file, { enablePaths: true }); | ||
| return oas | ||
| .version() | ||
| .then(({ specification, version }) => { | ||
| debug(`specification type for ${file}: ${specification}`); | ||
| debug(`version for ${file}: ${version}`); | ||
| this.debug(`specification type for ${file}: ${specification}`); | ||
| this.debug(`version for ${file}: ${version}`); | ||
| return ['openapi', 'swagger', 'postman'].includes(specification) | ||
| ? { filePath: file, specType: capitalizeSpecType(specification) as SpecType, version } | ||
| : null; | ||
| }) | ||
| .catch(e => { | ||
| debug(`error extracting API definition specification version for ${file}: ${e.message}`); | ||
| this.debug(`error extracting API definition specification version for ${file}: ${e.message}`); | ||
| return null; | ||
| }); | ||
| }), | ||
| ) | ||
| ).filter(truthy); | ||
|
|
||
| debug(`number of possible OpenAPI/Swagger files found: ${possibleSpecFiles.length}`); | ||
| this.debug(`number of possible OpenAPI/Swagger files found: ${possibleSpecFiles.length}`); | ||
|
|
||
| if (!possibleSpecFiles.length) { | ||
| fileFindingSpinner.fail(); | ||
|
|
@@ -134,7 +117,7 @@ export default async function prepareOas( | |
|
|
||
| if (possibleSpecFiles.length === 1) { | ||
| fileFindingSpinner.stop(); | ||
| info(chalk.yellow(`We found ${specPath} and are attempting to ${action} it.`)); | ||
| this.info(chalk.yellow(`We found ${specPath} and are attempting to ${action} it.`)); | ||
| } else if (possibleSpecFiles.length > 1) { | ||
| if (isCI()) { | ||
| fileFindingSpinner.fail(); | ||
|
|
@@ -160,9 +143,9 @@ export default async function prepareOas( | |
|
|
||
| const spinner = ora({ text: `Validating the API definition located at ${specPath}...`, ...oraOptions() }).start(); | ||
|
|
||
| debug(`about to normalize spec located at ${specPath}`); | ||
| this.debug(`about to normalize spec located at ${specPath}`); | ||
| const oas = new OASNormalize(specPath, { colorizeErrors: true, enablePaths: true }); | ||
| debug('spec normalized'); | ||
| this.debug('spec normalized'); | ||
|
|
||
| // We're retrieving the original specification type here instead of after validation because if | ||
| // they give us a Postman collection we should tell them that we handled a Postman collection, not | ||
|
|
@@ -182,42 +165,42 @@ export default async function prepareOas( | |
| }) | ||
| .catch((err: Error) => { | ||
| spinner.fail(); | ||
| debug(`raw oas load error object: ${JSON.stringify(err)}`); | ||
| this.debug(`raw oas load error object: ${JSON.stringify(err)}`); | ||
| throw err; | ||
| }); | ||
|
|
||
| let api: OpenAPI.Document; | ||
| await oas.validate().catch((err: Error) => { | ||
| spinner.fail(); | ||
| debug(`raw validation error object: ${JSON.stringify(err)}`); | ||
| this.debug(`raw validation error object: ${JSON.stringify(err)}`); | ||
| throw err; | ||
| }); | ||
|
|
||
| // If we were supplied a Postman collection this will **always** convert it to OpenAPI 3.0. | ||
| debug('converting the spec to OpenAPI 3.0 (if necessary)'); | ||
| this.debug('converting the spec to OpenAPI 3.0 (if necessary)'); | ||
| api = await oas.convert().catch((err: Error) => { | ||
| spinner.fail(); | ||
| debug(`raw openapi conversion error object: ${JSON.stringify(err)}`); | ||
| this.debug(`raw openapi conversion error object: ${JSON.stringify(err)}`); | ||
| throw err; | ||
| }); | ||
|
|
||
| spinner.stop(); | ||
|
|
||
| debug('πππππ spec validated! logging spec below πππππ'); | ||
| debug(api); | ||
| debug('πππππ finished logging spec πππππ'); | ||
| debug(`spec type: ${specType}`); | ||
| this.debug('πππππ spec validated! logging spec below πππππ'); | ||
| this.debug(api); | ||
| this.debug('πππππ finished logging spec πππππ'); | ||
| this.debug(`spec type: ${specType}`); | ||
|
|
||
| if (opts.title) { | ||
| debug(`renaming title field to ${opts.title}`); | ||
| api.info.title = opts.title; | ||
| if (this.flags.title) { | ||
| this.debug(`renaming title field to ${this.flags.title}`); | ||
| api.info.title = this.flags.title; | ||
| } | ||
|
|
||
| const specFileType = oas.type; | ||
|
|
||
| // No need to optional chain here since `info.version` is required to pass validation | ||
| const specVersion: string = api.info.version; | ||
| debug(`version in spec: ${specVersion}`); | ||
| this.debug(`version in spec: ${specVersion}`); | ||
|
|
||
| const commandsThatBundle: (typeof command)[] = [ | ||
| 'openapi inspect', | ||
|
|
@@ -229,7 +212,7 @@ export default async function prepareOas( | |
| if (commandsThatBundle.includes(command)) { | ||
| api = await oas.bundle(); | ||
|
|
||
| debug('spec bundled'); | ||
| this.debug('spec bundled'); | ||
| } | ||
|
|
||
| return { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the resolve command doing with this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just for consistency i've mostly had it where every command that ends up outputting a new OAS file (i.e., pretty much every command besides
inspectandvalidate) could benefit from this flag since it allows people to set custominfo.titlefields on the output