oas 20.9.0 → 20.10.1

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.
@@ -25,7 +25,7 @@ export interface toJSONSchemaOptions {
25
25
  */
26
26
  isPolymorphicAllOfChild?: boolean;
27
27
  /**
28
- * Array of parent `default` schemas to utilzie when attempting to path together schema defaults.
28
+ * Array of parent `default` schemas to utilize when attempting to path together schema defaults.
29
29
  */
30
30
  prevDefaultSchemas?: RMOAS.SchemaObject[];
31
31
  /**
@@ -363,6 +363,12 @@ function toJSONSchema(data, opts) {
363
363
  else {
364
364
  schema[polyType][idx] = toJSONSchema(item, polyOptions);
365
365
  }
366
+ // Ensure that we don't have any invalid `required` booleans lying around.
367
+ if ((0, helpers_1.isObject)(schema[polyType][idx]) &&
368
+ 'required' in schema[polyType][idx] &&
369
+ typeof schema[polyType][idx].required === 'boolean') {
370
+ delete schema[polyType][idx].required;
371
+ }
366
372
  });
367
373
  }
368
374
  });
@@ -599,6 +605,12 @@ function toJSONSchema(data, opts) {
599
605
  refLogger: refLogger,
600
606
  transformer: transformer,
601
607
  });
608
+ // If we have a non-array `required` entry in our `items` schema then it's invalid and we
609
+ // should remove it. We only support non-array boolean `required` properties inside object
610
+ // properties.
611
+ if ((0, helpers_1.isObject)(schema.items) && 'required' in schema.items && !Array.isArray(schema.items.required)) {
612
+ delete schema.items.required;
613
+ }
602
614
  }
603
615
  }
604
616
  else if ('properties' in schema || 'additionalProperties' in schema) {
@@ -631,19 +643,39 @@ function toJSONSchema(data, opts) {
631
643
  transformer: transformer,
632
644
  });
633
645
  // If this property is read or write only then we should fully hide it from its parent schema.
646
+ var propShouldBeUpdated = true;
634
647
  if ((hideReadOnlyProperties || hideWriteOnlyProperties) && !Object.keys(newPropSchema).length) {
635
648
  // We should only delete this schema if it wasn't already empty though. We do this
636
649
  // because we (un)fortunately have handling in our API Explorer form system for
637
650
  // schemas that are devoid of any `type` declaration.
638
651
  if (Object.keys(schema.properties[prop]).length > 0) {
639
652
  delete schema.properties[prop];
640
- }
641
- else {
642
- schema.properties[prop] = newPropSchema;
653
+ propShouldBeUpdated = false;
643
654
  }
644
655
  }
645
- else {
656
+ if (propShouldBeUpdated) {
646
657
  schema.properties[prop] = newPropSchema;
658
+ /**
659
+ * JSON Schema does not have any support for `required: <boolean>` but because some
660
+ * of our users do this, and it does not throw OpenAPI validation errors thanks to
661
+ * some extremely loose typings around `schema` in the official JSON Schema
662
+ * definitions that the OAI offers, we're opting to support these users and upgrade
663
+ * their invalid `required` definitions into ones that our tooling can interpret.
664
+ *
665
+ * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json#L1114-L1121}
666
+ */
667
+ if ((0, helpers_1.isObject)(newPropSchema) &&
668
+ 'required' in newPropSchema &&
669
+ typeof newPropSchema.required === 'boolean' &&
670
+ newPropSchema.required === true) {
671
+ if ('required' in schema && Array.isArray(schema.required)) {
672
+ schema.required.push(prop);
673
+ }
674
+ else {
675
+ schema.required = [prop];
676
+ }
677
+ delete schema.properties[prop].required;
678
+ }
647
679
  }
648
680
  }
649
681
  });
