oas 17.7.3 → 17.8.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/operation.d.ts +23 -4
- package/CHANGELOG.md +34 -0
- package/dist/index.js +10 -5
- package/dist/lib/dedupe-common-parameters.js +5 -1
- package/dist/lib/openapi-to-json-schema.js +5 -1
- package/dist/operation/get-parameters-as-json-schema.js +5 -1
- package/dist/operation.js +62 -7
- package/package.json +2 -2
- package/src/cli/lib/utils.js +10 -7
- package/src/index.ts +6 -4
- package/src/operation.ts +72 -6
- package/tsconfig.test.json +0 -9
package/@types/operation.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RequestBodyExamples } from './operation/get-requestbody-examples';
|
|
2
2
|
import type { CallbackExamples } from './operation/get-callback-examples';
|
|
3
3
|
import type { ResponseExamples } from './operation/get-response-examples';
|
|
4
|
+
import type { SchemaWrapper } from './operation/get-parameters-as-json-schema';
|
|
4
5
|
import * as RMOAS from './rmoas.types';
|
|
5
6
|
declare type SecurityType = 'Basic' | 'Bearer' | 'Query' | 'Header' | 'Cookie' | 'OAuth2' | 'http' | 'apiKey';
|
|
6
7
|
export default class Operation {
|
|
@@ -43,6 +44,10 @@ export default class Operation {
|
|
|
43
44
|
request: string[];
|
|
44
45
|
response: string[];
|
|
45
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* All parameters and request bodies converted into JSON Schema.
|
|
49
|
+
*/
|
|
50
|
+
parameterJsonSchema: SchemaWrapper[];
|
|
46
51
|
constructor(api: RMOAS.OASDocument, path: string, method: RMOAS.HttpMethods, operation: RMOAS.OperationObject);
|
|
47
52
|
getSummary(): string;
|
|
48
53
|
getDescription(): string;
|
|
@@ -84,11 +89,15 @@ export default class Operation {
|
|
|
84
89
|
*/
|
|
85
90
|
hasOperationId(): boolean;
|
|
86
91
|
/**
|
|
87
|
-
* Get an `operationId` for this operation. If one is not present (it's not required by the spec!)
|
|
88
|
-
* and method will be returned instead.
|
|
92
|
+
* Get an `operationId` for this operation. If one is not present (it's not required by the spec!)
|
|
93
|
+
* a hash of the path and method will be returned instead.
|
|
89
94
|
*
|
|
95
|
+
* @param opts
|
|
96
|
+
* @param opts.camelCase Generate a JS method-friendly operation ID when one isn't present.
|
|
90
97
|
*/
|
|
91
|
-
getOperationId(
|
|
98
|
+
getOperationId(opts?: {
|
|
99
|
+
camelCase: boolean;
|
|
100
|
+
}): string;
|
|
92
101
|
/**
|
|
93
102
|
* Return an array of all tags, and their metadata, that exist on this operation.
|
|
94
103
|
*
|
|
@@ -109,13 +118,18 @@ export default class Operation {
|
|
|
109
118
|
*
|
|
110
119
|
*/
|
|
111
120
|
getParameters(): RMOAS.ParameterObject[];
|
|
121
|
+
/**
|
|
122
|
+
* Determine if this operation has any required parameters.
|
|
123
|
+
*
|
|
124
|
+
*/
|
|
125
|
+
hasRequiredParameters(): boolean;
|
|
112
126
|
/**
|
|
113
127
|
* Convert the operation into an array of JSON Schema schemas for each available type of parameter available on the
|
|
114
128
|
* operation.
|
|
115
129
|
*
|
|
116
130
|
* @param globalDefaults Contains an object of user defined schema defaults.
|
|
117
131
|
*/
|
|
118
|
-
getParametersAsJsonSchema(globalDefaults?: Record<string, unknown>):
|
|
132
|
+
getParametersAsJsonSchema(globalDefaults?: Record<string, unknown>): SchemaWrapper[];
|
|
119
133
|
/**
|
|
120
134
|
* Get a single response for this status code, formatted as JSON schema.
|
|
121
135
|
*
|
|
@@ -144,6 +158,11 @@ export default class Operation {
|
|
|
144
158
|
* @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
|
|
145
159
|
*/
|
|
146
160
|
getRequestBodyMediaTypes(): string[];
|
|
161
|
+
/**
|
|
162
|
+
* Determine if this operation has a required request body.
|
|
163
|
+
*
|
|
164
|
+
*/
|
|
165
|
+
hasRequiredRequestBody(): boolean;
|
|
147
166
|
/**
|
|
148
167
|
* Retrieve a specific request body content schema off this operation.
|
|
149
168
|
*
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
## <small>17.8.2 (2022-03-21)</small>
|
|
2
|
+
|
|
3
|
+
* fix: issue where hostname server variables wouldn't match subdomains or ports (#623) ([0630600](https://github.com/readmeio/oas/commit/0630600)), closes [#623](https://github.com/readmeio/oas/issues/623)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## <small>17.8.1 (2022-03-04)</small>
|
|
8
|
+
|
|
9
|
+
* fix: typo in the `--pattern` option ([42db80a](https://github.com/readmeio/oas/commit/42db80a))
|
|
10
|
+
* feat: adding new accessors for determining if an operation has required params (#615) ([c081d92](https://github.com/readmeio/oas/commit/c081d92)), closes [#615](https://github.com/readmeio/oas/issues/615)
|
|
11
|
+
* feat: optionally generate friendlier operationIds (#602) ([6826164](https://github.com/readmeio/oas/commit/6826164)), closes [#602](https://github.com/readmeio/oas/issues/602)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 17.8.0 (2022-03-02)
|
|
16
|
+
|
|
17
|
+
* chore(deps-dev): bump @commitlint/cli from 16.1.0 to 16.2.1 (#612) ([e7364dd](https://github.com/readmeio/oas/commit/e7364dd)), closes [#612](https://github.com/readmeio/oas/issues/612)
|
|
18
|
+
* chore(deps-dev): bump @commitlint/config-conventional (#607) ([5451921](https://github.com/readmeio/oas/commit/5451921)), closes [#607](https://github.com/readmeio/oas/issues/607)
|
|
19
|
+
* chore(deps-dev): bump @readme/eslint-config from 8.4.1 to 8.4.4 (#609) ([7d097f3](https://github.com/readmeio/oas/commit/7d097f3)), closes [#609](https://github.com/readmeio/oas/issues/609)
|
|
20
|
+
* chore(deps-dev): bump @types/jest from 27.4.0 to 27.4.1 (#611) ([ed2b0a3](https://github.com/readmeio/oas/commit/ed2b0a3)), closes [#611](https://github.com/readmeio/oas/issues/611)
|
|
21
|
+
* chore(deps-dev): bump eslint from 8.8.0 to 8.10.0 (#610) ([2382b87](https://github.com/readmeio/oas/commit/2382b87)), closes [#610](https://github.com/readmeio/oas/issues/610)
|
|
22
|
+
* chore(deps-dev): bump eslint-plugin-jsdoc from 37.7.1 to 37.9.5 (#613) ([456bc79](https://github.com/readmeio/oas/commit/456bc79)), closes [#613](https://github.com/readmeio/oas/issues/613)
|
|
23
|
+
* chore(deps-dev): bump jest from 27.4.7 to 27.5.1 (#608) ([41c09f6](https://github.com/readmeio/oas/commit/41c09f6)), closes [#608](https://github.com/readmeio/oas/issues/608)
|
|
24
|
+
* chore(deps-dev): bump typescript from 4.5.5 to 4.6.2 (#605) ([93216ea](https://github.com/readmeio/oas/commit/93216ea)), closes [#605](https://github.com/readmeio/oas/issues/605)
|
|
25
|
+
* chore(deps): bump actions/checkout from 2.4.0 to 3 (#606) ([ea8a28a](https://github.com/readmeio/oas/commit/ea8a28a)), closes [#606](https://github.com/readmeio/oas/issues/606)
|
|
26
|
+
* chore(deps): bump actions/setup-node from 2.5.1 to 3 (#604) ([a463050](https://github.com/readmeio/oas/commit/a463050)), closes [#604](https://github.com/readmeio/oas/issues/604)
|
|
27
|
+
* chore(style): upgrading our core typescript code standards (#598) ([f12d472](https://github.com/readmeio/oas/commit/f12d472)), closes [#598](https://github.com/readmeio/oas/issues/598)
|
|
28
|
+
* feat: adding a dereference option to preserve ref pointers as titles (#601) ([161aebf](https://github.com/readmeio/oas/commit/161aebf)), closes [#601](https://github.com/readmeio/oas/issues/601)
|
|
29
|
+
* feat: upgrading swagger-inline and adding new `pathGlob` and `pattern` options (#614) ([a7dbe6a](https://github.com/readmeio/oas/commit/a7dbe6a)), closes [#614](https://github.com/readmeio/oas/issues/614)
|
|
30
|
+
* build: 17.7.3 release ([0c9974c](https://github.com/readmeio/oas/commit/0c9974c))
|
|
31
|
+
* test: colocating the testing tsconfig with the tests (#599) ([8919177](https://github.com/readmeio/oas/commit/8919177)), closes [#599](https://github.com/readmeio/oas/issues/599)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
1
35
|
## <small>17.7.3 (2022-02-15)</small>
|
|
2
36
|
|
|
3
37
|
* feat: adding a dereference option to preserve ref pointers as titles (#601) ([161aebf](https://github.com/readmeio/oas/commit/161aebf)), closes [#601](https://github.com/readmeio/oas/issues/601)
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,11 @@ var __assign = (this && this.__assign) || function () {
|
|
|
12
12
|
};
|
|
13
13
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
14
|
if (k2 === undefined) k2 = k;
|
|
15
|
-
Object.
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
16
20
|
}) : (function(o, m, k, k2) {
|
|
17
21
|
if (k2 === undefined) k2 = k;
|
|
18
22
|
o[k2] = m[k];
|
|
@@ -80,6 +84,7 @@ exports.Callback = operation_1.Callback;
|
|
|
80
84
|
exports.Webhook = operation_1.Webhook;
|
|
81
85
|
var utils_1 = __importStar(require("./utils"));
|
|
82
86
|
exports.utils = utils_1["default"];
|
|
87
|
+
var SERVER_VARIABLE_REGEX = /{([-_a-zA-Z0-9:.[\]]+)}/g;
|
|
83
88
|
function ensureProtocol(url) {
|
|
84
89
|
// Add protocol to urls starting with // e.g. //example.com
|
|
85
90
|
// This is because httpsnippet throws a HARError when it doesnt have a protocol
|
|
@@ -133,12 +138,12 @@ function normalizedUrl(api, selected) {
|
|
|
133
138
|
*
|
|
134
139
|
* For example, when given `https://{region}.node.example.com/v14` this will return back:
|
|
135
140
|
*
|
|
136
|
-
* https://([-_a-zA-Z0-9[\\]]+).node.example.com/v14
|
|
141
|
+
* https://([-_a-zA-Z0-9:.[\\]]+).node.example.com/v14
|
|
137
142
|
*
|
|
138
143
|
* @param url URL to transform
|
|
139
144
|
*/
|
|
140
145
|
function transformUrlIntoRegex(url) {
|
|
141
|
-
return stripTrailingSlash(url.replace(
|
|
146
|
+
return stripTrailingSlash(url.replace(SERVER_VARIABLE_REGEX, '([-_a-zA-Z0-9:.[\\]]+)'));
|
|
142
147
|
}
|
|
143
148
|
/**
|
|
144
149
|
* Normalize a path so that we can use it with `path-to-regexp` to do operation lookups.
|
|
@@ -358,7 +363,7 @@ var Oas = /** @class */ (function () {
|
|
|
358
363
|
// way we'll be able to extract the parameter names and match them up with the matched server that we obtained
|
|
359
364
|
// above.
|
|
360
365
|
var variables = {};
|
|
361
|
-
Array.from(server.url.matchAll(
|
|
366
|
+
Array.from(server.url.matchAll(SERVER_VARIABLE_REGEX)).forEach(function (variable, y) {
|
|
362
367
|
variables[variable[1]] = found[y + 1];
|
|
363
368
|
});
|
|
364
369
|
return {
|
|
@@ -392,7 +397,7 @@ var Oas = /** @class */ (function () {
|
|
|
392
397
|
if (variables === void 0) { variables = {}; }
|
|
393
398
|
// When we're constructing URLs, server URLs with trailing slashes cause problems with doing lookups, so if we have
|
|
394
399
|
// one here on, slice it off.
|
|
395
|
-
return stripTrailingSlash(url.replace(
|
|
400
|
+
return stripTrailingSlash(url.replace(SERVER_VARIABLE_REGEX, function (original, key) {
|
|
396
401
|
var userVariable = (0, get_user_variable_1["default"])(_this.user, key);
|
|
397
402
|
if (userVariable) {
|
|
398
403
|
return userVariable;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -12,7 +12,11 @@ var __assign = (this && this.__assign) || function () {
|
|
|
12
12
|
};
|
|
13
13
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
14
|
if (k2 === undefined) k2 = k;
|
|
15
|
-
Object.
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
16
20
|
}) : (function(o, m, k, k2) {
|
|
17
21
|
if (k2 === undefined) k2 = k;
|
|
18
22
|
o[k2] = m[k];
|
|
@@ -12,7 +12,11 @@ var __assign = (this && this.__assign) || function () {
|
|
|
12
12
|
};
|
|
13
13
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
14
|
if (k2 === undefined) k2 = k;
|
|
15
|
-
Object.
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
16
20
|
}) : (function(o, m, k, k2) {
|
|
17
21
|
if (k2 === undefined) k2 = k;
|
|
18
22
|
o[k2] = m[k];
|
package/dist/operation.js
CHANGED
|
@@ -16,7 +16,11 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
16
16
|
})();
|
|
17
17
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
18
|
if (k2 === undefined) k2 = k;
|
|
19
|
-
Object.
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
20
24
|
}) : (function(o, m, k, k2) {
|
|
21
25
|
if (k2 === undefined) k2 = k;
|
|
22
26
|
o[k2] = m[k];
|
|
@@ -282,20 +286,33 @@ var Operation = /** @class */ (function () {
|
|
|
282
286
|
return 'operationId' in this.schema;
|
|
283
287
|
};
|
|
284
288
|
/**
|
|
285
|
-
* Get an `operationId` for this operation. If one is not present (it's not required by the spec!)
|
|
286
|
-
* and method will be returned instead.
|
|
289
|
+
* Get an `operationId` for this operation. If one is not present (it's not required by the spec!)
|
|
290
|
+
* a hash of the path and method will be returned instead.
|
|
287
291
|
*
|
|
292
|
+
* @param opts
|
|
293
|
+
* @param opts.camelCase Generate a JS method-friendly operation ID when one isn't present.
|
|
288
294
|
*/
|
|
289
|
-
Operation.prototype.getOperationId = function () {
|
|
295
|
+
Operation.prototype.getOperationId = function (opts) {
|
|
290
296
|
if ('operationId' in this.schema) {
|
|
291
297
|
return this.schema.operationId;
|
|
292
298
|
}
|
|
293
|
-
var
|
|
299
|
+
var method = this.method.toLowerCase();
|
|
300
|
+
var operationId = this.path
|
|
294
301
|
.replace(/[^a-zA-Z0-9]/g, '-') // Remove weird characters
|
|
295
302
|
.replace(/^-|-$/g, '') // Don't start or end with -
|
|
296
303
|
.replace(/--+/g, '-') // Remove double --'s
|
|
297
304
|
.toLowerCase();
|
|
298
|
-
|
|
305
|
+
if (opts === null || opts === void 0 ? void 0 : opts.camelCase) {
|
|
306
|
+
operationId = operationId.replace(/[^a-zA-Z0-9]+(.)/g, function (_, chr) { return chr.toUpperCase(); });
|
|
307
|
+
// If the generated operationId already starts with the method (eg. `getPets`) we don't want
|
|
308
|
+
// to double it up into `getGetPets`.
|
|
309
|
+
if (operationId.startsWith(method)) {
|
|
310
|
+
return operationId;
|
|
311
|
+
}
|
|
312
|
+
operationId = operationId.charAt(0).toUpperCase() + operationId.slice(1);
|
|
313
|
+
return "".concat(method).concat(operationId);
|
|
314
|
+
}
|
|
315
|
+
return "".concat(method, "_").concat(operationId);
|
|
299
316
|
};
|
|
300
317
|
/**
|
|
301
318
|
* Return an array of all tags, and their metadata, that exist on this operation.
|
|
@@ -354,6 +371,13 @@ var Operation = /** @class */ (function () {
|
|
|
354
371
|
}
|
|
355
372
|
return parameters;
|
|
356
373
|
};
|
|
374
|
+
/**
|
|
375
|
+
* Determine if this operation has any required parameters.
|
|
376
|
+
*
|
|
377
|
+
*/
|
|
378
|
+
Operation.prototype.hasRequiredParameters = function () {
|
|
379
|
+
return this.getParameters().some(function (param) { return 'required' in param && param.required; });
|
|
380
|
+
};
|
|
357
381
|
/**
|
|
358
382
|
* Convert the operation into an array of JSON Schema schemas for each available type of parameter available on the
|
|
359
383
|
* operation.
|
|
@@ -361,7 +385,11 @@ var Operation = /** @class */ (function () {
|
|
|
361
385
|
* @param globalDefaults Contains an object of user defined schema defaults.
|
|
362
386
|
*/
|
|
363
387
|
Operation.prototype.getParametersAsJsonSchema = function (globalDefaults) {
|
|
364
|
-
|
|
388
|
+
if (this.parameterJsonSchema) {
|
|
389
|
+
return this.parameterJsonSchema;
|
|
390
|
+
}
|
|
391
|
+
this.parameterJsonSchema = (0, get_parameters_as_json_schema_1["default"])(this, this.api, globalDefaults);
|
|
392
|
+
return this.parameterJsonSchema;
|
|
365
393
|
};
|
|
366
394
|
/**
|
|
367
395
|
* Get a single response for this status code, formatted as JSON schema.
|
|
@@ -403,6 +431,33 @@ var Operation = /** @class */ (function () {
|
|
|
403
431
|
}
|
|
404
432
|
return Object.keys(requestBody.content);
|
|
405
433
|
};
|
|
434
|
+
/**
|
|
435
|
+
* Determine if this operation has a required request body.
|
|
436
|
+
*
|
|
437
|
+
*/
|
|
438
|
+
Operation.prototype.hasRequiredRequestBody = function () {
|
|
439
|
+
if (!this.hasRequestBody()) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
var requestBody = this.schema.requestBody;
|
|
443
|
+
if (RMOAS.isRef(requestBody)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
if (requestBody.required) {
|
|
447
|
+
return true;
|
|
448
|
+
}
|
|
449
|
+
// The OpenAPI spec isn't clear on the differentiation between schema `required` and
|
|
450
|
+
// `requestBody.required` because you can have required top-level schema properties but a
|
|
451
|
+
// non-required requestBody that negates each other.
|
|
452
|
+
//
|
|
453
|
+
// To kind of work ourselves around this and present a better QOL for this accessor, if at this
|
|
454
|
+
// final point where we don't have a required request body, but the underlying Media Type Object
|
|
455
|
+
// schema says that it has required properties then we should ultimately recognize that this
|
|
456
|
+
// request body is required -- even as the request body description says otherwise.
|
|
457
|
+
return !!this.getParametersAsJsonSchema()
|
|
458
|
+
.filter(function (js) { return ['body', 'formData'].includes(js.type); })
|
|
459
|
+
.find(function (js) { return js.schema && Array.isArray(js.schema.required) && js.schema.required.length; });
|
|
460
|
+
};
|
|
406
461
|
/**
|
|
407
462
|
* Retrieve a specific request body content schema off this operation.
|
|
408
463
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oas",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.8.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)",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"oas-normalize": "^5.1.1",
|
|
63
63
|
"openapi-types": "^10.0.0",
|
|
64
64
|
"path-to-regexp": "^6.2.0",
|
|
65
|
-
"swagger-inline": "^5.0
|
|
65
|
+
"swagger-inline": "^5.1.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@commitlint/cli": "^16.0.1",
|
package/src/cli/lib/utils.js
CHANGED
|
@@ -44,17 +44,20 @@ exports.findSwagger = async function (info, cb) {
|
|
|
44
44
|
process.exit(1);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
let pathGlob = '**/*';
|
|
47
|
+
let pathGlob = info.opts.pathGlob || '**/*';
|
|
48
48
|
if (info.opts.path) {
|
|
49
49
|
pathGlob = `${info.opts.path.replace(/\/$/, '')}/*`;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const generatedDefinition = await swaggerInline(pathGlob, {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
)
|
|
52
|
+
const generatedDefinition = await swaggerInline(pathGlob, {
|
|
53
|
+
format: '.json',
|
|
54
|
+
scope: info.opts.scope,
|
|
55
|
+
base,
|
|
56
|
+
pattern: info.opts.pattern || null,
|
|
57
|
+
}).catch(err => {
|
|
58
|
+
console.error(err);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
});
|
|
58
61
|
|
|
59
62
|
let oas = new OASNormalize(generatedDefinition);
|
|
60
63
|
const bundledDefinition = await oas.bundle().catch(err => {
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ type PathMatches = PathMatch[];
|
|
|
24
24
|
|
|
25
25
|
type Variables = Record<string, string | number | { default?: string | number }[] | { default?: string | number }>;
|
|
26
26
|
|
|
27
|
+
const SERVER_VARIABLE_REGEX = /{([-_a-zA-Z0-9:.[\]]+)}/g;
|
|
28
|
+
|
|
27
29
|
function ensureProtocol(url: string) {
|
|
28
30
|
// Add protocol to urls starting with // e.g. //example.com
|
|
29
31
|
// This is because httpsnippet throws a HARError when it doesnt have a protocol
|
|
@@ -84,12 +86,12 @@ function normalizedUrl(api: RMOAS.OASDocument, selected: number) {
|
|
|
84
86
|
*
|
|
85
87
|
* For example, when given `https://{region}.node.example.com/v14` this will return back:
|
|
86
88
|
*
|
|
87
|
-
* https://([-_a-zA-Z0-9[\\]]+).node.example.com/v14
|
|
89
|
+
* https://([-_a-zA-Z0-9:.[\\]]+).node.example.com/v14
|
|
88
90
|
*
|
|
89
91
|
* @param url URL to transform
|
|
90
92
|
*/
|
|
91
93
|
function transformUrlIntoRegex(url: string) {
|
|
92
|
-
return stripTrailingSlash(url.replace(
|
|
94
|
+
return stripTrailingSlash(url.replace(SERVER_VARIABLE_REGEX, '([-_a-zA-Z0-9:.[\\]]+)'));
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
/**
|
|
@@ -365,7 +367,7 @@ export default class Oas {
|
|
|
365
367
|
// way we'll be able to extract the parameter names and match them up with the matched server that we obtained
|
|
366
368
|
// above.
|
|
367
369
|
const variables: Record<string, string | number> = {};
|
|
368
|
-
Array.from(server.url.matchAll(
|
|
370
|
+
Array.from(server.url.matchAll(SERVER_VARIABLE_REGEX)).forEach((variable, y) => {
|
|
369
371
|
variables[variable[1]] = found[y + 1];
|
|
370
372
|
});
|
|
371
373
|
|
|
@@ -401,7 +403,7 @@ export default class Oas {
|
|
|
401
403
|
// When we're constructing URLs, server URLs with trailing slashes cause problems with doing lookups, so if we have
|
|
402
404
|
// one here on, slice it off.
|
|
403
405
|
return stripTrailingSlash(
|
|
404
|
-
url.replace(
|
|
406
|
+
url.replace(SERVER_VARIABLE_REGEX, (original: string, key: string) => {
|
|
405
407
|
const userVariable = getUserVariable(this.user, key);
|
|
406
408
|
if (userVariable) {
|
|
407
409
|
return userVariable as string;
|
package/src/operation.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
|
|
|
2
2
|
import type { RequestBodyExamples } from './operation/get-requestbody-examples';
|
|
3
3
|
import type { CallbackExamples } from './operation/get-callback-examples';
|
|
4
4
|
import type { ResponseExamples } from './operation/get-response-examples';
|
|
5
|
+
import type { SchemaWrapper } from './operation/get-parameters-as-json-schema';
|
|
5
6
|
|
|
6
7
|
import * as RMOAS from './rmoas.types';
|
|
7
8
|
import dedupeCommonParameters from './lib/dedupe-common-parameters';
|
|
@@ -65,6 +66,11 @@ export default class Operation {
|
|
|
65
66
|
response: string[];
|
|
66
67
|
};
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* All parameters and request bodies converted into JSON Schema.
|
|
71
|
+
*/
|
|
72
|
+
parameterJsonSchema: SchemaWrapper[];
|
|
73
|
+
|
|
68
74
|
constructor(api: RMOAS.OASDocument, path: string, method: RMOAS.HttpMethods, operation: RMOAS.OperationObject) {
|
|
69
75
|
this.schema = operation;
|
|
70
76
|
this.api = api;
|
|
@@ -323,22 +329,38 @@ export default class Operation {
|
|
|
323
329
|
}
|
|
324
330
|
|
|
325
331
|
/**
|
|
326
|
-
* Get an `operationId` for this operation. If one is not present (it's not required by the spec!)
|
|
327
|
-
* and method will be returned instead.
|
|
332
|
+
* Get an `operationId` for this operation. If one is not present (it's not required by the spec!)
|
|
333
|
+
* a hash of the path and method will be returned instead.
|
|
328
334
|
*
|
|
335
|
+
* @param opts
|
|
336
|
+
* @param opts.camelCase Generate a JS method-friendly operation ID when one isn't present.
|
|
329
337
|
*/
|
|
330
|
-
getOperationId(): string {
|
|
338
|
+
getOperationId(opts?: { camelCase: boolean }): string {
|
|
331
339
|
if ('operationId' in this.schema) {
|
|
332
340
|
return this.schema.operationId;
|
|
333
341
|
}
|
|
334
342
|
|
|
335
|
-
const
|
|
343
|
+
const method = this.method.toLowerCase();
|
|
344
|
+
let operationId = this.path
|
|
336
345
|
.replace(/[^a-zA-Z0-9]/g, '-') // Remove weird characters
|
|
337
346
|
.replace(/^-|-$/g, '') // Don't start or end with -
|
|
338
347
|
.replace(/--+/g, '-') // Remove double --'s
|
|
339
348
|
.toLowerCase();
|
|
340
349
|
|
|
341
|
-
|
|
350
|
+
if (opts?.camelCase) {
|
|
351
|
+
operationId = operationId.replace(/[^a-zA-Z0-9]+(.)/g, (_, chr) => chr.toUpperCase());
|
|
352
|
+
|
|
353
|
+
// If the generated operationId already starts with the method (eg. `getPets`) we don't want
|
|
354
|
+
// to double it up into `getGetPets`.
|
|
355
|
+
if (operationId.startsWith(method)) {
|
|
356
|
+
return operationId;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
operationId = operationId.charAt(0).toUpperCase() + operationId.slice(1);
|
|
360
|
+
return `${method}${operationId}`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return `${method}_${operationId}`;
|
|
342
364
|
}
|
|
343
365
|
|
|
344
366
|
/**
|
|
@@ -405,6 +427,14 @@ export default class Operation {
|
|
|
405
427
|
return parameters;
|
|
406
428
|
}
|
|
407
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Determine if this operation has any required parameters.
|
|
432
|
+
*
|
|
433
|
+
*/
|
|
434
|
+
hasRequiredParameters() {
|
|
435
|
+
return this.getParameters().some(param => 'required' in param && param.required);
|
|
436
|
+
}
|
|
437
|
+
|
|
408
438
|
/**
|
|
409
439
|
* Convert the operation into an array of JSON Schema schemas for each available type of parameter available on the
|
|
410
440
|
* operation.
|
|
@@ -412,7 +442,12 @@ export default class Operation {
|
|
|
412
442
|
* @param globalDefaults Contains an object of user defined schema defaults.
|
|
413
443
|
*/
|
|
414
444
|
getParametersAsJsonSchema(globalDefaults?: Record<string, unknown>) {
|
|
415
|
-
|
|
445
|
+
if (this.parameterJsonSchema) {
|
|
446
|
+
return this.parameterJsonSchema;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
this.parameterJsonSchema = getParametersAsJsonSchema(this, this.api, globalDefaults);
|
|
450
|
+
return this.parameterJsonSchema;
|
|
416
451
|
}
|
|
417
452
|
|
|
418
453
|
/**
|
|
@@ -461,6 +496,37 @@ export default class Operation {
|
|
|
461
496
|
return Object.keys(requestBody.content);
|
|
462
497
|
}
|
|
463
498
|
|
|
499
|
+
/**
|
|
500
|
+
* Determine if this operation has a required request body.
|
|
501
|
+
*
|
|
502
|
+
*/
|
|
503
|
+
hasRequiredRequestBody() {
|
|
504
|
+
if (!this.hasRequestBody()) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const requestBody = this.schema.requestBody;
|
|
509
|
+
if (RMOAS.isRef(requestBody)) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (requestBody.required) {
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// The OpenAPI spec isn't clear on the differentiation between schema `required` and
|
|
518
|
+
// `requestBody.required` because you can have required top-level schema properties but a
|
|
519
|
+
// non-required requestBody that negates each other.
|
|
520
|
+
//
|
|
521
|
+
// To kind of work ourselves around this and present a better QOL for this accessor, if at this
|
|
522
|
+
// final point where we don't have a required request body, but the underlying Media Type Object
|
|
523
|
+
// schema says that it has required properties then we should ultimately recognize that this
|
|
524
|
+
// request body is required -- even as the request body description says otherwise.
|
|
525
|
+
return !!this.getParametersAsJsonSchema()
|
|
526
|
+
.filter(js => ['body', 'formData'].includes(js.type))
|
|
527
|
+
.find(js => js.schema && Array.isArray(js.schema.required) && js.schema.required.length);
|
|
528
|
+
}
|
|
529
|
+
|
|
464
530
|
/**
|
|
465
531
|
* Retrieve a specific request body content schema off this operation.
|
|
466
532
|
*
|