oas 17.5.0 → 17.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/lib/dedupe-common-parameters.d.ts +9 -0
- package/@types/lib/get-schema.d.ts +1 -0
- package/@types/operation/get-parameters-as-json-schema.d.ts +3 -3
- package/@types/operation.d.ts +18 -3
- package/@types/rmoas.types.d.ts +9 -0
- package/CHANGELOG.md +37 -0
- package/dist/lib/dedupe-common-parameters.js +43 -0
- package/dist/lib/get-schema.js +1 -0
- package/dist/lib/openapi-to-json-schema.js +7 -11
- package/dist/operation/get-parameters-as-json-schema.js +29 -47
- package/dist/operation/get-response-examples.js +18 -4
- package/dist/operation.js +74 -5
- package/dist/samples/index.js +18 -13
- package/package.json +2 -2
- package/src/lib/dedupe-common-parameters.ts +25 -0
- package/src/lib/get-schema.ts +1 -0
- package/src/lib/openapi-to-json-schema.ts +7 -12
- package/src/operation/get-parameters-as-json-schema.ts +32 -57
- package/src/operation/get-response-examples.ts +8 -0
- package/src/operation.ts +85 -6
- package/src/rmoas.types.ts +9 -0
- package/src/samples/index.ts +18 -13
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as RMOAS from '../rmoas.types';
|
|
2
|
+
/**
|
|
3
|
+
* With an array of common parameters filter down them to what isn't already present in a list of non-common
|
|
4
|
+
* parameters.
|
|
5
|
+
*
|
|
6
|
+
* @param parameters
|
|
7
|
+
* @param commonParameters
|
|
8
|
+
*/
|
|
9
|
+
export default function dedupeCommonParameters(parameters: RMOAS.ParameterObject[], commonParameters: RMOAS.ParameterObject[]): import("openapi-types").OpenAPIV3.ParameterObject[];
|
|
@@ -5,6 +5,7 @@ import type * as RMOAS from '../rmoas.types';
|
|
|
5
5
|
*
|
|
6
6
|
* If the reference pointer looks like a `requestBodies` reference, then we also do a lookup for the actual schema.
|
|
7
7
|
*
|
|
8
|
+
* @deprecated
|
|
8
9
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields-8}
|
|
9
10
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#fixed-fields-8}
|
|
10
11
|
* @param operation Operation to look for a primary requestBody schema in.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { OASDocument,
|
|
1
|
+
import type { OASDocument, SchemaObject } from '../rmoas.types';
|
|
2
|
+
import type Operation from '../operation';
|
|
2
3
|
import * as RMOAS from '../rmoas.types';
|
|
3
4
|
export declare type SchemaWrapper = {
|
|
4
5
|
$schema?: string;
|
|
@@ -17,9 +18,8 @@ export declare const types: {
|
|
|
17
18
|
[key: keyof RMOAS.OASDocument]: string;
|
|
18
19
|
};
|
|
19
20
|
/**
|
|
20
|
-
* @param path
|
|
21
21
|
* @param operation
|
|
22
22
|
* @param api
|
|
23
23
|
* @param globalDefaults
|
|
24
24
|
*/
|
|
25
|
-
export default function getParametersAsJsonSchema(
|
|
25
|
+
export default function getParametersAsJsonSchema(operation: Operation, api: OASDocument, globalDefaults?: {}): SchemaWrapper[];
|
package/@types/operation.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
|
|
2
1
|
import type { RequestBodyExamples } from './operation/get-requestbody-examples';
|
|
3
2
|
import type { CallbackExamples } from './operation/get-callback-examples';
|
|
4
3
|
import type { ResponseExamples } from './operation/get-response-examples';
|
|
@@ -100,10 +99,14 @@ export default class Operation {
|
|
|
100
99
|
*
|
|
101
100
|
*/
|
|
102
101
|
isDeprecated(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Determine if the operation has any (non-request body) parameters.
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
hasParameters(): boolean;
|
|
103
107
|
/**
|
|
104
108
|
* Return the parameters (non-request body) on the operation.
|
|
105
109
|
*
|
|
106
|
-
* @todo This should also pull in common params.
|
|
107
110
|
*/
|
|
108
111
|
getParameters(): Array<RMOAS.ParameterObject>;
|
|
109
112
|
/**
|
|
@@ -134,14 +137,25 @@ export default class Operation {
|
|
|
134
137
|
*
|
|
135
138
|
*/
|
|
136
139
|
hasRequestBody(): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Retrieve the list of all available media types that the operations request body can accept.
|
|
142
|
+
*
|
|
143
|
+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject}
|
|
144
|
+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
145
|
+
*/
|
|
146
|
+
getRequestBodyMediaTypes(): string[];
|
|
137
147
|
/**
|
|
138
148
|
* Retrieve a specific request body content schema off this operation.
|
|
139
149
|
*
|
|
150
|
+
* If no media type is supplied this will return either the first available JSON-like request body, or the first
|
|
151
|
+
* available if there are no JSON-like media types present. When this return comes back it's in the form of an array
|
|
152
|
+
* with the first key being the selected media type, followed by the media type object in question.
|
|
153
|
+
*
|
|
140
154
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject}
|
|
141
155
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
142
156
|
* @param mediaType Specific request body media type to retrieve if present.
|
|
143
157
|
*/
|
|
144
|
-
getRequestBody(mediaType
|
|
158
|
+
getRequestBody(mediaType?: string): false | RMOAS.MediaTypeObject | [string, RMOAS.MediaTypeObject];
|
|
145
159
|
/**
|
|
146
160
|
* Retrieve an array of request body examples that this operation has.
|
|
147
161
|
*
|
|
@@ -219,6 +233,7 @@ export declare class Callback extends Operation {
|
|
|
219
233
|
getIdentifier(): string;
|
|
220
234
|
getSummary(): string;
|
|
221
235
|
getDescription(): string;
|
|
236
|
+
getParameters(): Array<RMOAS.ParameterObject>;
|
|
222
237
|
}
|
|
223
238
|
export declare class Webhook extends Operation {
|
|
224
239
|
}
|
package/@types/rmoas.types.d.ts
CHANGED
|
@@ -41,6 +41,15 @@ export declare type ServerVariableObject = OpenAPIV3.ServerVariableObject | Open
|
|
|
41
41
|
export declare type ServerVariablesObject = {
|
|
42
42
|
[variable: string]: ServerVariableObject;
|
|
43
43
|
};
|
|
44
|
+
export declare type ServerVariable = Record<string, string | number | Array<{
|
|
45
|
+
default?: string | number;
|
|
46
|
+
}> | {
|
|
47
|
+
default?: string | number;
|
|
48
|
+
} | Record<string, never>>;
|
|
49
|
+
export declare type Servers = {
|
|
50
|
+
selected: number;
|
|
51
|
+
variables: ServerVariable;
|
|
52
|
+
};
|
|
44
53
|
/**
|
|
45
54
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#componentsObject}
|
|
46
55
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#componentsObject}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,40 @@
|
|
|
1
|
+
## <small>17.7.2 (2022-02-02)</small>
|
|
2
|
+
|
|
3
|
+
* chore(deps-dev): bump @commitlint/cli from 16.0.1 to 16.1.0 (#591) ([a46f0ab](https://github.com/readmeio/oas/commit/a46f0ab)), closes [#591](https://github.com/readmeio/oas/issues/591)
|
|
4
|
+
* chore(deps-dev): bump @readme/eslint-config from 8.1.2 to 8.2.0 (#592) ([55554dc](https://github.com/readmeio/oas/commit/55554dc)), closes [#592](https://github.com/readmeio/oas/issues/592)
|
|
5
|
+
* chore(deps-dev): bump @readme/oas-examples from 4.3.2 to 4.4.0 (#588) ([fbdef2b](https://github.com/readmeio/oas/commit/fbdef2b)), closes [#588](https://github.com/readmeio/oas/issues/588)
|
|
6
|
+
* chore(deps-dev): bump @types/memoizee from 0.4.6 to 0.4.7 (#596) ([ccd1a3c](https://github.com/readmeio/oas/commit/ccd1a3c)), closes [#596](https://github.com/readmeio/oas/issues/596)
|
|
7
|
+
* chore(deps-dev): bump eslint from 8.6.0 to 8.8.0 (#593) ([d681a62](https://github.com/readmeio/oas/commit/d681a62)), closes [#593](https://github.com/readmeio/oas/issues/593)
|
|
8
|
+
* chore(deps-dev): bump eslint-plugin-jsdoc from 37.5.0 to 37.7.0 (#594) ([aa525ab](https://github.com/readmeio/oas/commit/aa525ab)), closes [#594](https://github.com/readmeio/oas/issues/594)
|
|
9
|
+
* chore(deps-dev): bump jest from 27.4.5 to 27.4.7 (#589) ([475c40b](https://github.com/readmeio/oas/commit/475c40b)), closes [#589](https://github.com/readmeio/oas/issues/589)
|
|
10
|
+
* chore(deps-dev): bump ts-jest from 27.1.2 to 27.1.3 (#595) ([c2ca154](https://github.com/readmeio/oas/commit/c2ca154)), closes [#595](https://github.com/readmeio/oas/issues/595)
|
|
11
|
+
* chore(deps-dev): bump typescript from 4.5.4 to 4.5.5 (#590) ([26bc893](https://github.com/readmeio/oas/commit/26bc893)), closes [#590](https://github.com/readmeio/oas/issues/590)
|
|
12
|
+
* chore(deps): bump swagger-inline from 5.0.2 to 5.0.4 (#597) ([c173d1e](https://github.com/readmeio/oas/commit/c173d1e)), closes [#597](https://github.com/readmeio/oas/issues/597)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## <small>17.7.1 (2022-01-31)</small>
|
|
17
|
+
|
|
18
|
+
* fix: bumping oas-normalize to fix a bug with header content validation (#587) ([c5594ee](https://github.com/readmeio/oas/commit/c5594ee)), closes [#587](https://github.com/readmeio/oas/issues/587)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## 17.7.0 (2022-01-27)
|
|
23
|
+
|
|
24
|
+
* fix: show response headers w/o mediaType content (#584) ([a9bccd1](https://github.com/readmeio/oas/commit/a9bccd1)), closes [#584](https://github.com/readmeio/oas/issues/584)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## 17.6.0 (2022-01-26)
|
|
29
|
+
|
|
30
|
+
* chore: add server variable typescript types (#586) ([0868626](https://github.com/readmeio/oas/commit/0868626)), closes [#586](https://github.com/readmeio/oas/issues/586)
|
|
31
|
+
* chore(deps): bumping node-fetch ([0f7dbe1](https://github.com/readmeio/oas/commit/0f7dbe1))
|
|
32
|
+
* fix: funky typing with how we extract examples during JSON Schema generation (#585) ([15ece60](https://github.com/readmeio/oas/commit/15ece60)), closes [#585](https://github.com/readmeio/oas/issues/585)
|
|
33
|
+
* refactor: cleaning up the messy `getSchema` library and other improvements (#581) ([f3f0e43](https://github.com/readmeio/oas/commit/f3f0e43)), closes [#581](https://github.com/readmeio/oas/issues/581)
|
|
34
|
+
* refactor: use default for samples over generic type (#582) ([c1b1c66](https://github.com/readmeio/oas/commit/c1b1c66)), closes [#582](https://github.com/readmeio/oas/issues/582)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
1
38
|
## 17.5.0 (2022-01-12)
|
|
2
39
|
|
|
3
40
|
* feat: addition of a getRequestBody accessor (#580) ([88b0b33](https://github.com/readmeio/oas/commit/88b0b33)), closes [#580](https://github.com/readmeio/oas/issues/580)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
exports.__esModule = true;
|
|
22
|
+
var RMOAS = __importStar(require("../rmoas.types"));
|
|
23
|
+
/**
|
|
24
|
+
* With an array of common parameters filter down them to what isn't already present in a list of non-common
|
|
25
|
+
* parameters.
|
|
26
|
+
*
|
|
27
|
+
* @param parameters
|
|
28
|
+
* @param commonParameters
|
|
29
|
+
*/
|
|
30
|
+
function dedupeCommonParameters(parameters, commonParameters) {
|
|
31
|
+
return commonParameters.filter(function (param) {
|
|
32
|
+
return !parameters.find(function (param2) {
|
|
33
|
+
if (param.name && param2.name) {
|
|
34
|
+
return param.name === param2.name && param["in"] === param2["in"];
|
|
35
|
+
}
|
|
36
|
+
else if (RMOAS.isRef(param) && RMOAS.isRef(param2)) {
|
|
37
|
+
return param.$ref === param2.$ref;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
exports["default"] = dedupeCommonParameters;
|
package/dist/lib/get-schema.js
CHANGED
|
@@ -11,6 +11,7 @@ var find_schema_definition_1 = __importDefault(require("./find-schema-definition
|
|
|
11
11
|
*
|
|
12
12
|
* If the reference pointer looks like a `requestBodies` reference, then we also do a lookup for the actual schema.
|
|
13
13
|
*
|
|
14
|
+
* @deprecated
|
|
14
15
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields-8}
|
|
15
16
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#fixed-fields-8}
|
|
16
17
|
* @param operation Operation to look for a primary requestBody schema in.
|
|
@@ -180,19 +180,11 @@ function searchForExampleByPointer(pointer, examples) {
|
|
|
180
180
|
schema = schema.example;
|
|
181
181
|
}
|
|
182
182
|
else {
|
|
183
|
-
|
|
184
|
-
if (!keys.length) {
|
|
183
|
+
if (!Array.isArray(schema.examples) || !schema.examples.length) {
|
|
185
184
|
continue;
|
|
186
185
|
}
|
|
187
186
|
// Prevent us from crashing if `examples` is a completely empty object.
|
|
188
|
-
|
|
189
|
-
if (typeof ex !== 'object' || Array.isArray(ex)) {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
else if (!('value' in ex)) {
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
schema = ex.value;
|
|
187
|
+
schema = schema.examples.shift();
|
|
196
188
|
}
|
|
197
189
|
try {
|
|
198
190
|
example = jsonpointer_1["default"].get(schema, pointers[i]);
|
|
@@ -384,7 +376,11 @@ function toJSONSchema(data, opts) {
|
|
|
384
376
|
reshapedExamples_1 = true;
|
|
385
377
|
}
|
|
386
378
|
else {
|
|
387
|
-
|
|
379
|
+
// If this example is neither a primitive or an array we should dump it into the `prevSchemas` array
|
|
380
|
+
// because we might be able to extract an example from it further downstream.
|
|
381
|
+
prevSchemas.push({
|
|
382
|
+
example: example.value
|
|
383
|
+
});
|
|
388
384
|
}
|
|
389
385
|
}
|
|
390
386
|
});
|
|
@@ -34,7 +34,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
34
34
|
};
|
|
35
35
|
exports.__esModule = true;
|
|
36
36
|
exports.types = void 0;
|
|
37
|
-
var get_schema_1 = __importDefault(require("../lib/get-schema"));
|
|
38
37
|
var matches_mimetype_1 = __importDefault(require("../lib/matches-mimetype"));
|
|
39
38
|
var openapi_to_json_schema_1 = __importDefault(require("../lib/openapi-to-json-schema"));
|
|
40
39
|
var RMOAS = __importStar(require("../rmoas.types"));
|
|
@@ -75,12 +74,11 @@ function cloneObject(obj) {
|
|
|
75
74
|
return JSON.parse(JSON.stringify(obj));
|
|
76
75
|
}
|
|
77
76
|
/**
|
|
78
|
-
* @param path
|
|
79
77
|
* @param operation
|
|
80
78
|
* @param api
|
|
81
79
|
* @param globalDefaults
|
|
82
80
|
*/
|
|
83
|
-
function getParametersAsJsonSchema(
|
|
81
|
+
function getParametersAsJsonSchema(operation, api, globalDefaults) {
|
|
84
82
|
var _a;
|
|
85
83
|
if (globalDefaults === void 0) { globalDefaults = {}; }
|
|
86
84
|
var hasCircularRefs = false;
|
|
@@ -126,29 +124,33 @@ function getParametersAsJsonSchema(path, operation, api, globalDefaults) {
|
|
|
126
124
|
/**
|
|
127
125
|
*
|
|
128
126
|
*/
|
|
129
|
-
function
|
|
130
|
-
var
|
|
131
|
-
if (!
|
|
127
|
+
function transformRequestBody() {
|
|
128
|
+
var requestBody = operation.getRequestBody();
|
|
129
|
+
if (!requestBody || !Array.isArray(requestBody))
|
|
132
130
|
return null;
|
|
133
|
-
var
|
|
134
|
-
var
|
|
131
|
+
var mediaType = requestBody[0], mediaTypeObject = requestBody[1];
|
|
132
|
+
var type = mediaType === 'application/x-www-form-urlencoded' ? 'formData' : 'body';
|
|
135
133
|
// If this schema is completely empty, don't bother processing it.
|
|
136
|
-
if (Object.keys(
|
|
134
|
+
if (!Object.keys(mediaTypeObject.schema).length) {
|
|
137
135
|
return null;
|
|
138
136
|
}
|
|
139
|
-
var
|
|
140
|
-
if ('example' in
|
|
141
|
-
|
|
137
|
+
var prevSchemas = [];
|
|
138
|
+
if ('example' in mediaTypeObject) {
|
|
139
|
+
prevSchemas.push({ example: mediaTypeObject.example });
|
|
142
140
|
}
|
|
143
|
-
else if ('examples' in
|
|
144
|
-
|
|
141
|
+
else if ('examples' in mediaTypeObject) {
|
|
142
|
+
prevSchemas.push({
|
|
143
|
+
examples: Object.values(mediaTypeObject.examples)
|
|
144
|
+
.map(function (example) { return example.value; })
|
|
145
|
+
.filter(function (val) { return val !== undefined; })
|
|
146
|
+
});
|
|
145
147
|
}
|
|
146
148
|
// We're cloning the request schema because we've had issues with request schemas that were dereferenced being
|
|
147
149
|
// processed multiple times because their component is also processed.
|
|
148
|
-
var requestSchema = cloneObject(
|
|
149
|
-
var cleanedSchema = (0, openapi_to_json_schema_1["default"])(requestSchema, { globalDefaults: globalDefaults, prevSchemas:
|
|
150
|
+
var requestSchema = cloneObject(mediaTypeObject.schema);
|
|
151
|
+
var cleanedSchema = (0, openapi_to_json_schema_1["default"])(requestSchema, { globalDefaults: globalDefaults, prevSchemas: prevSchemas, refLogger: refLogger });
|
|
150
152
|
// If this schema is **still** empty, don't bother returning it.
|
|
151
|
-
if (Object.keys(cleanedSchema).length
|
|
153
|
+
if (!Object.keys(cleanedSchema).length) {
|
|
152
154
|
return null;
|
|
153
155
|
}
|
|
154
156
|
return {
|
|
@@ -158,13 +160,7 @@ function getParametersAsJsonSchema(path, operation, api, globalDefaults) {
|
|
|
158
160
|
deprecatedProps: getDeprecated(cleanedSchema, type)
|
|
159
161
|
};
|
|
160
162
|
}
|
|
161
|
-
function
|
|
162
|
-
if (api && 'paths' in api && path in api.paths && 'parameters' in api.paths[path]) {
|
|
163
|
-
return api.paths[path].parameters;
|
|
164
|
-
}
|
|
165
|
-
return [];
|
|
166
|
-
}
|
|
167
|
-
function getComponents() {
|
|
163
|
+
function transformComponents() {
|
|
168
164
|
if (!('components' in api)) {
|
|
169
165
|
return false;
|
|
170
166
|
}
|
|
@@ -185,23 +181,8 @@ function getParametersAsJsonSchema(path, operation, api, globalDefaults) {
|
|
|
185
181
|
});
|
|
186
182
|
return components;
|
|
187
183
|
}
|
|
188
|
-
function
|
|
189
|
-
var operationParams = operation.
|
|
190
|
-
var commonParams = getCommonParams();
|
|
191
|
-
if (commonParams.length !== 0) {
|
|
192
|
-
var commonParamsNotInParams = commonParams.filter(function (param) {
|
|
193
|
-
return !operationParams.find(function (param2) {
|
|
194
|
-
if (param.name && param2.name) {
|
|
195
|
-
return param.name === param2.name && param["in"] === param2["in"];
|
|
196
|
-
}
|
|
197
|
-
else if (RMOAS.isRef(param) && RMOAS.isRef(param2)) {
|
|
198
|
-
return param.$ref === param2.$ref;
|
|
199
|
-
}
|
|
200
|
-
return false;
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
operationParams = operationParams.concat(commonParamsNotInParams || []);
|
|
204
|
-
}
|
|
184
|
+
function transformParameters() {
|
|
185
|
+
var operationParams = operation.getParameters();
|
|
205
186
|
return Object.keys(exports.types).map(function (type) {
|
|
206
187
|
var required = [];
|
|
207
188
|
// This `as` actually *could* be a ref, but we don't want refs to pass through here, so `.in` will never match `type`
|
|
@@ -303,14 +284,15 @@ function getParametersAsJsonSchema(path, operation, api, globalDefaults) {
|
|
|
303
284
|
};
|
|
304
285
|
});
|
|
305
286
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (!hasParameters && !hasRequestBody
|
|
287
|
+
// If this operation neither has any parameters or a request body then we should return null because there won't be
|
|
288
|
+
// any JSON Schema.
|
|
289
|
+
if (!operation.hasParameters() && !operation.hasRequestBody()) {
|
|
309
290
|
return null;
|
|
310
|
-
|
|
291
|
+
}
|
|
292
|
+
var components = transformComponents();
|
|
311
293
|
var typeKeys = Object.keys(exports.types);
|
|
312
|
-
return (_a = [
|
|
313
|
-
.concat.apply(_a,
|
|
294
|
+
return (_a = [transformRequestBody()])
|
|
295
|
+
.concat.apply(_a, transformParameters()).filter(Boolean)
|
|
314
296
|
.map(function (group) {
|
|
315
297
|
// Since this library assumes that the schema has already been dereferenced, adding every component here that
|
|
316
298
|
// **isn't** circular adds a ton of bloat so it'd be cool if `components` was just the remaining `$ref` pointers
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
15
|
};
|
|
@@ -14,6 +25,7 @@ function getResponseExamples(operation) {
|
|
|
14
25
|
return Object.keys(operation.responses || {})
|
|
15
26
|
.map(function (status) {
|
|
16
27
|
var response = operation.responses[status];
|
|
28
|
+
var onlyHeaders = false;
|
|
17
29
|
// If we have a $ref here that means that this was a circular ref so we should ignore it.
|
|
18
30
|
if ((0, rmoas_types_1.isRef)(response)) {
|
|
19
31
|
return false;
|
|
@@ -31,13 +43,15 @@ function getResponseExamples(operation) {
|
|
|
31
43
|
mediaTypes[mediaType] = examples;
|
|
32
44
|
}
|
|
33
45
|
});
|
|
46
|
+
// If the response has no content, but has headers, hardcode an empty example so the headers modal will still display
|
|
47
|
+
if (response.headers && Object.keys(response.headers).length && !Object.keys(mediaTypes).length) {
|
|
48
|
+
mediaTypes['*/*'] = [];
|
|
49
|
+
onlyHeaders = true;
|
|
50
|
+
}
|
|
34
51
|
if (!Object.keys(mediaTypes).length) {
|
|
35
52
|
return false;
|
|
36
53
|
}
|
|
37
|
-
return {
|
|
38
|
-
status: status,
|
|
39
|
-
mediaTypes: mediaTypes
|
|
40
|
-
};
|
|
54
|
+
return __assign({ status: status, mediaTypes: mediaTypes }, (onlyHeaders ? { onlyHeaders: onlyHeaders } : {}));
|
|
41
55
|
})
|
|
42
56
|
.filter(Boolean);
|
|
43
57
|
}
|
package/dist/operation.js
CHANGED
|
@@ -39,6 +39,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
exports.__esModule = true;
|
|
40
40
|
exports.Webhook = exports.Callback = void 0;
|
|
41
41
|
var RMOAS = __importStar(require("./rmoas.types"));
|
|
42
|
+
var dedupe_common_parameters_1 = __importDefault(require("./lib/dedupe-common-parameters"));
|
|
42
43
|
var find_schema_definition_1 = __importDefault(require("./lib/find-schema-definition"));
|
|
43
44
|
var get_parameters_as_json_schema_1 = __importDefault(require("./operation/get-parameters-as-json-schema"));
|
|
44
45
|
var get_response_as_json_schema_1 = __importDefault(require("./operation/get-response-as-json-schema"));
|
|
@@ -333,13 +334,25 @@ var Operation = /** @class */ (function () {
|
|
|
333
334
|
Operation.prototype.isDeprecated = function () {
|
|
334
335
|
return 'deprecated' in this.schema ? this.schema.deprecated : false;
|
|
335
336
|
};
|
|
337
|
+
/**
|
|
338
|
+
* Determine if the operation has any (non-request body) parameters.
|
|
339
|
+
*
|
|
340
|
+
*/
|
|
341
|
+
Operation.prototype.hasParameters = function () {
|
|
342
|
+
return !!this.getParameters().length;
|
|
343
|
+
};
|
|
336
344
|
/**
|
|
337
345
|
* Return the parameters (non-request body) on the operation.
|
|
338
346
|
*
|
|
339
|
-
* @todo This should also pull in common params.
|
|
340
347
|
*/
|
|
341
348
|
Operation.prototype.getParameters = function () {
|
|
342
|
-
|
|
349
|
+
var _a, _b, _c, _d;
|
|
350
|
+
var parameters = (((_a = this.schema) === null || _a === void 0 ? void 0 : _a.parameters) || []);
|
|
351
|
+
var commonParams = (((_d = (_c = (_b = this.api) === null || _b === void 0 ? void 0 : _b.paths) === null || _c === void 0 ? void 0 : _c[this.path]) === null || _d === void 0 ? void 0 : _d.parameters) || []);
|
|
352
|
+
if (commonParams.length) {
|
|
353
|
+
parameters = parameters.concat((0, dedupe_common_parameters_1["default"])(parameters, commonParams) || []);
|
|
354
|
+
}
|
|
355
|
+
return parameters;
|
|
343
356
|
};
|
|
344
357
|
/**
|
|
345
358
|
* Convert the operation into an array of JSON Schema schemas for each available type of parameter available on the
|
|
@@ -348,7 +361,7 @@ var Operation = /** @class */ (function () {
|
|
|
348
361
|
* @param globalDefaults Contains an object of user defined schema defaults.
|
|
349
362
|
*/
|
|
350
363
|
Operation.prototype.getParametersAsJsonSchema = function (globalDefaults) {
|
|
351
|
-
return (0, get_parameters_as_json_schema_1["default"])(this
|
|
364
|
+
return (0, get_parameters_as_json_schema_1["default"])(this, this.api, globalDefaults);
|
|
352
365
|
};
|
|
353
366
|
/**
|
|
354
367
|
* Get a single response for this status code, formatted as JSON schema.
|
|
@@ -372,9 +385,31 @@ var Operation = /** @class */ (function () {
|
|
|
372
385
|
Operation.prototype.hasRequestBody = function () {
|
|
373
386
|
return !!this.schema.requestBody;
|
|
374
387
|
};
|
|
388
|
+
/**
|
|
389
|
+
* Retrieve the list of all available media types that the operations request body can accept.
|
|
390
|
+
*
|
|
391
|
+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject}
|
|
392
|
+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
393
|
+
*/
|
|
394
|
+
Operation.prototype.getRequestBodyMediaTypes = function () {
|
|
395
|
+
if (!this.hasRequestBody()) {
|
|
396
|
+
return [];
|
|
397
|
+
}
|
|
398
|
+
var requestBody = this.schema.requestBody;
|
|
399
|
+
if (RMOAS.isRef(requestBody)) {
|
|
400
|
+
// If the request body is still a `$ref` pointer we should return false because this library assumes that you've
|
|
401
|
+
// run dereferencing beforehand.
|
|
402
|
+
return [];
|
|
403
|
+
}
|
|
404
|
+
return Object.keys(requestBody.content);
|
|
405
|
+
};
|
|
375
406
|
/**
|
|
376
407
|
* Retrieve a specific request body content schema off this operation.
|
|
377
408
|
*
|
|
409
|
+
* If no media type is supplied this will return either the first available JSON-like request body, or the first
|
|
410
|
+
* available if there are no JSON-like media types present. When this return comes back it's in the form of an array
|
|
411
|
+
* with the first key being the selected media type, followed by the media type object in question.
|
|
412
|
+
*
|
|
378
413
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject}
|
|
379
414
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
380
415
|
* @param mediaType Specific request body media type to retrieve if present.
|
|
@@ -384,12 +419,37 @@ var Operation = /** @class */ (function () {
|
|
|
384
419
|
return false;
|
|
385
420
|
}
|
|
386
421
|
var requestBody = this.schema.requestBody;
|
|
387
|
-
if (RMOAS.isRef(requestBody)
|
|
422
|
+
if (RMOAS.isRef(requestBody)) {
|
|
388
423
|
// If the request body is still a `$ref` pointer we should return false because this library assumes that you've
|
|
389
424
|
// run dereferencing beforehand.
|
|
390
425
|
return false;
|
|
391
426
|
}
|
|
392
|
-
|
|
427
|
+
if (mediaType) {
|
|
428
|
+
if (!(mediaType in requestBody.content)) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
return requestBody.content[mediaType];
|
|
432
|
+
}
|
|
433
|
+
// Since no media type was supplied we need to find either the first JSON-like media type that we've got, or the
|
|
434
|
+
// first available of anything else if no JSON-like media types are present.
|
|
435
|
+
var availableMediaType;
|
|
436
|
+
var mediaTypes = this.getRequestBodyMediaTypes();
|
|
437
|
+
mediaTypes.forEach(function (mt) {
|
|
438
|
+
if (!availableMediaType && matches_mimetype_1["default"].json(mt)) {
|
|
439
|
+
availableMediaType = mt;
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
if (!availableMediaType) {
|
|
443
|
+
mediaTypes.forEach(function (mt) {
|
|
444
|
+
if (!availableMediaType) {
|
|
445
|
+
availableMediaType = mt;
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
if (availableMediaType) {
|
|
450
|
+
return [availableMediaType, requestBody.content[availableMediaType]];
|
|
451
|
+
}
|
|
452
|
+
return false;
|
|
393
453
|
};
|
|
394
454
|
/**
|
|
395
455
|
* Retrieve an array of request body examples that this operation has.
|
|
@@ -552,6 +612,15 @@ var Callback = /** @class */ (function (_super) {
|
|
|
552
612
|
}
|
|
553
613
|
return ((_a = this.schema) === null || _a === void 0 ? void 0 : _a.description) ? this.schema.description.trim() : undefined;
|
|
554
614
|
};
|
|
615
|
+
Callback.prototype.getParameters = function () {
|
|
616
|
+
var _a;
|
|
617
|
+
var parameters = (((_a = this.schema) === null || _a === void 0 ? void 0 : _a.parameters) || []);
|
|
618
|
+
var commonParams = (this.parentSchema.parameters || []);
|
|
619
|
+
if (commonParams.length) {
|
|
620
|
+
parameters = parameters.concat((0, dedupe_common_parameters_1["default"])(parameters, commonParams) || []);
|
|
621
|
+
}
|
|
622
|
+
return parameters;
|
|
623
|
+
};
|
|
555
624
|
return Callback;
|
|
556
625
|
}(Operation));
|
|
557
626
|
exports.Callback = Callback;
|
package/dist/samples/index.js
CHANGED
|
@@ -6,20 +6,25 @@ exports.__esModule = true;
|
|
|
6
6
|
var utils_1 = require("./utils");
|
|
7
7
|
var memoizee_1 = __importDefault(require("memoizee"));
|
|
8
8
|
var json_schema_merge_allof_1 = __importDefault(require("json-schema-merge-allof"));
|
|
9
|
+
var sampleDefaults = function (genericSample) {
|
|
10
|
+
return function (schema) {
|
|
11
|
+
return typeof schema["default"] === typeof genericSample ? schema["default"] : genericSample;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
9
14
|
var primitives = {
|
|
10
|
-
string:
|
|
11
|
-
string_email:
|
|
12
|
-
'string_date-time':
|
|
13
|
-
string_date:
|
|
14
|
-
'string_YYYY-MM-DD':
|
|
15
|
-
string_uuid:
|
|
16
|
-
string_hostname:
|
|
17
|
-
string_ipv4:
|
|
18
|
-
string_ipv6:
|
|
19
|
-
number:
|
|
20
|
-
number_float:
|
|
21
|
-
integer:
|
|
22
|
-
boolean:
|
|
15
|
+
string: sampleDefaults('string'),
|
|
16
|
+
string_email: sampleDefaults('user@example.com'),
|
|
17
|
+
'string_date-time': sampleDefaults(new Date().toISOString()),
|
|
18
|
+
string_date: sampleDefaults(new Date().toISOString().substring(0, 10)),
|
|
19
|
+
'string_YYYY-MM-DD': sampleDefaults(new Date().toISOString().substring(0, 10)),
|
|
20
|
+
string_uuid: sampleDefaults('3fa85f64-5717-4562-b3fc-2c963f66afa6'),
|
|
21
|
+
string_hostname: sampleDefaults('example.com'),
|
|
22
|
+
string_ipv4: sampleDefaults('198.51.100.42'),
|
|
23
|
+
string_ipv6: sampleDefaults('2001:0db8:5b96:0000:0000:426f:8e17:642a'),
|
|
24
|
+
number: sampleDefaults(0),
|
|
25
|
+
number_float: sampleDefaults(0.0),
|
|
26
|
+
integer: sampleDefaults(0),
|
|
27
|
+
boolean: sampleDefaults(true)
|
|
23
28
|
};
|
|
24
29
|
var primitive = function (schema) {
|
|
25
30
|
schema = (0, utils_1.objectify)(schema);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oas",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.7.2",
|
|
4
4
|
"description": "Working with OpenAPI definitions is hard. This makes it easier.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ReadMe <support@readme.io> (https://readme.com)",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"jsonpointer": "^5.0.0",
|
|
60
60
|
"memoizee": "^0.4.14",
|
|
61
61
|
"minimist": "^1.2.0",
|
|
62
|
-
"oas-normalize": "^5.1.
|
|
62
|
+
"oas-normalize": "^5.1.1",
|
|
63
63
|
"openapi-types": "^10.0.0",
|
|
64
64
|
"path-to-regexp": "^6.2.0",
|
|
65
65
|
"swagger-inline": "^5.0.2"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as RMOAS from '../rmoas.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* With an array of common parameters filter down them to what isn't already present in a list of non-common
|
|
5
|
+
* parameters.
|
|
6
|
+
*
|
|
7
|
+
* @param parameters
|
|
8
|
+
* @param commonParameters
|
|
9
|
+
*/
|
|
10
|
+
export default function dedupeCommonParameters(
|
|
11
|
+
parameters: RMOAS.ParameterObject[],
|
|
12
|
+
commonParameters: RMOAS.ParameterObject[]
|
|
13
|
+
) {
|
|
14
|
+
return commonParameters.filter((param: RMOAS.ParameterObject) => {
|
|
15
|
+
return !parameters.find((param2: RMOAS.ParameterObject) => {
|
|
16
|
+
if (param.name && param2.name) {
|
|
17
|
+
return param.name === param2.name && param.in === param2.in;
|
|
18
|
+
} else if (RMOAS.isRef(param) && RMOAS.isRef(param2)) {
|
|
19
|
+
return param.$ref === param2.$ref;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return false;
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
package/src/lib/get-schema.ts
CHANGED
|
@@ -8,6 +8,7 @@ import findSchemaDefinition from './find-schema-definition';
|
|
|
8
8
|
*
|
|
9
9
|
* If the reference pointer looks like a `requestBodies` reference, then we also do a lookup for the actual schema.
|
|
10
10
|
*
|
|
11
|
+
* @deprecated
|
|
11
12
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields-8}
|
|
12
13
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#fixed-fields-8}
|
|
13
14
|
* @param operation Operation to look for a primary requestBody schema in.
|
|
@@ -150,21 +150,12 @@ function searchForExampleByPointer(pointer: string, examples: PrevSchemasType =
|
|
|
150
150
|
if ('example' in schema) {
|
|
151
151
|
schema = schema.example;
|
|
152
152
|
} else {
|
|
153
|
-
|
|
154
|
-
if (!keys.length) {
|
|
153
|
+
if (!Array.isArray(schema.examples) || !schema.examples.length) {
|
|
155
154
|
continue;
|
|
156
155
|
}
|
|
157
156
|
|
|
158
157
|
// Prevent us from crashing if `examples` is a completely empty object.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (typeof ex !== 'object' || Array.isArray(ex)) {
|
|
162
|
-
continue;
|
|
163
|
-
} else if (!('value' in ex)) {
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
schema = ex.value;
|
|
158
|
+
schema = schema.examples.shift();
|
|
168
159
|
}
|
|
169
160
|
|
|
170
161
|
try {
|
|
@@ -376,7 +367,11 @@ export default function toJSONSchema(
|
|
|
376
367
|
examples.push(example.value[0]);
|
|
377
368
|
reshapedExamples = true;
|
|
378
369
|
} else {
|
|
379
|
-
|
|
370
|
+
// If this example is neither a primitive or an array we should dump it into the `prevSchemas` array
|
|
371
|
+
// because we might be able to extract an example from it further downstream.
|
|
372
|
+
prevSchemas.push({
|
|
373
|
+
example: example.value,
|
|
374
|
+
});
|
|
380
375
|
}
|
|
381
376
|
}
|
|
382
377
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ComponentsObject, OASDocument,
|
|
1
|
+
import type { ComponentsObject, OASDocument, SchemaObject } from '../rmoas.types';
|
|
2
2
|
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
3
|
-
import
|
|
3
|
+
import type Operation from '../operation';
|
|
4
4
|
import matchesMimetype from '../lib/matches-mimetype';
|
|
5
5
|
import toJSONSchema from '../lib/openapi-to-json-schema';
|
|
6
6
|
import * as RMOAS from '../rmoas.types';
|
|
@@ -57,17 +57,11 @@ function cloneObject<T>(obj: T): T {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* @param path
|
|
61
60
|
* @param operation
|
|
62
61
|
* @param api
|
|
63
62
|
* @param globalDefaults
|
|
64
63
|
*/
|
|
65
|
-
export default function getParametersAsJsonSchema(
|
|
66
|
-
path: string,
|
|
67
|
-
operation: OperationObject,
|
|
68
|
-
api: OASDocument,
|
|
69
|
-
globalDefaults = {}
|
|
70
|
-
) {
|
|
64
|
+
export default function getParametersAsJsonSchema(operation: Operation, api: OASDocument, globalDefaults = {}) {
|
|
71
65
|
let hasCircularRefs = false;
|
|
72
66
|
|
|
73
67
|
function refLogger() {
|
|
@@ -122,32 +116,36 @@ export default function getParametersAsJsonSchema(
|
|
|
122
116
|
/**
|
|
123
117
|
*
|
|
124
118
|
*/
|
|
125
|
-
function
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
119
|
+
function transformRequestBody(): SchemaWrapper {
|
|
120
|
+
const requestBody = operation.getRequestBody();
|
|
121
|
+
if (!requestBody || !Array.isArray(requestBody)) return null;
|
|
128
122
|
|
|
129
|
-
const
|
|
130
|
-
const
|
|
123
|
+
const [mediaType, mediaTypeObject] = requestBody;
|
|
124
|
+
const type = mediaType === 'application/x-www-form-urlencoded' ? 'formData' : 'body';
|
|
131
125
|
|
|
132
126
|
// If this schema is completely empty, don't bother processing it.
|
|
133
|
-
if (Object.keys(
|
|
127
|
+
if (!Object.keys(mediaTypeObject.schema).length) {
|
|
134
128
|
return null;
|
|
135
129
|
}
|
|
136
130
|
|
|
137
|
-
const
|
|
138
|
-
if ('example' in
|
|
139
|
-
|
|
140
|
-
} else if ('examples' in
|
|
141
|
-
|
|
131
|
+
const prevSchemas = [] as Array<RMOAS.SchemaObject>;
|
|
132
|
+
if ('example' in mediaTypeObject) {
|
|
133
|
+
prevSchemas.push({ example: mediaTypeObject.example });
|
|
134
|
+
} else if ('examples' in mediaTypeObject) {
|
|
135
|
+
prevSchemas.push({
|
|
136
|
+
examples: Object.values(mediaTypeObject.examples)
|
|
137
|
+
.map((example: RMOAS.ExampleObject) => example.value)
|
|
138
|
+
.filter(val => val !== undefined),
|
|
139
|
+
});
|
|
142
140
|
}
|
|
143
141
|
|
|
144
142
|
// We're cloning the request schema because we've had issues with request schemas that were dereferenced being
|
|
145
143
|
// processed multiple times because their component is also processed.
|
|
146
|
-
const requestSchema = cloneObject(
|
|
147
|
-
const cleanedSchema = toJSONSchema(requestSchema, { globalDefaults, prevSchemas
|
|
144
|
+
const requestSchema = cloneObject(mediaTypeObject.schema);
|
|
145
|
+
const cleanedSchema = toJSONSchema(requestSchema, { globalDefaults, prevSchemas, refLogger });
|
|
148
146
|
|
|
149
147
|
// If this schema is **still** empty, don't bother returning it.
|
|
150
|
-
if (Object.keys(cleanedSchema).length
|
|
148
|
+
if (!Object.keys(cleanedSchema).length) {
|
|
151
149
|
return null;
|
|
152
150
|
}
|
|
153
151
|
|
|
@@ -162,15 +160,7 @@ export default function getParametersAsJsonSchema(
|
|
|
162
160
|
};
|
|
163
161
|
}
|
|
164
162
|
|
|
165
|
-
function
|
|
166
|
-
if (api && 'paths' in api && path in api.paths && 'parameters' in api.paths[path]) {
|
|
167
|
-
return api.paths[path].parameters;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return [];
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function getComponents(): ComponentsObject {
|
|
163
|
+
function transformComponents(): ComponentsObject {
|
|
174
164
|
if (!('components' in api)) {
|
|
175
165
|
return false;
|
|
176
166
|
}
|
|
@@ -196,25 +186,8 @@ export default function getParametersAsJsonSchema(
|
|
|
196
186
|
return components;
|
|
197
187
|
}
|
|
198
188
|
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
const commonParams = getCommonParams();
|
|
202
|
-
|
|
203
|
-
if (commonParams.length !== 0) {
|
|
204
|
-
const commonParamsNotInParams = commonParams.filter((param: RMOAS.ParameterObject) => {
|
|
205
|
-
return !operationParams.find((param2: RMOAS.ParameterObject) => {
|
|
206
|
-
if (param.name && param2.name) {
|
|
207
|
-
return param.name === param2.name && param.in === param2.in;
|
|
208
|
-
} else if (RMOAS.isRef(param) && RMOAS.isRef(param2)) {
|
|
209
|
-
return param.$ref === param2.$ref;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return false;
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
operationParams = operationParams.concat(commonParamsNotInParams || []);
|
|
217
|
-
}
|
|
189
|
+
function transformParameters(): Array<SchemaWrapper> {
|
|
190
|
+
const operationParams = operation.getParameters();
|
|
218
191
|
|
|
219
192
|
return Object.keys(types).map(type => {
|
|
220
193
|
const required: Array<string> = [];
|
|
@@ -330,15 +303,17 @@ export default function getParametersAsJsonSchema(
|
|
|
330
303
|
});
|
|
331
304
|
}
|
|
332
305
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
if (!hasParameters && !hasRequestBody
|
|
306
|
+
// If this operation neither has any parameters or a request body then we should return null because there won't be
|
|
307
|
+
// any JSON Schema.
|
|
308
|
+
if (!operation.hasParameters() && !operation.hasRequestBody()) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
336
311
|
|
|
337
|
-
const components =
|
|
312
|
+
const components = transformComponents();
|
|
338
313
|
|
|
339
314
|
const typeKeys = Object.keys(types);
|
|
340
|
-
return [
|
|
341
|
-
.concat(...
|
|
315
|
+
return [transformRequestBody()]
|
|
316
|
+
.concat(...transformParameters())
|
|
342
317
|
.filter(Boolean)
|
|
343
318
|
.map(group => {
|
|
344
319
|
// Since this library assumes that the schema has already been dereferenced, adding every component here that
|
|
@@ -18,6 +18,7 @@ export default function getResponseExamples(operation: RMOAS.OperationObject) {
|
|
|
18
18
|
return Object.keys(operation.responses || {})
|
|
19
19
|
.map(status => {
|
|
20
20
|
const response = operation.responses[status];
|
|
21
|
+
let onlyHeaders = false;
|
|
21
22
|
|
|
22
23
|
// If we have a $ref here that means that this was a circular ref so we should ignore it.
|
|
23
24
|
if (isRef(response)) {
|
|
@@ -39,6 +40,12 @@ export default function getResponseExamples(operation: RMOAS.OperationObject) {
|
|
|
39
40
|
}
|
|
40
41
|
});
|
|
41
42
|
|
|
43
|
+
// If the response has no content, but has headers, hardcode an empty example so the headers modal will still display
|
|
44
|
+
if (response.headers && Object.keys(response.headers).length && !Object.keys(mediaTypes).length) {
|
|
45
|
+
mediaTypes['*/*'] = [];
|
|
46
|
+
onlyHeaders = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
if (!Object.keys(mediaTypes).length) {
|
|
43
50
|
return false;
|
|
44
51
|
}
|
|
@@ -46,6 +53,7 @@ export default function getResponseExamples(operation: RMOAS.OperationObject) {
|
|
|
46
53
|
return {
|
|
47
54
|
status,
|
|
48
55
|
mediaTypes,
|
|
56
|
+
...(onlyHeaders ? { onlyHeaders } : {}),
|
|
49
57
|
};
|
|
50
58
|
})
|
|
51
59
|
.filter(Boolean) as ResponseExamples;
|
package/src/operation.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { CallbackExamples } from './operation/get-callback-examples';
|
|
|
4
4
|
import type { ResponseExamples } from './operation/get-response-examples';
|
|
5
5
|
|
|
6
6
|
import * as RMOAS from './rmoas.types';
|
|
7
|
+
import dedupeCommonParameters from './lib/dedupe-common-parameters';
|
|
7
8
|
import findSchemaDefinition from './lib/find-schema-definition';
|
|
8
9
|
import getParametersAsJsonSchema from './operation/get-parameters-as-json-schema';
|
|
9
10
|
import getResponseAsJsonSchema from './operation/get-response-as-json-schema';
|
|
@@ -382,13 +383,26 @@ export default class Operation {
|
|
|
382
383
|
return 'deprecated' in this.schema ? this.schema.deprecated : false;
|
|
383
384
|
}
|
|
384
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Determine if the operation has any (non-request body) parameters.
|
|
388
|
+
*
|
|
389
|
+
*/
|
|
390
|
+
hasParameters() {
|
|
391
|
+
return !!this.getParameters().length;
|
|
392
|
+
}
|
|
393
|
+
|
|
385
394
|
/**
|
|
386
395
|
* Return the parameters (non-request body) on the operation.
|
|
387
396
|
*
|
|
388
|
-
* @todo This should also pull in common params.
|
|
389
397
|
*/
|
|
390
398
|
getParameters(): Array<RMOAS.ParameterObject> {
|
|
391
|
-
|
|
399
|
+
let parameters = (this.schema?.parameters || []) as Array<RMOAS.ParameterObject>;
|
|
400
|
+
const commonParams = (this.api?.paths?.[this.path]?.parameters || []) as Array<RMOAS.ParameterObject>;
|
|
401
|
+
if (commonParams.length) {
|
|
402
|
+
parameters = parameters.concat(dedupeCommonParameters(parameters, commonParams) || []);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return parameters;
|
|
392
406
|
}
|
|
393
407
|
|
|
394
408
|
/**
|
|
@@ -398,7 +412,7 @@ export default class Operation {
|
|
|
398
412
|
* @param globalDefaults Contains an object of user defined schema defaults.
|
|
399
413
|
*/
|
|
400
414
|
getParametersAsJsonSchema(globalDefaults?: Record<string, unknown>) {
|
|
401
|
-
return getParametersAsJsonSchema(this
|
|
415
|
+
return getParametersAsJsonSchema(this, this.api, globalDefaults);
|
|
402
416
|
}
|
|
403
417
|
|
|
404
418
|
/**
|
|
@@ -426,26 +440,81 @@ export default class Operation {
|
|
|
426
440
|
return !!this.schema.requestBody;
|
|
427
441
|
}
|
|
428
442
|
|
|
443
|
+
/**
|
|
444
|
+
* Retrieve the list of all available media types that the operations request body can accept.
|
|
445
|
+
*
|
|
446
|
+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject}
|
|
447
|
+
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
448
|
+
*/
|
|
449
|
+
getRequestBodyMediaTypes() {
|
|
450
|
+
if (!this.hasRequestBody()) {
|
|
451
|
+
return [];
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const requestBody = this.schema.requestBody;
|
|
455
|
+
if (RMOAS.isRef(requestBody)) {
|
|
456
|
+
// If the request body is still a `$ref` pointer we should return false because this library assumes that you've
|
|
457
|
+
// run dereferencing beforehand.
|
|
458
|
+
return [];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return Object.keys(requestBody.content);
|
|
462
|
+
}
|
|
463
|
+
|
|
429
464
|
/**
|
|
430
465
|
* Retrieve a specific request body content schema off this operation.
|
|
431
466
|
*
|
|
467
|
+
* If no media type is supplied this will return either the first available JSON-like request body, or the first
|
|
468
|
+
* available if there are no JSON-like media types present. When this return comes back it's in the form of an array
|
|
469
|
+
* with the first key being the selected media type, followed by the media type object in question.
|
|
470
|
+
*
|
|
432
471
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject}
|
|
433
472
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
434
473
|
* @param mediaType Specific request body media type to retrieve if present.
|
|
435
474
|
*/
|
|
436
|
-
getRequestBody(mediaType
|
|
475
|
+
getRequestBody(mediaType?: string): false | RMOAS.MediaTypeObject | [string, RMOAS.MediaTypeObject] {
|
|
437
476
|
if (!this.hasRequestBody()) {
|
|
438
477
|
return false;
|
|
439
478
|
}
|
|
440
479
|
|
|
441
480
|
const requestBody = this.schema.requestBody;
|
|
442
|
-
if (RMOAS.isRef(requestBody)
|
|
481
|
+
if (RMOAS.isRef(requestBody)) {
|
|
443
482
|
// If the request body is still a `$ref` pointer we should return false because this library assumes that you've
|
|
444
483
|
// run dereferencing beforehand.
|
|
445
484
|
return false;
|
|
446
485
|
}
|
|
447
486
|
|
|
448
|
-
|
|
487
|
+
if (mediaType) {
|
|
488
|
+
if (!(mediaType in requestBody.content)) {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return requestBody.content[mediaType];
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Since no media type was supplied we need to find either the first JSON-like media type that we've got, or the
|
|
496
|
+
// first available of anything else if no JSON-like media types are present.
|
|
497
|
+
let availableMediaType: string;
|
|
498
|
+
const mediaTypes = this.getRequestBodyMediaTypes();
|
|
499
|
+
mediaTypes.forEach((mt: string) => {
|
|
500
|
+
if (!availableMediaType && matchesMimeType.json(mt)) {
|
|
501
|
+
availableMediaType = mt;
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
if (!availableMediaType) {
|
|
506
|
+
mediaTypes.forEach((mt: string) => {
|
|
507
|
+
if (!availableMediaType) {
|
|
508
|
+
availableMediaType = mt;
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (availableMediaType) {
|
|
514
|
+
return [availableMediaType, requestBody.content[availableMediaType]];
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return false;
|
|
449
518
|
}
|
|
450
519
|
|
|
451
520
|
/**
|
|
@@ -645,6 +714,16 @@ export class Callback extends Operation {
|
|
|
645
714
|
|
|
646
715
|
return this.schema?.description ? this.schema.description.trim() : undefined;
|
|
647
716
|
}
|
|
717
|
+
|
|
718
|
+
getParameters(): Array<RMOAS.ParameterObject> {
|
|
719
|
+
let parameters = (this.schema?.parameters || []) as Array<RMOAS.ParameterObject>;
|
|
720
|
+
const commonParams = (this.parentSchema.parameters || []) as Array<RMOAS.ParameterObject>;
|
|
721
|
+
if (commonParams.length) {
|
|
722
|
+
parameters = parameters.concat(dedupeCommonParameters(parameters, commonParams) || []);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
return parameters;
|
|
726
|
+
}
|
|
648
727
|
}
|
|
649
728
|
|
|
650
729
|
export class Webhook extends Operation {}
|
package/src/rmoas.types.ts
CHANGED
|
@@ -60,6 +60,15 @@ export type ServerVariableObject = OpenAPIV3.ServerVariableObject | OpenAPIV3_1.
|
|
|
60
60
|
export type ServerVariablesObject = {
|
|
61
61
|
[variable: string]: ServerVariableObject;
|
|
62
62
|
};
|
|
63
|
+
export type ServerVariable = Record<
|
|
64
|
+
string,
|
|
65
|
+
string | number | Array<{ default?: string | number }> | { default?: string | number } | Record<string, never>
|
|
66
|
+
>;
|
|
67
|
+
|
|
68
|
+
export type Servers = {
|
|
69
|
+
selected: number;
|
|
70
|
+
variables: ServerVariable;
|
|
71
|
+
};
|
|
63
72
|
|
|
64
73
|
/**
|
|
65
74
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#componentsObject}
|
package/src/samples/index.ts
CHANGED
|
@@ -9,20 +9,25 @@ import { objectify, usesPolymorphism, isFunc, normalizeArray, deeplyStripKey } f
|
|
|
9
9
|
import memoize from 'memoizee';
|
|
10
10
|
import mergeAllOf from 'json-schema-merge-allof';
|
|
11
11
|
|
|
12
|
+
const sampleDefaults = (genericSample: string | number | boolean) => {
|
|
13
|
+
return (schema: RMOAS.SchemaObject): typeof genericSample =>
|
|
14
|
+
typeof schema.default === typeof genericSample ? schema.default : genericSample;
|
|
15
|
+
};
|
|
16
|
+
|
|
12
17
|
const primitives: Record<string, (arg: void | RMOAS.SchemaObject) => string | number | boolean> = {
|
|
13
|
-
string: (
|
|
14
|
-
string_email: (
|
|
15
|
-
'string_date-time': (
|
|
16
|
-
string_date: (
|
|
17
|
-
'string_YYYY-MM-DD': (
|
|
18
|
-
string_uuid: (
|
|
19
|
-
string_hostname: (
|
|
20
|
-
string_ipv4: (
|
|
21
|
-
string_ipv6: (
|
|
22
|
-
number: ()
|
|
23
|
-
number_float: (
|
|
24
|
-
integer: ()
|
|
25
|
-
boolean: (
|
|
18
|
+
string: sampleDefaults('string'),
|
|
19
|
+
string_email: sampleDefaults('user@example.com'),
|
|
20
|
+
'string_date-time': sampleDefaults(new Date().toISOString()),
|
|
21
|
+
string_date: sampleDefaults(new Date().toISOString().substring(0, 10)),
|
|
22
|
+
'string_YYYY-MM-DD': sampleDefaults(new Date().toISOString().substring(0, 10)),
|
|
23
|
+
string_uuid: sampleDefaults('3fa85f64-5717-4562-b3fc-2c963f66afa6'),
|
|
24
|
+
string_hostname: sampleDefaults('example.com'),
|
|
25
|
+
string_ipv4: sampleDefaults('198.51.100.42'),
|
|
26
|
+
string_ipv6: sampleDefaults('2001:0db8:5b96:0000:0000:426f:8e17:642a'),
|
|
27
|
+
number: sampleDefaults(0),
|
|
28
|
+
number_float: sampleDefaults(0.0),
|
|
29
|
+
integer: sampleDefaults(0),
|
|
30
|
+
boolean: sampleDefaults(true),
|
|
26
31
|
};
|
|
27
32
|
|
|
28
33
|
const primitive = (schema: RMOAS.SchemaObject) => {
|