-
Notifications
You must be signed in to change notification settings - Fork 43
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
feat(openapi): introduction of a new openapi:inspect
command
#698
Conversation
@@ -34,7 +34,7 @@ export default class OpenAPICommand extends Command { | |||
super(); | |||
|
|||
this.command = 'openapi'; | |||
this.usage = 'openapi [file] [options]'; | |||
this.usage = 'openapi [file|url] [options]'; |
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.
oas-normalize, which all of these commands use for spec processing, handles URLs so we should document in these commands that you can supply them either of these.
@kanadgupta This is still a WIP but I'd love if you could take a look now before I start to write tests for the command. Here's the commands you can use to test: Full report
Feature report
Feature report (fancy syntax)
I don't much care for the way the feature report screen looks at the moment:
|
Just played around, really loving it!
What if this function returned a
Yeah I like this "show all extension usage" approach! Our extensions may change over time too so I don't really think those are conventions our users should need to know. Now that I'm thinking about it, it'd be cool2 if we had our extensions documented in the TS types in
👍🏽 Footnotes
|
circularRefs: | ||
· #/components/schemas/MultiPart/properties/parent | ||
· #/components/schemas/ZoneOffset/properties/rules" |
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.
👀
This was made possible by some improvements to oas1, @readme/openapi-parser2 and @readme/json-schema-ref-parser3 to give us access to the $ref
pointers in API specs that are circular. Previously all we had to go off on was "are there still $ref
pointers remaining in a spec" after dereferencing and with the way that dereferencing works if it encounters a circular ref in a $ref
tree it'll stop dereferencing that tree completely, leaving everything in tact.
Footnotes
__tests__/cmds/openapi/uses.test.ts
Outdated
@@ -0,0 +1,81 @@ | |||
/* eslint-disable jest/no-conditional-expect */ |
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.
eslint-plugin-jest
doesn't like me doing expect()
calls inside a try-catch
and it wants me to instead write a wrapper for the command call and no thanks I'd rather not.
@@ -47,17 +47,19 @@ | |||
"form-data": "^4.0.0", | |||
"gray-matter": "^4.0.1", | |||
"ignore": "^5.2.0", | |||
"jsonpath": "^1.1.1", | |||
"jsonpath-plus": "^7.2.0", |
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.
I swapped this out because I'm using jsonpath-plus
in oas
for this new analyzer
library and it doesn't make sense to have rdme ship both in users' node_modules/
directories.
Why did I use jsonpath-plus
instead of jsonpath? jsonpath-plus has a nicer API, a larger install base, and has been recently updated within the past few months vs 2 years.
"prompts": "^2.4.2", | ||
"semver": "^7.0.0", | ||
"simple-git": "^3.13.0", | ||
"table": "^6.8.1", |
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.
src/cmds/openapi/uses.ts
Outdated
if (hasUnusedFeature) { | ||
// If we have any unused features we should reject the command with a soft error so we | ||
// output the report as normal but return a `exit(1)` status code. | ||
return Promise.reject(new SoftError(report)); |
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.
We talked about doing this as a Promise.allSettled
but it was much easier to have this.buildFeaturesReport
return a boolean for this instead of overhauling the already complex report composition to fit into the structure of a Promise.
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.
makes sense to me! really dig this SoftError
pattern
|
||
const OPENAPI_FEATURE_DOCS: Record<keyof Analysis['openapi'], Pick<AnalyzedFeature, 'description' | 'url'>> = { | ||
additionalProperties: { | ||
description: 'additionalProperties allows you to document dictionaries where the keys are user-supplied strings.', |
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.
All of these descriptions could definitely use some work I'm sure.
// OpenAPI features | ||
...Object.keys(OPENAPI_FEATURE_DOCS), | ||
|
||
'readme', // A catch-all for ReadMe features and extensions. Will look for everything. |
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.
Because having people do --feature=x-readme.explorer-enable
is gnar they can do --feature=readme
and we'll just query all of their ReadMe extension and feature usage instead. They won't be able to do piecemeal lookups on these but they get a cleaner API instead looking for some of the data they want.
@@ -5,7 +5,7 @@ | |||
"downlevelIteration": true, | |||
"esModuleInterop": true, | |||
"experimentalDecorators": true, | |||
"lib": ["es2020"], | |||
"lib": ["es2020", "ES2021.Intl"], |
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.
Pulling Intl
in because I'm using Intl.ListFormat to make composing "feature, feature, and feature" sentence fragments a lot easier.
@kanadgupta @darrenyong @Dashron I found a bunch of small UI bugs last night while looking again at the screenshots I made which just pushed up a bunch of fixes for so this is finally ready for review now. |
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.
mostly small nits, but this feels great when playing around locally and I'm super excited 😌
src/cmds/openapi/uses.ts
Outdated
if (hasUnusedFeature) { | ||
// If we have any unused features we should reject the command with a soft error so we | ||
// output the report as normal but return a `exit(1)` status code. | ||
return Promise.reject(new SoftError(report)); |
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.
makes sense to me! really dig this SoftError
pattern
Co-authored-by: Kanad Gupta <[email protected]>
Co-authored-by: Kanad Gupta <[email protected]>
openapi:uses
commandopenapi:inspect
command
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.
🥳
🧰 Changes
This introduces a new
openapi:uses
openapi:inspect
command that does a series of analyses on API definitions across a series of OpenAPI and ReadMe-speciifc datapoints.💽 Datapoints
OpenAPI
additionalProperties
?callbacks
?$ref
pointers in the spec? Where are they?discriminator
in polymorphic schemas?links
?anyof
,allOf
, andoneOf
) for composing themselves?webhooks
feature for describing webhooks?ReadMe
And we also look for usage of ReadMe's OpenAPI extensions:
x-default
x-readme.code-samples
x-readme.headers
x-readme.explorer-enabled
x-readme.proxy-enabled
x-readme.samples-languages
As well as some deprecated extensions that we've got:
x-readme.samples-enabled
RAW_BODY
(not technically an extension but a quirk of our Manual API editor)📽️ Demo
Screen.Recording.2022-12-02.at.5.28.49.PM.mov
🧬 QA & Testing
Easier to test this locally with a full build instead of using
ts-node
so runnpm run build
and then these commands:Full report
Feature report
Feature report (fancy syntax)