@@ -169,28 +169,12 @@ function getParametersAsJSONSchema(operation, api, opts) {
169
169
  if (!('components' in api)) {
170
170
  return false;
171
171
  }
172
- var components = {
173
- /**
174
- * Initializing an empty `components[componentType] = {}` object within the `forEach` below
175
- * is incredibly slow because each of these component types has a wide variety of shapes. So
176
- * in order to not have TS compilation times that takes literally **seconds** because of a
177
- * single line we're instead opting to prefill this object with some empty placeholders that
178
- * we'll later remove if they didn't get used.
179
- *
180
- * Obviously not ideal but I'd rather have a couple lines of boilerplate nonsense than having
181
- * to wait a noticeably frustrating amount of time for TS Intellisense to reload itself after
182
- * you save a line in any file.
183
- */
184
- examples: {},
185
- schemas: {},
186
- responses: {},
187
- parameters: {},
188
- requestBodies: {},
189
- headers: {},
190
- securitySchemes: {},
191
- links: {},
192
- callbacks: {},
193
- };
172
+ var components = __assign({}, Object.keys(api.components)
173
+ .map(function (componentType) {
174
+ var _a;
175
+ return (_a = {}, _a[componentType] = {}, _a);
176
+ })
177
+ .reduce(function (prev, next) { return Object.assign(prev, next); }, {}));
194
178
  Object.keys(api.components).forEach(function (componentType) {
195
179
  if (typeof api.components[componentType] === 'object' && !Array.isArray(api.components[componentType])) {
196
180
  Object.keys(api.components[componentType]).forEach(function (schemaName) {
@@ -206,17 +190,7 @@ function getParametersAsJSONSchema(operation, api, opts) {
206
190
  }
207
191
  });
208
192
  // If none of our above component type placeholders got used let's clean them up.
209
- [
210
- 'examples',
211
- 'schemas',
212
- 'responses',
213
- 'parameters',
214
- 'requestBodies',
215
- 'headers',
216
- 'securitySchemes',
217
- 'links',
218
- 'callbacks',
219
- ].forEach(function (componentType) {
193
+ Object.keys(components).forEach(function (componentType) {
220
194
  if (!Object.keys(components[componentType]).length) {
221
195
  delete components[componentType];
222
196
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oas",
3
- "version": "20.9.0",
3
+ "version": "20.10.1",
4
4
  "description": "Comprehensive tooling for working with OpenAPI definitions",
5
5
  "license": "MIT",
6
6
  "author": "ReadMe <support@readme.io> (https://readme.com)",
@@ -57,7 +57,7 @@ export interface toJSONSchemaOptions {
57
57
  isPolymorphicAllOfChild?: boolean;
58
58
 
59
59
  /**
60
- * Array of parent `default` schemas to utilzie when attempting to path together schema defaults.
60
+ * Array of parent `default` schemas to utilize when attempting to path together schema defaults.
61
61
  */
62
62
  prevDefaultSchemas?: RMOAS.SchemaObject[];
63
63
 
@@ -431,6 +431,15 @@ export default function toJSONSchema(
431
431
  } else {
432
432
  schema[polyType][idx] = toJSONSchema(item as RMOAS.SchemaObject, polyOptions);
433
433
  }
434
+
435
+ // Ensure that we don't have any invalid `required` booleans lying around.
436
+ if (
437
+ isObject(schema[polyType][idx]) &&
438
+ 'required' in (schema[polyType][idx] as SchemaObject) &&
439
+ typeof (schema[polyType][idx] as SchemaObject).required === 'boolean'
440
+ ) {
441
+ delete (schema[polyType][idx] as SchemaObject).required;
442
+ }
434
443
  });
435
444
  }
436
445
  });
@@ -674,6 +683,13 @@ export default function toJSONSchema(
674
683
  refLogger,
675
684
  transformer,
676
685
  });
686
+
687
+ // If we have a non-array `required` entry in our `items` schema then it's invalid and we
688
+ // should remove it. We only support non-array boolean `required` properties inside object
689
+ // properties.
690
+ if (isObject(schema.items) && 'required' in schema.items && !Array.isArray(schema.items.required)) {
691
+ delete schema.items.required;
692
+ }
677
693
  }
678
694
  } else if ('properties' in schema || 'additionalProperties' in schema) {
679
695
  // This is a fix to handle cases where someone may have typod `items` as `properties` on an
@@ -706,17 +722,43 @@ export default function toJSONSchema(
706
722
  });
707
723
 
708
724
  // If this property is read or write only then we should fully hide it from its parent schema.
725
+ let propShouldBeUpdated = true;
709
726
  if ((hideReadOnlyProperties || hideWriteOnlyProperties) && !Object.keys(newPropSchema).length) {
710
727
  // We should only delete this schema if it wasn't already empty though. We do this
711
728
  // because we (un)fortunately have handling in our API Explorer form system for
712
729
  // schemas that are devoid of any `type` declaration.
713
730
  if (Object.keys(schema.properties[prop]).length > 0) {
714
731
  delete schema.properties[prop];
715
- } else {
716
- schema.properties[prop] = newPropSchema;
732
+ propShouldBeUpdated = false;
717
733
  }
718
- } else {
734
+ }
735
+
736
+ if (propShouldBeUpdated) {
719
737
  schema.properties[prop] = newPropSchema;
738
+
739
+ /**
740
+ * JSON Schema does not have any support for `required: <boolean>` but because some
741
+ * of our users do this, and it does not throw OpenAPI validation errors thanks to
742
+ * some extremely loose typings around `schema` in the official JSON Schema
743
+ * definitions that the OAI offers, we're opting to support these users and upgrade
744
+ * their invalid `required` definitions into ones that our tooling can interpret.
745
+ *
746
+ * @see {@link https://github.com/OAI/OpenAPI-Specification/blob/main/schemas/v3.1/schema.json#L1114-L1121}
747
+ */
748
+ if (
749
+ isObject(newPropSchema) &&
750
+ 'required' in newPropSchema &&
751
+ typeof newPropSchema.required === 'boolean' &&
752
+ newPropSchema.required === true
753
+ ) {
754
+ if ('required' in schema && Array.isArray(schema.required)) {
755
+ schema.required.push(prop);
756
+ } else {
757
+ schema.required = [prop];
758
+ }
759
+
760
+ delete (schema.properties[prop] as SchemaObject).required;
761
+ }
720
762
  }
721
763
  }
722
764
  });
