oas 20.3.0 → 20.5.0

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.
@@ -1,3 +1,5 @@
1
1
  {
2
- "js/ts.implicitProjectConfig.strictNullChecks": false
2
+ "editor.codeActionsOnSave": {
3
+ "source.fixAll": true
4
+ }
3
5
  }
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 20.5.0 (2023-03-02)
2
+
3
+ * chore: bumping out of date deps ([a905664](https://github.com/readmeio/oas/commit/a905664))
4
+ * chore(deps): bumping deps ([f0de8b9](https://github.com/readmeio/oas/commit/f0de8b9))
5
+ * fix: only adding components to generated JSON Schema if we need to (#732) ([9787b4d](https://github.com/readmeio/oas/commit/9787b4d)), closes [#732](https://github.com/readmeio/oas/issues/732)
6
+
7
+
8
+
9
+ ## 20.4.0 (2023-01-12)
10
+
11
+ * feat: pass through requestBody descriptions (#730) ([3272137](https://github.com/readmeio/oas/commit/3272137)), closes [#730](https://github.com/readmeio/oas/issues/730)
12
+
13
+
14
+
1
15
  ## 20.3.0 (2023-01-03)
2
16
 
3
17
  * chore: bumping deps ([ed5e473](https://github.com/readmeio/oas/commit/ed5e473))
@@ -5,6 +5,7 @@ export interface SchemaWrapper {
5
5
  type: string;
6
6
  label?: string;
7
7
  schema: SchemaObject;
8
+ description?: string;
8
9
  deprecatedProps?: SchemaWrapper;
9
10
  }
10
11
  /**
@@ -127,7 +127,7 @@ function getParametersAsJSONSchema(operation, api, opts) {
127
127
  var requestBody = operation.getRequestBody();
128
128
  if (!requestBody || !Array.isArray(requestBody))
129
129
  return null;
130
- var mediaType = requestBody[0], mediaTypeObject = requestBody[1];
130
+ var mediaType = requestBody[0], mediaTypeObject = requestBody[1], description = requestBody[2];
131
131
  var type = mediaType === 'application/x-www-form-urlencoded' ? 'formData' : 'body';
132
132
  // If this schema is completely empty, don't bother processing it.
133
133
  if (!mediaTypeObject.schema || !Object.keys(mediaTypeObject.schema).length) {
@@ -157,30 +157,38 @@ function getParametersAsJSONSchema(operation, api, opts) {
157
157
  if (!Object.keys(cleanedSchema).length) {
158
158
  return null;
159
159
  }
160
- return {
161
- type: type,
162
- label: exports.types[type],
163
- schema: (0, openapi_to_json_schema_1.isPrimitive)(cleanedSchema)
160
+ return __assign({ type: type, label: exports.types[type], schema: (0, openapi_to_json_schema_1.isPrimitive)(cleanedSchema)
164
161
  ? cleanedSchema
165
- : __assign(__assign({}, cleanedSchema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(cleanedSchema, api) }),
166
- deprecatedProps: getDeprecated(cleanedSchema, type)
167
- };
162
+ : __assign(__assign({}, cleanedSchema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(cleanedSchema, api) }), deprecatedProps: getDeprecated(cleanedSchema, type) }, (description ? { description: description } : {}));
168
163
  }
169
164
  function transformComponents() {
170
165
  if (!('components' in api)) {
171
166
  return false;
172
167
  }
173
- var components = {};
168
+ var components = {
169
+ /**
170
+ * Initializing an empty `components[componentType] = {}` object within the `forEach` below
171
+ * is incredibly slow because each of these component types has a wide variety of shapes. So
172
+ * in order to not have TS compilation times that takes literally **seconds** because of a
173
+ * single line we're instead opting to prefill this object with some empty placeholders that
174
+ * we'll later remove if they didn't get used.
175
+ *
176
+ * Obviously not ideal but I'd rather have a couple lines of boilerplate nonsense than having
177
+ * to wait a noticeably frustrating amount of time for TS Intellisense to reload itself after
178
+ * you save a line in any file.
179
+ */
180
+ examples: {},
181
+ schemas: {},
182
+ responses: {},
183
+ parameters: {},
184
+ requestBodies: {},
185
+ headers: {},
186
+ securitySchemes: {},
187
+ links: {},
188
+ callbacks: {}
189
+ };
174
190
  Object.keys(api.components).forEach(function (componentType) {
175
191
  if (typeof api.components[componentType] === 'object' && !Array.isArray(api.components[componentType])) {
176
- /**
177
- * Typescript is INCREDIBLY SLOW parsing this one line. I think it's because of the large
178
- * variety of types that that object could represent but I can't yet think of a way to get
179
- * around that.
180
- *
181
- * @todo
182
- */
183
- components[componentType] = {};
184
192
  Object.keys(api.components[componentType]).forEach(function (schemaName) {
185
193
  var componentSchema = (0, clone_object_1["default"])(api.components[componentType][schemaName]);
186
194
  components[componentType][schemaName] = (0, openapi_to_json_schema_1["default"])(componentSchema, {
@@ -191,6 +199,22 @@ function getParametersAsJSONSchema(operation, api, opts) {
191
199
  });
192
200
  }
193
201
  });
202
+ // If none of our above component type placeholders got used let's clean them up.
203
+ [
204
+ 'examples',
205
+ 'schemas',
206
+ 'responses',
207
+ 'parameters',
208
+ 'requestBodies',
209
+ 'headers',
210
+ 'securitySchemes',
211
+ 'links',
212
+ 'callbacks',
213
+ ].forEach(function (componentType) {
214
+ if (!Object.keys(components[componentType]).length) {
215
+ delete components[componentType];
216
+ }
217
+ });
194
218
  return components;
195
219
  }
196
220
  function transformParameters() {
@@ -345,10 +369,14 @@ function getParametersAsJSONSchema(operation, api, opts) {
345
369
  if (!operation.hasParameters() && !operation.hasRequestBody()) {
346
370
  return null;
347
371
  }
348
- var components = transformComponents();
349
372
  var typeKeys = Object.keys(exports.types);
350
- return (_a = [transformRequestBody()])
351
- .concat.apply(_a, transformParameters()).filter(Boolean)
373
+ var jsonSchema = (_a = [transformRequestBody()]).concat.apply(_a, transformParameters()).filter(Boolean);
374
+ // We should only include `components`, or even bother transforming components into JSON Schema,
375
+ // if we either have circular refs or if we have discriminator mapping refs somewhere and want to
376
+ // include them.
377
+ var shouldIncludeComponents = hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs);
378
+ var components = shouldIncludeComponents ? transformComponents() : false;
379
+ return jsonSchema
352
380
  .map(function (group) {
353
381
  /**
354
382
  * Since this library assumes that the schema has already been dereferenced, adding every
@@ -357,13 +385,9 @@ function getParametersAsJSONSchema(operation, api, opts) {
357
385
  *
358
386
  * @todo
359
387
  */
360
- if (components) {
361
- // We should only include components if we've got circular refs or we have discriminator
362
- // mapping refs (we want to include them).
363
- if (hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs)) {
364
- // Fixing typing and confused version mismatches
365
- group.schema.components = components;
366
- }
388
+ if (components && shouldIncludeComponents) {
389
+ // Fixing typing and confused version mismatches
390
+ group.schema.components = components;
367
391
  }
368
392
  // Delete deprecatedProps if it's null on the schema.
369
393
  if (!group.deprecatedProps)
@@ -210,7 +210,7 @@ export default class Operation {
210
210
  * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
211
211
  * @param mediaType Specific request body media type to retrieve if present.
212
212
  */
213
- getRequestBody(mediaType?: string): false | RMOAS.MediaTypeObject | [string, RMOAS.MediaTypeObject];
213
+ getRequestBody(mediaType?: string): false | RMOAS.MediaTypeObject | [string, RMOAS.MediaTypeObject, ...string[]];
214
214
  /**
215
215
  * Retrieve an array of request body examples that this operation has.
216
216
  *
package/dist/operation.js CHANGED
@@ -48,6 +48,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
48
48
  __setModuleDefault(result, mod);
49
49
  return result;
50
50
  };
51
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
52
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
53
+ if (ar || !(i in from)) {
54
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
55
+ ar[i] = from[i];
56
+ }
57
+ }
58
+ return to.concat(ar || Array.prototype.slice.call(from));
59
+ };
51
60
  var __importDefault = (this && this.__importDefault) || function (mod) {
52
61
  return (mod && mod.__esModule) ? mod : { "default": mod };
53
62
  };
@@ -543,7 +552,10 @@ var Operation = /** @class */ (function () {
543
552
  });
544
553
  }
545
554
  if (availableMediaType) {
546
- return [availableMediaType, requestBody.content[availableMediaType]];
555
+ return __spreadArray([
556
+ availableMediaType,
557
+ requestBody.content[availableMediaType]
558
+ ], (requestBody.description ? [requestBody.description] : []), true);
547
559
  }
548
560
  return false;
549
561
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oas",
3
- "version": "20.3.0",
3
+ "version": "20.5.0",
4
4
  "description": "Comprehensive tooling for working with OpenAPI definitions",
5
5
  "license": "MIT",
6
6
  "author": "ReadMe <support@readme.io> (https://readme.com)",
@@ -52,26 +52,26 @@
52
52
  "jsonpath-plus": "^7.2.0",
53
53
  "jsonpointer": "^5.0.0",
54
54
  "memoizee": "^0.4.14",
55
- "oas-normalize": "^8.3.0",
55
+ "oas-normalize": "^8.3.2",
56
56
  "openapi-types": "^12.1.0",
57
57
  "path-to-regexp": "^6.2.0"
58
58
  },
59
59
  "devDependencies": {
60
- "@commitlint/cli": "^17.3.0",
61
- "@commitlint/config-conventional": "^17.3.0",
62
- "@readme/eslint-config": "^10.3.2",
60
+ "@commitlint/cli": "^17.4.4",
61
+ "@commitlint/config-conventional": "^17.4.4",
62
+ "@readme/eslint-config": "^10.5.1",
63
63
  "@readme/oas-examples": "^5.7.1",
64
64
  "@readme/openapi-parser": "^2.4.0",
65
- "@types/jest": "^29.2.5",
65
+ "@types/jest": "^29.4.0",
66
66
  "@types/json-schema-merge-allof": "^0.6.1",
67
67
  "@types/memoizee": "^0.4.6",
68
- "@types/node": "^18.11.18",
69
- "eslint": "^8.31.0",
68
+ "@types/node": "^18.14.4",
69
+ "eslint": "^8.35.0",
70
70
  "husky": "^8.0.3",
71
- "jest": "^29.3.1",
72
- "prettier": "^2.8.1",
73
- "ts-jest": "^29.0.3",
74
- "typescript": "^4.9.4"
71
+ "jest": "^29.4.3",
72
+ "prettier": "^2.8.4",
73
+ "ts-jest": "^29.0.5",
74
+ "typescript": "^4.9.5"
75
75
  },
76
76
  "prettier": "@readme/eslint-config/prettier",
77
77
  "commitlint": {
package/src/index.ts CHANGED
@@ -110,7 +110,7 @@ function normalizePath(path: string) {
110
110
  // also handling quirks here like if there's an optional proceeding or trailing curly bracket
111
111
  // (`{{pathParam}` or `{pathParam}}`) as any unescaped curlys, which would be present in
112
112
  // `:pathParam}`, will throw a regex exception.
113
- .replace(/({?){(.*?)}(}?)/g, function (str, ...args) {
113
+ .replace(/({?){(.*?)}(}?)/g, (str, ...args) => {
114
114
  // If a path contains a path parameter with hyphens, like `:dlc-release`, when it's regexd
115
115
  // with `path-to-regexp` it match against the `:dlc` portion of the parameter, breaking all
116
116
  // matching against the full path.
@@ -1,5 +1,5 @@
1
1
  function matchesMediaType(types: string[], mediaType: string): boolean {
2
- return types.some(function (type) {
2
+ return types.some(type => {
3
3
  return mediaType.indexOf(type) > -1;
4
4
  });
5
5
  }
@@ -13,6 +13,7 @@ export interface SchemaWrapper {
13
13
  type: string;
14
14
  label?: string;
15
15
  schema: SchemaObject;
16
+ description?: string;
16
17
  deprecatedProps?: SchemaWrapper;
17
18
  }
18
19
 
@@ -124,7 +125,7 @@ export default function getParametersAsJSONSchema(
124
125
  const requestBody = operation.getRequestBody();
125
126
  if (!requestBody || !Array.isArray(requestBody)) return null;
126
127
 
127
- const [mediaType, mediaTypeObject] = requestBody;
128
+ const [mediaType, mediaTypeObject, description] = requestBody;
128
129
  const type = mediaType === 'application/x-www-form-urlencoded' ? 'formData' : 'body';
129
130
 
130
131
  // If this schema is completely empty, don't bother processing it.
@@ -146,6 +147,7 @@ export default function getParametersAsJSONSchema(
146
147
  // We're cloning the request schema because we've had issues with request schemas that were
147
148
  // dereferenced being processed multiple times because their component is also processed.
148
149
  const requestSchema = cloneObject(mediaTypeObject.schema);
150
+
149
151
  const cleanedSchema = toJSONSchema(requestSchema, {
150
152
  globalDefaults: opts.globalDefaults,
151
153
  prevSchemas,
@@ -168,6 +170,7 @@ export default function getParametersAsJSONSchema(
168
170
  $schema: getSchemaVersionString(cleanedSchema, api),
169
171
  },
170
172
  deprecatedProps: getDeprecated(cleanedSchema, type),
173
+ ...(description ? { description } : {}),
171
174
  };
172
175
  }
173
176
 
@@ -176,19 +179,31 @@ export default function getParametersAsJSONSchema(
176
179
  return false;
177
180
  }
178
181
 
179
- const components: Partial<ComponentsObject> = {};
182
+ const components: Partial<ComponentsObject> = {
183
+ /**
184
+ * Initializing an empty `components[componentType] = {}` object within the `forEach` below
185
+ * is incredibly slow because each of these component types has a wide variety of shapes. So
186
+ * in order to not have TS compilation times that takes literally **seconds** because of a
187
+ * single line we're instead opting to prefill this object with some empty placeholders that
188
+ * we'll later remove if they didn't get used.
189
+ *
190
+ * Obviously not ideal but I'd rather have a couple lines of boilerplate nonsense than having
191
+ * to wait a noticeably frustrating amount of time for TS Intellisense to reload itself after
192
+ * you save a line in any file.
193
+ */
194
+ examples: {},
195
+ schemas: {},
196
+ responses: {},
197
+ parameters: {},
198
+ requestBodies: {},
199
+ headers: {},
200
+ securitySchemes: {},
201
+ links: {},
202
+ callbacks: {},
203
+ };
180
204
 
181
205
  Object.keys(api.components).forEach((componentType: keyof ComponentsObject) => {
182
206
  if (typeof api.components[componentType] === 'object' && !Array.isArray(api.components[componentType])) {
183
- /**
184
- * Typescript is INCREDIBLY SLOW parsing this one line. I think it's because of the large
185
- * variety of types that that object could represent but I can't yet think of a way to get
186
- * around that.
187
- *
188
- * @todo
189
- */
190
- components[componentType] = {};
191
-
192
207
  Object.keys(api.components[componentType]).forEach(schemaName => {
193
208
  const componentSchema = cloneObject(api.components[componentType][schemaName]);
194
209
  components[componentType][schemaName] = toJSONSchema(componentSchema as SchemaObject, {
@@ -200,6 +215,23 @@ export default function getParametersAsJSONSchema(
200
215
  }
201
216
  });
202
217
 
218
+ // If none of our above component type placeholders got used let's clean them up.
219
+ [
220
+ 'examples',
221
+ 'schemas',
222
+ 'responses',
223
+ 'parameters',
224
+ 'requestBodies',
225
+ 'headers',
226
+ 'securitySchemes',
227
+ 'links',
228
+ 'callbacks',
229
+ ].forEach((componentType: keyof ComponentsObject) => {
230
+ if (!Object.keys(components[componentType]).length) {
231
+ delete components[componentType];
232
+ }
233
+ });
234
+
203
235
  return components;
204
236
  }
205
237
 
@@ -375,12 +407,18 @@ export default function getParametersAsJSONSchema(
375
407
  return null;
376
408
  }
377
409
 
378
- const components = transformComponents();
379
-
380
410
  const typeKeys = Object.keys(types);
381
- return [transformRequestBody()]
382
- .concat(...transformParameters())
383
- .filter(Boolean)
411
+ const jsonSchema = [transformRequestBody()].concat(...transformParameters()).filter(Boolean);
412
+
413
+ // We should only include `components`, or even bother transforming components into JSON Schema,
414
+ // if we either have circular refs or if we have discriminator mapping refs somewhere and want to
415
+ // include them.
416
+ const shouldIncludeComponents =
417
+ hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs);
418
+
419
+ const components = shouldIncludeComponents ? transformComponents() : false;
420
+
421
+ return jsonSchema
384
422
  .map(group => {
385
423
  /**
386
424
  * Since this library assumes that the schema has already been dereferenced, adding every
@@ -389,13 +427,9 @@ export default function getParametersAsJSONSchema(
389
427
  *
390
428
  * @todo
391
429
  */
392
- if (components) {
393
- // We should only include components if we've got circular refs or we have discriminator
394
- // mapping refs (we want to include them).
395
- if (hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs)) {
396
- // Fixing typing and confused version mismatches
397
- (group.schema.components as ComponentsObject) = components;
398
- }
430
+ if (components && shouldIncludeComponents) {
431
+ // Fixing typing and confused version mismatches
432
+ (group.schema.components as ComponentsObject) = components;
399
433
  }
400
434
 
401
435
  // Delete deprecatedProps if it's null on the schema.
package/src/operation.ts CHANGED
@@ -621,7 +621,7 @@ export default class Operation {
621
621
  * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#mediaTypeObject}
622
622
  * @param mediaType Specific request body media type to retrieve if present.
623
623
  */
624
- getRequestBody(mediaType?: string): false | RMOAS.MediaTypeObject | [string, RMOAS.MediaTypeObject] {
624
+ getRequestBody(mediaType?: string): false | RMOAS.MediaTypeObject | [string, RMOAS.MediaTypeObject, ...string[]] {
625
625
  if (!this.hasRequestBody()) {
626
626
  return false;
627
627
  }
@@ -660,7 +660,11 @@ export default class Operation {
660
660
  }
661
661
 
662
662
  if (availableMediaType) {
663
- return [availableMediaType, requestBody.content[availableMediaType]];
663
+ return [
664
+ availableMediaType,
665
+ requestBody.content[availableMediaType],
666
+ ...(requestBody.description ? [requestBody.description] : []),
667
+ ];
664
668
  }
665
669
 
666
670
  return false;