Skip to content

Commit 05ad5c1

Browse files
authored
feat(oas): adding support for common parameter detection to the analyzer (#919)
## 🧰 Changes This adds support to `oas/analyzer` for surfacing information on if a given API definition utilizes [common parameters](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object). I've also gone through and updated a bunch of bad deep links to parts of the OAS. Would be nice if the OAI would stop breaking these deep links every couple of years.
1 parent 1a67b47 commit 05ad5c1

15 files changed

+136
-98
lines changed

packages/oas/README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ Because this library has full TypeScript types and docblocks this README is not
119119
<!-- prettier-ignore-start -->
120120
| Method | Description |
121121
| :--- | :--- |
122-
| `.getExtension()` | Retrieve a given [specification extension](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions) if it exists at the root of the API definition. |
123-
| `.hasExtension()` | Determine if a given [specification extension](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions) exists on the root of the API definition. |
122+
| `.getExtension()` | Retrieve a given [specification extension](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions) if it exists at the root of the API definition. |
123+
| `.hasExtension()` | Determine if a given [specification extension](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions) exists on the root of the API definition. |
124124
| `.validateExtension()` | Determine if a given [ReadMe custom OpenAPI extension](https://docs.readme.com/docs/openapi-extensions) is valid or not. |
125125
| `.validateExtensions()` | Validate all of our [ReadMe custom OpenAPI extension](https://docs.readme.com/docs/openapi-extensions), throwing exceptions when necessary. |
126126
<!-- prettier-ignore-end -->
@@ -153,7 +153,7 @@ const operation = petstore.operation('/pet', 'post');
153153
| Method | Description |
154154
| :--- | :--- |
155155
| `.getContentType()` | Retrieve the primary request body content type. If multiple are present, prefer whichever is JSON-compliant. |
156-
| `.getDescription()` | Retrieve the `description` that's set on this operation. This supports common descriptions that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject). |
156+
| `.getDescription()` | Retrieve the `description` that's set on this operation. This supports common descriptions that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object). |
157157
| `.getOperationId()` | Retrieve the `operationId` that's present on the operation, and if one is not present one will be created based off the method + path and returned instead. |
158158
| `.hasOperationId()` | Determine if the operation has an `operationId` present. |
159159
| `.isDeprecated()` | Determine if this operation is marked as deprecated. |
@@ -164,8 +164,8 @@ const operation = petstore.operation('/pet', 'post');
164164
| `.isWebhook()` | Determine if this operation is an instance of the `Webhook` class. |
165165
| `.getExampleGroups()` | Returns an object with groups of all example definitions (body/header/query/path/response/etc.). The examples are grouped by their key when defined via the `examples` map. |
166166
| `.getHeaders()` | Retrieve all headers that can either be sent for or returned from this operation. This includes header-based authentication schemes, common header parameters, and request body and response content types. |
167-
| `.getSummary()` | Retrieve the `summary` that's set on this operation. This supports common summaries that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject). |
168-
| `.getTags()` | Retrieve all tags, and [their metadata](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#tagObject), that exist on this operation. |
167+
| `.getSummary()` | Retrieve the `summary` that's set on this operation. This supports common summaries that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object). |
168+
| `.getTags()` | Retrieve all tags, and [their metadata](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#tag-object), that exist on this operation. |
169169
<!-- prettier-ignore-end -->
170170

171171
#### Callbacks
@@ -182,7 +182,7 @@ const operation = petstore.operation('/pet', 'post');
182182
#### Parameters
183183

184184
> [!NOTE]
185-
> All parameter accessors here support, and will automatically retrieve and handle, common parameters that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject).
185+
> All parameter accessors here support, and will automatically retrieve and handle, common parameters that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object).
186186
187187
<!-- prettier-ignore-start -->
188188
| Method | Description |
@@ -231,14 +231,14 @@ const operation = petstore.operation('/pet', 'post');
231231
<!-- prettier-ignore-start -->
232232
| Method | Description |
233233
| :--- | :--- |
234-
| `.hasExtension()` | Determine if a given [specification extension](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions) exists on this operation. |
234+
| `.hasExtension()` | Determine if a given [specification extension](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specification-extensions) exists on this operation. |
235235
<!-- prettier-ignore-end -->
236236

237237
Information about ReadMe's supported OpenAPI extensions at https://docs.readme.com/docs/openapi-extensions.
238238

239239
### Callbacks
240240

241-
The `Callback` class inherits `Operation` so every API available on instances of `Operation` is available here too. Much like `Operation`, we also support common parameters, summaries, and descriptions that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject) within a `callbacks` definition.
241+
The `Callback` class inherits `Operation` so every API available on instances of `Operation` is available here too. Much like `Operation`, we also support common parameters, summaries, and descriptions that may be set at the [path item level](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object) within a `callbacks` definition.
242242

243243
#### General
244244

@@ -285,6 +285,7 @@ console.log(await analyzer(petstore));
285285
| `additionalProperties` | Does your API use `additionalProperties`? |
286286
| `callbacks` | Does your API use [callbacks](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#callback-object)? |
287287
| `circularRefs` | Does your API have any circular `$ref` pointers, and if so where are they located? |
288+
| `commonParameters` | Does your API utilize [common parameters](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object)? |
288289
| `discriminators` | Does your API use polymorphic [discriminators](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#discriminator-object)? |
289290
| `links` | Does your API use [links](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#link-object)? |
290291
| `style` | Do any parameters in your API require [style](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#user-content-parameterstyle) serialization?

packages/oas/src/analyzer/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default async function analyzer(definition: OASDocument): Promise<OASAnal
1414
const additionalProperties = OPENAPI_QUERIES.additionalProperties(definition);
1515
const callbacks = OPENAPI_QUERIES.callbacks(definition);
1616
const circularRefs = await OPENAPI_QUERIES.circularRefs(definition);
17+
const commonParameters = OPENAPI_QUERIES.commonParameters(definition);
1718
const discriminators = OPENAPI_QUERIES.discriminators(definition);
1819
const links = OPENAPI_QUERIES.links(definition);
1920
const parameterSerialization = OPENAPI_QUERIES.parameterSerialization(definition);
@@ -60,6 +61,10 @@ export default async function analyzer(definition: OASDocument): Promise<OASAnal
6061
present: !!circularRefs.length,
6162
locations: circularRefs,
6263
},
64+
commonParameters: {
65+
present: !!commonParameters.length,
66+
locations: commonParameters,
67+
},
6368
discriminators: {
6469
present: !!discriminators.length,
6570
locations: discriminators,

packages/oas/src/analyzer/queries/openapi.ts

+25-15
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export function additionalProperties(definition: OASDocument) {
1616
/**
1717
* Determine if a given API definition utilizes `callbacks`.
1818
*
19-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callbackObject}
20-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#callbackObject}
19+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callback-object}
20+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#callback-object}
2121
*/
2222
export function callbacks(definition: OASDocument) {
2323
return query(['$.components.callbacks', '$.paths..callbacks'], definition).map(res => refizePointer(res.pointer));
@@ -42,11 +42,21 @@ export async function circularRefs(definition: OASDocument) {
4242
return results;
4343
}
4444

45+
/**
46+
* Determine if a given API definition utilizes common parameters.
47+
*
48+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#path-item-object}
49+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-item-object}
50+
*/
51+
export function commonParameters(definition: OASDocument) {
52+
return query(['$..paths[*].parameters'], definition).map(res => refizePointer(res.pointer));
53+
}
54+
4555
/**
4656
* Determine if a given API definition utilizes discriminators.
4757
*
48-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#discriminatorObject}
49-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#discriminatorObject}
58+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#discriminator-object}
59+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#discriminator-object}
5060
*/
5161
export function discriminators(definition: OASDocument) {
5262
return query(['$..discriminator'], definition).map(res => refizePointer(res.pointer));
@@ -55,8 +65,8 @@ export function discriminators(definition: OASDocument) {
5565
/**
5666
* Determine if a given API definition utilizes `links`.
5767
*
58-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#linkObject}
59-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#linkObject}
68+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#link-object}
69+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#link-object}
6070
*/
6171
export function links(definition: OASDocument) {
6272
return query(['$..links'], definition).map(res => refizePointer(res.pointer));
@@ -114,8 +124,8 @@ export function polymorphism(definition: OASDocument) {
114124
/**
115125
* Determine every kind of security type that a given API definition has documented.
116126
*
117-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securitySchemeObject}
118-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#securitySchemeObject}
127+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-scheme-object}
128+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#security-scheme-object}
119129
*/
120130
export function securityTypes(definition: OASDocument) {
121131
return Array.from(new Set(query(['$.components.securitySchemes..type'], definition).map(res => res.value as string)));
@@ -124,8 +134,8 @@ export function securityTypes(definition: OASDocument) {
124134
/**
125135
* Determine if a given API definition utilizes server variables.
126136
*
127-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#serverVariableObject}
128-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#serverVariableObject}
137+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-variable-object}
138+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#server-variable-object}
129139
*/
130140
export function serverVariables(definition: OASDocument) {
131141
return query(['$.servers..variables^'], definition).map(res => refizePointer(res.pointer));
@@ -134,8 +144,8 @@ export function serverVariables(definition: OASDocument) {
134144
/**
135145
* Determine how many operations are defined in a given API definition.
136146
*
137-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operationObject}
138-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#operationObject}
147+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object}
148+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#operation-object}
139149
*/
140150
export function totalOperations(definition: OASDocument) {
141151
return query(['$..paths[*]'], definition)
@@ -146,7 +156,7 @@ export function totalOperations(definition: OASDocument) {
146156
/**
147157
* Determine if a given API definition utilizes `webhooks` support in OpenAPI 3.1.
148158
*
149-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oasObject}
159+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oasWebhooks}
150160
*/
151161
export function webhooks(definition: OASDocument) {
152162
return query(['$.webhooks[*]'], definition).map(res => refizePointer(res.pointer));
@@ -156,8 +166,8 @@ export function webhooks(definition: OASDocument) {
156166
* Determine if a given API definition has XML schemas, payloads, or responses.
157167
*
158168
* @todo detect `+xml` media types
159-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xmlObject}
160-
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xmlObject}
169+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-object}
170+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#xml-object}
161171
*/
162172
export function xml(definition: OASDocument) {
163173
return query(

packages/oas/src/analyzer/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface OASAnalysis {
1818
additionalProperties: OASAnalysisFeature;
1919
callbacks: OASAnalysisFeature;
2020
circularRefs: OASAnalysisFeature;
21+
commonParameters: OASAnalysisFeature;
2122
discriminators: OASAnalysisFeature;
2223
links: OASAnalysisFeature;
2324
polymorphism: OASAnalysisFeature;

0 commit comments

Comments
 (0)