@@ -220,26 +220,9 @@ export default function getParametersAsJSONSchema(
220
220
  }
221
221
 
222
222
  const components: Partial<ComponentsObject> = {
223
- /**
224
- * Initializing an empty `components[componentType] = {}` object within the `forEach` below
225
- * is incredibly slow because each of these component types has a wide variety of shapes. So
226
- * in order to not have TS compilation times that takes literally **seconds** because of a
227
- * single line we're instead opting to prefill this object with some empty placeholders that
228
- * we'll later remove if they didn't get used.
229
- *
230
- * Obviously not ideal but I'd rather have a couple lines of boilerplate nonsense than having
231
- * to wait a noticeably frustrating amount of time for TS Intellisense to reload itself after
232
- * you save a line in any file.
233
- */
234
- examples: {},
235
- schemas: {},
236
- responses: {},
237
- parameters: {},
238
- requestBodies: {},
239
- headers: {},
240
- securitySchemes: {},
241
- links: {},
242
- callbacks: {},
223
+ ...Object.keys(api.components)
224
+ .map(componentType => ({ [componentType]: {} }))
225
+ .reduce((prev, next) => Object.assign(prev, next), {}),
243
226
  };
244
227
 
245
228
  Object.keys(api.components).forEach((componentType: keyof ComponentsObject) => {
@@ -258,17 +241,7 @@ export default function getParametersAsJSONSchema(
258
241
  });
259
242
 
260
243
  // If none of our above component type placeholders got used let's clean them up.
261
- [
262
- 'examples',
263
- 'schemas',
264
- 'responses',
265
- 'parameters',
266
- 'requestBodies',
267
- 'headers',
268
- 'securitySchemes',
269
- 'links',
270
- 'callbacks',
271
- ].forEach((componentType: keyof ComponentsObject) => {
244
+ Object.keys(components).forEach((componentType: keyof ComponentsObject) => {
272
245
  if (!Object.keys(components[componentType]).length) {
273
246
  delete components[componentType];
274
247
  }