oas 19.0.0 → 19.0.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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## <small>19.0.2 (2022-10-26)</small>
2
+
3
+ * fix: quirks with discriminators and the `transformer` JSON Schema option (#698) ([b84c57f](https://github.com/readmeio/oas/commit/b84c57f)), closes [#698](https://github.com/readmeio/oas/issues/698)
4
+
5
+
6
+
7
+ ## <small>19.0.1 (2022-10-14)</small>
8
+
9
+ * feat: supporting transforming a schema object to a primitive (#697) ([048bfc6](https://github.com/readmeio/oas/commit/048bfc6)), closes [#697](https://github.com/readmeio/oas/issues/697)
10
+
11
+
12
+
1
13
  ## 19.0.0 (2022-10-10)
2
14
 
3
15
  * docs: cleaning up some typescript options docs (#696) ([d200fef](https://github.com/readmeio/oas/commit/d200fef)), closes [#696](https://github.com/readmeio/oas/issues/696)
@@ -24,7 +24,7 @@ export declare type toJSONSchemaOptions = {
24
24
  /**
25
25
  * A function that's called anytime a (circular) `$ref` is found.
26
26
  */
27
- refLogger?: (ref: string) => void;
27
+ refLogger?: (ref: string, type: 'ref' | 'discriminator') => void;
28
28
  /**
29
29
  * A function that's called to potentially transform any discovered schema.
30
30
  */
@@ -269,7 +269,7 @@ function toJSONSchema(data, opts) {
269
269
  // If this schema contains a `$ref`, it's circular and we shouldn't try to resolve it. Just
270
270
  // return and move along.
271
271
  if (RMOAS.isRef(schema)) {
272
- refLogger(schema.$ref);
272
+ refLogger(schema.$ref, 'ref');
273
273
  return transformer({
274
274
  $ref: schema.$ref
275
275
  });
@@ -345,7 +345,7 @@ function toJSONSchema(data, opts) {
345
345
  // them to the supplied `refLogger`.
346
346
  var mapping_1 = schema.discriminator.mapping;
347
347
  Object.keys(mapping_1).forEach(function (k) {
348
- refLogger(mapping_1[k]);
348
+ refLogger(mapping_1[k], 'discriminator');
349
349
  });
350
350
  }
351
351
  }
@@ -393,7 +393,7 @@ function toJSONSchema(data, opts) {
393
393
  if ('$ref' in example) {
394
394
  // no-op because any `$ref` example here after dereferencing is circular so we should
395
395
  // ignore it
396
- refLogger(example.$ref);
396
+ refLogger(example.$ref, 'ref');
397
397
  }
398
398
  else if ('value' in example) {
399
399
  if (isPrimitive(example.value)) {
@@ -446,7 +446,7 @@ function toJSONSchema(data, opts) {
446
446
  if (!Array.isArray(schema.items) && Object.keys(schema.items).length === 1 && RMOAS.isRef(schema.items)) {
447
447
  // `items` contains a `$ref`, so since it's circular we should do a no-op here and log
448
448
  // and ignore it.
449
- refLogger(schema.items.$ref);
449
+ refLogger(schema.items.$ref, 'ref');
450
450
  }
451
451
  else if (schema.items !== true) {
452
452
  // Run through the arrays contents and clean them up.
@@ -17,6 +17,7 @@ export declare type SchemaWrapper = {
17
17
  export declare const types: Record<keyof OASDocument, string>;
18
18
  export default function getParametersAsJSONSchema(operation: Operation, api: OASDocument, opts?: {
19
19
  globalDefaults?: Record<string, unknown>;
20
+ includeDiscriminatorMappingRefs?: boolean;
20
21
  mergeIntoBodyAndMetadata?: boolean;
21
22
  retainDeprecatedProperties?: boolean;
22
23
  transformer?: (schema: SchemaObject) => SchemaObject;
@@ -61,8 +61,14 @@ exports.types = {
61
61
  function getParametersAsJSONSchema(operation, api, opts) {
62
62
  var _a;
63
63
  var hasCircularRefs = false;
64
- function refLogger() {
65
- hasCircularRefs = true;
64
+ var hasDiscriminatorMappingRefs = false;
65
+ function refLogger(ref, type) {
66
+ if (type === 'ref') {
67
+ hasCircularRefs = true;
68
+ }
69
+ else {
70
+ hasDiscriminatorMappingRefs = true;
71
+ }
66
72
  }
67
73
  function getDeprecated(schema, type) {
68
74
  // If we wish to retain deprecated properties then we shouldn't split them out into the
@@ -109,7 +115,9 @@ function getParametersAsJSONSchema(operation, api, opts) {
109
115
  });
110
116
  return {
111
117
  type: type,
112
- schema: __assign(__assign({}, deprecatedSchema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(deprecatedSchema, api) })
118
+ schema: (0, openapi_to_json_schema_1.isPrimitive)(deprecatedSchema)
119
+ ? deprecatedSchema
120
+ : __assign(__assign({}, deprecatedSchema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(deprecatedSchema, api) })
113
121
  };
114
122
  }
115
123
  /**
@@ -152,7 +160,9 @@ function getParametersAsJSONSchema(operation, api, opts) {
152
160
  return {
153
161
  type: type,
154
162
  label: exports.types[type],
155
- schema: __assign(__assign({}, cleanedSchema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(cleanedSchema, api) }),
163
+ schema: (0, openapi_to_json_schema_1.isPrimitive)(cleanedSchema)
164
+ ? cleanedSchema
165
+ : __assign(__assign({}, cleanedSchema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(cleanedSchema, api) }),
156
166
  deprecatedProps: getDeprecated(cleanedSchema, type)
157
167
  };
158
168
  }
@@ -210,16 +220,19 @@ function getParametersAsJSONSchema(operation, api, opts) {
210
220
  }
211
221
  if (current.deprecated)
212
222
  currentSchema.deprecated = current.deprecated;
213
- schema = __assign(__assign({}, (0, openapi_to_json_schema_1["default"])(currentSchema, {
223
+ var interimSchema = (0, openapi_to_json_schema_1["default"])(currentSchema, {
214
224
  currentLocation: "/".concat(current.name),
215
225
  globalDefaults: opts.globalDefaults,
216
226
  refLogger: refLogger,
217
227
  transformer: opts.transformer
218
- })), {
219
- // Note: this applies a $schema version to each field in the larger schema object.
220
- // It's not really *correct* but it's what we have to do because there's a chance that
221
- // the end user has indicated the schemas are different
222
- $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(currentSchema, api) });
228
+ });
229
+ schema = (0, openapi_to_json_schema_1.isPrimitive)(interimSchema)
230
+ ? interimSchema
231
+ : __assign(__assign({}, interimSchema), {
232
+ // Note: this applies a `$schema` version to each field in the larger schema
233
+ // object. It's not really **correct** but it's what we have to do because
234
+ // there's a chance that the end user has indicated the schemas are different.
235
+ $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(currentSchema, api) });
223
236
  }
224
237
  else if ('content' in current && typeof current.content === 'object') {
225
238
  var contentKeys = Object.keys(current.content);
@@ -256,16 +269,19 @@ function getParametersAsJSONSchema(operation, api, opts) {
256
269
  }
257
270
  if (current.deprecated)
258
271
  currentSchema.deprecated = current.deprecated;
259
- schema = __assign(__assign({}, (0, openapi_to_json_schema_1["default"])(currentSchema, {
272
+ var interimSchema = (0, openapi_to_json_schema_1["default"])(currentSchema, {
260
273
  currentLocation: "/".concat(current.name),
261
274
  globalDefaults: opts.globalDefaults,
262
275
  refLogger: refLogger,
263
276
  transformer: opts.transformer
264
- })), {
265
- // Note: this applies a $schema version to each field in the larger schema object.
266
- // It's not really *correct* but it's what we have to do because there's a chance
267
- // that the end user has indicated the schemas are different
268
- $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(currentSchema, api) });
277
+ });
278
+ schema = (0, openapi_to_json_schema_1.isPrimitive)(interimSchema)
279
+ ? interimSchema
280
+ : __assign(__assign({}, interimSchema), {
281
+ // Note: this applies a `$schema` version to each field in the larger schema
282
+ // object. It's not really **correct** but it's what we have to do because
283
+ // there's a chance that the end user has indicated the schemas are different.
284
+ $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(currentSchema, api) });
269
285
  }
270
286
  }
271
287
  }
@@ -339,9 +355,13 @@ function getParametersAsJSONSchema(operation, api, opts) {
339
355
  *
340
356
  * @todo
341
357
  */
342
- if (hasCircularRefs && components) {
343
- // Fixing typing and confused version mismatches
344
- group.schema.components = components;
358
+ if (components) {
359
+ // We should only include components if we've got circular refs or we have discriminator
360
+ // mapping refs (we want to include them).
361
+ if (hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs)) {
362
+ // Fixing typing and confused version mismatches
363
+ group.schema.components = components;
364
+ }
345
365
  }
346
366
  // Delete deprecatedProps if it's null on the schema.
347
367
  if (!group.deprecatedProps)
@@ -10,11 +10,7 @@ import type { OASDocument, SchemaObject } from 'rmoas.types';
10
10
  * @param statusCode The response status code to generate a schema for.
11
11
  */
12
12
  export default function getResponseAsJSONSchema(operation: Operation, api: OASDocument, statusCode: string | number, opts?: {
13
- /**
14
- * With a transformer you can transform any data within a given schema, like say if you want to
15
- * rewrite a potentially unsafe `title` that might be eventually used as a JS variable name,
16
- * just make sure to return your transformed schema.
17
- */
13
+ includeDiscriminatorMappingRefs?: boolean;
18
14
  transformer?: (schema: SchemaObject) => SchemaObject;
19
15
  }): {
20
16
  type: string | string[];
@@ -97,8 +97,14 @@ function getResponseAsJSONSchema(operation, api, statusCode, opts) {
97
97
  return null;
98
98
  }
99
99
  var hasCircularRefs = false;
100
- function refLogger() {
101
- hasCircularRefs = true;
100
+ var hasDiscriminatorMappingRefs = false;
101
+ function refLogger(ref, type) {
102
+ if (type === 'ref') {
103
+ hasCircularRefs = true;
104
+ }
105
+ else {
106
+ hasDiscriminatorMappingRefs = true;
107
+ }
102
108
  }
103
109
  /**
104
110
  * @param content An array of `MediaTypeObject`'s to retrieve a preferred schema out of. We
@@ -139,7 +145,9 @@ function getResponseAsJSONSchema(operation, api, statusCode, opts) {
139
145
  // able to render so instead of generating a JSON Schema with an `undefined` type we should
140
146
  // default to `string` so there's at least *something* the end-user can interact with.
141
147
  type: foundSchema.type || 'string',
142
- schema: __assign(__assign({}, schema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(schema, api) }),
148
+ schema: (0, openapi_to_json_schema_1.isPrimitive)(schema)
149
+ ? schema
150
+ : __assign(__assign({}, schema), { $schema: (0, openapi_to_json_schema_1.getSchemaVersionString)(schema, api) }),
143
151
  label: 'Response body'
144
152
  };
145
153
  if (response.description && schemaWrapper.schema) {
@@ -152,8 +160,12 @@ function getResponseAsJSONSchema(operation, api, statusCode, opts) {
152
160
  *
153
161
  * @todo
154
162
  */
155
- if (hasCircularRefs && api.components && schemaWrapper.schema) {
156
- schemaWrapper.schema.components = api.components;
163
+ if (api.components && schemaWrapper.schema) {
164
+ // We should only include components if we've got circular refs or we have discriminator
165
+ // mapping refs (we want to include them).
166
+ if (hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs)) {
167
+ schemaWrapper.schema.components = api.components;
168
+ }
157
169
  }
158
170
  jsonSchema.push(schemaWrapper);
159
171
  }
@@ -131,6 +131,11 @@ export default class Operation {
131
131
  * Contains an object of user defined schema defaults.
132
132
  */
133
133
  globalDefaults?: Record<string, unknown>;
134
+ /**
135
+ * If you wish to include discriminator mapping `$ref` components alongside your
136
+ * `discriminator` in schemas. Defaults to `true`.
137
+ */
138
+ includeDiscriminatorMappingRefs?: boolean;
134
139
  /**
135
140
  * If you want the output to be two objects: body (contains `body` and `formData` JSON
136
141
  * Schema) and metadata (contains `path`, `query`, `cookie`, and `header`).
@@ -154,6 +159,11 @@ export default class Operation {
154
159
  * @param statusCode Status code to pull a JSON Schema response for.
155
160
  */
156
161
  getResponseAsJSONSchema(statusCode: string | number, opts?: {
162
+ /**
163
+ * If you wish to include discriminator mapping `$ref` components alongside your
164
+ * `discriminator` in schemas. Defaults to `true`.
165
+ */
166
+ includeDiscriminatorMappingRefs?: boolean;
157
167
  /**
158
168
  * With a transformer you can transform any data within a given schema, like say if you want
159
169
  * to rewrite a potentially unsafe `title` that might be eventually used as a JS variable
package/dist/operation.js CHANGED
@@ -414,10 +414,7 @@ var Operation = /** @class */ (function () {
414
414
  */
415
415
  Operation.prototype.getParametersAsJSONSchema = function (opts) {
416
416
  if (opts === void 0) { opts = {}; }
417
- if (!opts.transformer) {
418
- opts.transformer = function (s) { return s; };
419
- }
420
- return (0, get_parameters_as_json_schema_1["default"])(this, this.api, opts);
417
+ return (0, get_parameters_as_json_schema_1["default"])(this, this.api, __assign({ includeDiscriminatorMappingRefs: true, transformer: function (s) { return s; } }, opts));
421
418
  };
422
419
  /**
423
420
  * Get a single response for this status code, formatted as JSON schema.
@@ -425,10 +422,8 @@ var Operation = /** @class */ (function () {
425
422
  * @param statusCode Status code to pull a JSON Schema response for.
426
423
  */
427
424
  Operation.prototype.getResponseAsJSONSchema = function (statusCode, opts) {
428
- if (opts === void 0) { opts = {
429
- transformer: function (s) { return s; }
430
- }; }
431
- return (0, get_response_as_json_schema_1["default"])(this, this.api, statusCode, opts);
425
+ if (opts === void 0) { opts = {}; }
426
+ return (0, get_response_as_json_schema_1["default"])(this, this.api, statusCode, __assign({ includeDiscriminatorMappingRefs: true, transformer: function (s) { return s; } }, opts));
432
427
  };
433
428
  /**
434
429
  * Get an array of all valid response status codes for this operation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oas",
3
- "version": "19.0.0",
3
+ "version": "19.0.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)",
@@ -56,7 +56,7 @@ export type toJSONSchemaOptions = {
56
56
  /**
57
57
  * A function that's called anytime a (circular) `$ref` is found.
58
58
  */
59
- refLogger?: (ref: string) => void;
59
+ refLogger?: (ref: string, type: 'ref' | 'discriminator') => void;
60
60
 
61
61
  /**
62
62
  * A function that's called to potentially transform any discovered schema.
@@ -295,7 +295,7 @@ export default function toJSONSchema(
295
295
  // If this schema contains a `$ref`, it's circular and we shouldn't try to resolve it. Just
296
296
  // return and move along.
297
297
  if (RMOAS.isRef(schema)) {
298
- refLogger(schema.$ref);
298
+ refLogger(schema.$ref, 'ref');
299
299
 
300
300
  return transformer({
301
301
  $ref: schema.$ref,
@@ -381,7 +381,7 @@ export default function toJSONSchema(
381
381
  // them to the supplied `refLogger`.
382
382
  const mapping = schema.discriminator.mapping;
383
383
  Object.keys(mapping).forEach(k => {
384
- refLogger(mapping[k]);
384
+ refLogger(mapping[k], 'discriminator');
385
385
  });
386
386
  }
387
387
  }
@@ -427,7 +427,7 @@ export default function toJSONSchema(
427
427
  if ('$ref' in example) {
428
428
  // no-op because any `$ref` example here after dereferencing is circular so we should
429
429
  // ignore it
430
- refLogger(example.$ref);
430
+ refLogger(example.$ref, 'ref');
431
431
  } else if ('value' in example) {
432
432
  if (isPrimitive(example.value)) {
433
433
  examples.push(example.value);
@@ -480,7 +480,7 @@ export default function toJSONSchema(
480
480
  if (!Array.isArray(schema.items) && Object.keys(schema.items).length === 1 && RMOAS.isRef(schema.items)) {
481
481
  // `items` contains a `$ref`, so since it's circular we should do a no-op here and log
482
482
  // and ignore it.
483
- refLogger(schema.items.$ref);
483
+ refLogger(schema.items.$ref, 'ref');
484
484
  } else if (schema.items !== true) {
485
485
  // Run through the arrays contents and clean them up.
486
486
  schema.items = toJSONSchema(schema.items as RMOAS.SchemaObject, {
@@ -4,7 +4,7 @@ import type { OpenAPIV3_1 } from 'openapi-types';
4
4
 
5
5
  import cloneObject from '../lib/clone-object';
6
6
  import matchesMimetype from '../lib/matches-mimetype';
7
- import toJSONSchema, { getSchemaVersionString } from '../lib/openapi-to-json-schema';
7
+ import toJSONSchema, { isPrimitive, getSchemaVersionString } from '../lib/openapi-to-json-schema';
8
8
 
9
9
  const isJSON = matchesMimetype.json;
10
10
 
@@ -38,15 +38,21 @@ export default function getParametersAsJSONSchema(
38
38
  api: OASDocument,
39
39
  opts?: {
40
40
  globalDefaults?: Record<string, unknown>;
41
+ includeDiscriminatorMappingRefs?: boolean;
41
42
  mergeIntoBodyAndMetadata?: boolean;
42
43
  retainDeprecatedProperties?: boolean;
43
44
  transformer?: (schema: SchemaObject) => SchemaObject;
44
45
  }
45
46
  ) {
46
47
  let hasCircularRefs = false;
48
+ let hasDiscriminatorMappingRefs = false;
47
49
 
48
- function refLogger() {
49
- hasCircularRefs = true;
50
+ function refLogger(ref: string, type: 'ref' | 'discriminator') {
51
+ if (type === 'ref') {
52
+ hasCircularRefs = true;
53
+ } else {
54
+ hasDiscriminatorMappingRefs = true;
55
+ }
50
56
  }
51
57
 
52
58
  function getDeprecated(schema: SchemaObject, type: string) {
@@ -102,10 +108,12 @@ export default function getParametersAsJSONSchema(
102
108
 
103
109
  return {
104
110
  type,
105
- schema: {
106
- ...deprecatedSchema,
107
- $schema: getSchemaVersionString(deprecatedSchema, api),
108
- },
111
+ schema: isPrimitive(deprecatedSchema)
112
+ ? deprecatedSchema
113
+ : {
114
+ ...deprecatedSchema,
115
+ $schema: getSchemaVersionString(deprecatedSchema, api),
116
+ },
109
117
  };
110
118
  }
111
119
 
@@ -153,10 +161,12 @@ export default function getParametersAsJSONSchema(
153
161
  return {
154
162
  type,
155
163
  label: types[type],
156
- schema: {
157
- ...cleanedSchema,
158
- $schema: getSchemaVersionString(cleanedSchema, api),
159
- },
164
+ schema: isPrimitive(cleanedSchema)
165
+ ? cleanedSchema
166
+ : {
167
+ ...cleanedSchema,
168
+ $schema: getSchemaVersionString(cleanedSchema, api),
169
+ },
160
170
  deprecatedProps: getDeprecated(cleanedSchema, type),
161
171
  };
162
172
  }
@@ -224,19 +234,23 @@ export default function getParametersAsJSONSchema(
224
234
 
225
235
  if (current.deprecated) currentSchema.deprecated = current.deprecated;
226
236
 
227
- schema = {
228
- ...toJSONSchema(currentSchema, {
229
- currentLocation: `/${current.name}`,
230
- globalDefaults: opts.globalDefaults,
231
- refLogger,
232
- transformer: opts.transformer,
233
- }),
234
-
235
- // Note: this applies a $schema version to each field in the larger schema object.
236
- // It's not really *correct* but it's what we have to do because there's a chance that
237
- // the end user has indicated the schemas are different
238
- $schema: getSchemaVersionString(currentSchema, api),
239
- };
237
+ const interimSchema = toJSONSchema(currentSchema, {
238
+ currentLocation: `/${current.name}`,
239
+ globalDefaults: opts.globalDefaults,
240
+ refLogger,
241
+ transformer: opts.transformer,
242
+ });
243
+
244
+ schema = isPrimitive(interimSchema)
245
+ ? interimSchema
246
+ : {
247
+ ...interimSchema,
248
+
249
+ // Note: this applies a `$schema` version to each field in the larger schema
250
+ // object. It's not really **correct** but it's what we have to do because
251
+ // there's a chance that the end user has indicated the schemas are different.
252
+ $schema: getSchemaVersionString(currentSchema, api),
253
+ };
240
254
  } else if ('content' in current && typeof current.content === 'object') {
241
255
  const contentKeys = Object.keys(current.content);
242
256
  if (contentKeys.length) {
@@ -272,19 +286,23 @@ export default function getParametersAsJSONSchema(
272
286
 
273
287
  if (current.deprecated) currentSchema.deprecated = current.deprecated;
274
288
 
275
- schema = {
276
- ...toJSONSchema(currentSchema, {
277
- currentLocation: `/${current.name}`,
278
- globalDefaults: opts.globalDefaults,
279
- refLogger,
280
- transformer: opts.transformer,
281
- }),
282
-
283
- // Note: this applies a $schema version to each field in the larger schema object.
284
- // It's not really *correct* but it's what we have to do because there's a chance
285
- // that the end user has indicated the schemas are different
286
- $schema: getSchemaVersionString(currentSchema, api),
287
- };
289
+ const interimSchema = toJSONSchema(currentSchema, {
290
+ currentLocation: `/${current.name}`,
291
+ globalDefaults: opts.globalDefaults,
292
+ refLogger,
293
+ transformer: opts.transformer,
294
+ });
295
+
296
+ schema = isPrimitive(interimSchema)
297
+ ? interimSchema
298
+ : {
299
+ ...interimSchema,
300
+
301
+ // Note: this applies a `$schema` version to each field in the larger schema
302
+ // object. It's not really **correct** but it's what we have to do because
303
+ // there's a chance that the end user has indicated the schemas are different.
304
+ $schema: getSchemaVersionString(currentSchema, api),
305
+ };
288
306
  }
289
307
  }
290
308
  }
@@ -369,9 +387,13 @@ export default function getParametersAsJSONSchema(
369
387
  *
370
388
  * @todo
371
389
  */
372
- if (hasCircularRefs && components) {
373
- // Fixing typing and confused version mismatches
374
- (group.schema.components as ComponentsObject) = components;
390
+ if (components) {
391
+ // We should only include components if we've got circular refs or we have discriminator
392
+ // mapping refs (we want to include them).
393
+ if (hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs)) {
394
+ // Fixing typing and confused version mismatches
395
+ (group.schema.components as ComponentsObject) = components;
396
+ }
375
397
  }
376
398
 
377
399
  // Delete deprecatedProps if it's null on the schema.
@@ -10,7 +10,7 @@ import type {
10
10
 
11
11
  import cloneObject from '../lib/clone-object';
12
12
  import matches from '../lib/matches-mimetype';
13
- import toJSONSchema, { getSchemaVersionString } from '../lib/openapi-to-json-schema';
13
+ import toJSONSchema, { isPrimitive, getSchemaVersionString } from '../lib/openapi-to-json-schema';
14
14
 
15
15
  const isJSON = matches.json;
16
16
 
@@ -91,11 +91,7 @@ export default function getResponseAsJSONSchema(
91
91
  api: OASDocument,
92
92
  statusCode: string | number,
93
93
  opts?: {
94
- /**
95
- * With a transformer you can transform any data within a given schema, like say if you want to
96
- * rewrite a potentially unsafe `title` that might be eventually used as a JS variable name,
97
- * just make sure to return your transformed schema.
98
- */
94
+ includeDiscriminatorMappingRefs?: boolean;
99
95
  transformer?: (schema: SchemaObject) => SchemaObject;
100
96
  }
101
97
  ) {
@@ -107,9 +103,14 @@ export default function getResponseAsJSONSchema(
107
103
  }
108
104
 
109
105
  let hasCircularRefs = false;
106
+ let hasDiscriminatorMappingRefs = false;
110
107
 
111
- function refLogger() {
112
- hasCircularRefs = true;
108
+ function refLogger(ref: string, type: 'ref' | 'discriminator') {
109
+ if (type === 'ref') {
110
+ hasCircularRefs = true;
111
+ } else {
112
+ hasDiscriminatorMappingRefs = true;
113
+ }
113
114
  }
114
115
 
115
116
  /**
@@ -160,10 +161,12 @@ export default function getResponseAsJSONSchema(
160
161
  // able to render so instead of generating a JSON Schema with an `undefined` type we should
161
162
  // default to `string` so there's at least *something* the end-user can interact with.
162
163
  type: foundSchema.type || 'string',
163
- schema: {
164
- ...schema,
165
- $schema: getSchemaVersionString(schema, api),
166
- },
164
+ schema: isPrimitive(schema)
165
+ ? schema
166
+ : {
167
+ ...schema,
168
+ $schema: getSchemaVersionString(schema, api),
169
+ },
167
170
  label: 'Response body',
168
171
  };
169
172
 
@@ -178,8 +181,12 @@ export default function getResponseAsJSONSchema(
178
181
  *
179
182
  * @todo
180
183
  */
181
- if (hasCircularRefs && api.components && schemaWrapper.schema) {
182
- ((schemaWrapper.schema as SchemaObject).components as ComponentsObject) = api.components as ComponentsObject;
184
+ if (api.components && schemaWrapper.schema) {
185
+ // We should only include components if we've got circular refs or we have discriminator
186
+ // mapping refs (we want to include them).
187
+ if (hasCircularRefs || (hasDiscriminatorMappingRefs && opts.includeDiscriminatorMappingRefs)) {
188
+ ((schemaWrapper.schema as SchemaObject).components as ComponentsObject) = api.components as ComponentsObject;
189
+ }
183
190
  }
184
191
 
185
192
  jsonSchema.push(schemaWrapper);
package/src/operation.ts CHANGED
@@ -465,6 +465,12 @@ export default class Operation {
465
465
  */
466
466
  globalDefaults?: Record<string, unknown>;
467
467
 
468
+ /**
469
+ * If you wish to include discriminator mapping `$ref` components alongside your
470
+ * `discriminator` in schemas. Defaults to `true`.
471
+ */
472
+ includeDiscriminatorMappingRefs?: boolean;
473
+
468
474
  /**
469
475
  * If you want the output to be two objects: body (contains `body` and `formData` JSON
470
476
  * Schema) and metadata (contains `path`, `query`, `cookie`, and `header`).
@@ -485,11 +491,11 @@ export default class Operation {
485
491
  transformer?: (schema: RMOAS.SchemaObject) => RMOAS.SchemaObject;
486
492
  } = {}
487
493
  ) {
488
- if (!opts.transformer) {
489
- opts.transformer = (s: RMOAS.SchemaObject) => s;
490
- }
491
-
492
- return getParametersAsJSONSchema(this, this.api, opts);
494
+ return getParametersAsJSONSchema(this, this.api, {
495
+ includeDiscriminatorMappingRefs: true,
496
+ transformer: (s: RMOAS.SchemaObject) => s,
497
+ ...opts,
498
+ });
493
499
  }
494
500
 
495
501
  /**
@@ -500,17 +506,25 @@ export default class Operation {
500
506
  getResponseAsJSONSchema(
501
507
  statusCode: string | number,
502
508
  opts: {
509
+ /**
510
+ * If you wish to include discriminator mapping `$ref` components alongside your
511
+ * `discriminator` in schemas. Defaults to `true`.
512
+ */
513
+ includeDiscriminatorMappingRefs?: boolean;
514
+
503
515
  /**
504
516
  * With a transformer you can transform any data within a given schema, like say if you want
505
517
  * to rewrite a potentially unsafe `title` that might be eventually used as a JS variable
506
518
  * name, just make sure to return your transformed schema.
507
519
  */
508
520
  transformer?: (schema: RMOAS.SchemaObject) => RMOAS.SchemaObject;
509
- } = {
510
- transformer: (s: RMOAS.SchemaObject) => s,
511
- }
521
+ } = {}
512
522
  ) {
513
- return getResponseAsJSONSchema(this, this.api, statusCode, opts);
523
+ return getResponseAsJSONSchema(this, this.api, statusCode, {
524
+ includeDiscriminatorMappingRefs: true,
525
+ transformer: (s: RMOAS.SchemaObject) => s,
526
+ ...opts,
527
+ });
514
528
  }
515
529
 
516
530
  /**