oas 20.8.9 → 20.9.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.
- package/dist/lib/helpers.d.ts +1 -0
- package/dist/lib/helpers.js +5 -1
- package/dist/lib/openapi-to-json-schema.d.ts +6 -4
- package/dist/lib/openapi-to-json-schema.js +73 -42
- package/dist/operation/get-parameters-as-json-schema.js +5 -5
- package/dist/samples/utils.js +2 -4
- package/package.json +5 -5
- package/src/lib/helpers.ts +4 -0
- package/src/lib/openapi-to-json-schema.ts +91 -49
- package/src/operation/get-parameters-as-json-schema.ts +6 -5
- package/src/samples/utils.ts +1 -3
- package/tsconfig.json +1 -1
package/dist/lib/helpers.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { SchemaObject } from 'rmoas.types';
|
|
2
2
|
export declare function hasSchemaType(schema: SchemaObject, discriminator: 'array' | 'object'): boolean;
|
|
3
|
+
export declare function isObject(val: unknown): boolean;
|
|
3
4
|
export declare function isPrimitive(val: unknown): boolean;
|
package/dist/lib/helpers.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isPrimitive = exports.hasSchemaType = void 0;
|
|
3
|
+
exports.isPrimitive = exports.isObject = exports.hasSchemaType = void 0;
|
|
4
4
|
function hasSchemaType(schema, discriminator) {
|
|
5
5
|
if (Array.isArray(schema.type)) {
|
|
6
6
|
return schema.type.includes(discriminator);
|
|
@@ -8,6 +8,10 @@ function hasSchemaType(schema, discriminator) {
|
|
|
8
8
|
return schema.type === discriminator;
|
|
9
9
|
}
|
|
10
10
|
exports.hasSchemaType = hasSchemaType;
|
|
11
|
+
function isObject(val) {
|
|
12
|
+
return typeof val === 'object' && val !== null && !Array.isArray(val);
|
|
13
|
+
}
|
|
14
|
+
exports.isObject = isObject;
|
|
11
15
|
function isPrimitive(val) {
|
|
12
16
|
return typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean';
|
|
13
17
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as RMOAS from '../rmoas.types';
|
|
2
|
-
type PrevSchemasType = RMOAS.SchemaObject[];
|
|
3
2
|
export interface toJSONSchemaOptions {
|
|
4
3
|
/**
|
|
5
4
|
* Whether or not to extend descriptions with a list of any present enums.
|
|
@@ -26,9 +25,13 @@ export interface toJSONSchemaOptions {
|
|
|
26
25
|
*/
|
|
27
26
|
isPolymorphicAllOfChild?: boolean;
|
|
28
27
|
/**
|
|
29
|
-
* Array of parent schemas to
|
|
28
|
+
* Array of parent `default` schemas to utilzie when attempting to path together schema defaults.
|
|
30
29
|
*/
|
|
31
|
-
|
|
30
|
+
prevDefaultSchemas?: RMOAS.SchemaObject[];
|
|
31
|
+
/**
|
|
32
|
+
* Array of parent `example` schemas to utilize when attempting to path together schema examples.
|
|
33
|
+
*/
|
|
34
|
+
prevExampleSchemas?: RMOAS.SchemaObject[];
|
|
32
35
|
/**
|
|
33
36
|
* A function that's called anytime a (circular) `$ref` is found.
|
|
34
37
|
*/
|
|
@@ -78,4 +81,3 @@ export declare function getSchemaVersionString(schema: RMOAS.SchemaObject, api:
|
|
|
78
81
|
* @param data OpenAPI Schema Object to convert to pure JSON Schema.
|
|
79
82
|
*/
|
|
80
83
|
export default function toJSONSchema(data: RMOAS.SchemaObject | boolean, opts?: toJSONSchemaOptions): RMOAS.SchemaObject;
|
|
81
|
-
export {};
|
|
@@ -141,8 +141,8 @@ function isRequestBodySchema(schema) {
|
|
|
141
141
|
return 'content' in schema;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
* Given a JSON pointer and an array of
|
|
145
|
-
* JSON pointer, or part of it, within the array.
|
|
144
|
+
* Given a JSON pointer, a type of property to look for, and an array of schemas do a reverse
|
|
145
|
+
* search through them until we find the JSON pointer, or part of it, within the array.
|
|
146
146
|
*
|
|
147
147
|
* This function will allow you to take a pointer like `/tags/name` and return back `buster` from
|
|
148
148
|
* the following array:
|
|
@@ -170,12 +170,13 @@ function isRequestBodySchema(schema) {
|
|
|
170
170
|
* it shouldn't raise immediate cause for alarm.
|
|
171
171
|
*
|
|
172
172
|
* @see {@link https://tools.ietf.org/html/rfc6901}
|
|
173
|
+
* @param property Specific type of schema property to look for a value for.
|
|
173
174
|
* @param pointer JSON pointer to search for an example for.
|
|
174
|
-
* @param
|
|
175
|
+
* @param schemas Array of previous schemas we've found relating to this pointer.
|
|
175
176
|
*/
|
|
176
|
-
function
|
|
177
|
-
if (
|
|
178
|
-
if (!
|
|
177
|
+
function searchForValueByPropAndPointer(property, pointer, schemas) {
|
|
178
|
+
if (schemas === void 0) { schemas = []; }
|
|
179
|
+
if (!schemas.length || !pointer.length) {
|
|
179
180
|
return undefined;
|
|
180
181
|
}
|
|
181
182
|
var locSplit = pointer.split('/').filter(Boolean).reverse();
|
|
@@ -185,38 +186,43 @@ function searchForExampleByPointer(pointer, examples) {
|
|
|
185
186
|
point = "/".concat(locSplit[i]).concat(point);
|
|
186
187
|
pointers.push(point);
|
|
187
188
|
}
|
|
188
|
-
var
|
|
189
|
-
var rev = __spreadArray([],
|
|
189
|
+
var foundValue;
|
|
190
|
+
var rev = __spreadArray([], schemas, true).reverse();
|
|
190
191
|
for (var i = 0; i < pointers.length; i += 1) {
|
|
191
192
|
for (var ii = 0; ii < rev.length; ii += 1) {
|
|
192
193
|
var schema = rev[ii];
|
|
193
|
-
if ('example'
|
|
194
|
-
|
|
194
|
+
if (property === 'example') {
|
|
195
|
+
if ('example' in schema) {
|
|
196
|
+
schema = schema.example;
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
if (!Array.isArray(schema.examples) || !schema.examples.length) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
// Prevent us from crashing if `examples` is a completely empty object.
|
|
203
|
+
schema = __spreadArray([], schema.examples, true).shift();
|
|
204
|
+
}
|
|
195
205
|
}
|
|
196
206
|
else {
|
|
197
|
-
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
// Prevent us from crashing if `examples` is a completely empty object.
|
|
201
|
-
schema = __spreadArray([], schema.examples, true).shift();
|
|
207
|
+
schema = schema.default;
|
|
202
208
|
}
|
|
203
209
|
try {
|
|
204
|
-
|
|
210
|
+
foundValue = jsonpointer_1.default.get(schema, pointers[i]);
|
|
205
211
|
}
|
|
206
212
|
catch (err) {
|
|
207
213
|
// If the schema we're looking at is `{obj: null}` and our pointer is `/obj/propertyName`
|
|
208
214
|
// `jsonpointer` will throw an error. If that happens, we should silently catch and toss it
|
|
209
215
|
// and return no example.
|
|
210
216
|
}
|
|
211
|
-
if (
|
|
217
|
+
if (foundValue !== undefined) {
|
|
212
218
|
break;
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
|
-
if (
|
|
221
|
+
if (foundValue !== undefined) {
|
|
216
222
|
break;
|
|
217
223
|
}
|
|
218
224
|
}
|
|
219
|
-
return
|
|
225
|
+
return foundValue;
|
|
220
226
|
}
|
|
221
227
|
/**
|
|
222
228
|
* Given an OpenAPI-flavored JSON Schema, make an effort to modify it so it's shaped more towards
|
|
@@ -258,7 +264,7 @@ function toJSONSchema(data, opts) {
|
|
|
258
264
|
if (opts === void 0) { opts = {}; }
|
|
259
265
|
var schema = data === true ? {} : __assign({}, data);
|
|
260
266
|
var schemaAdditionalProperties = RMOAS.isSchema(schema) ? schema.additionalProperties : null;
|
|
261
|
-
var _a = __assign({ addEnumsToDescriptions: false, currentLocation: '', globalDefaults: {}, hideReadOnlyProperties: false, hideWriteOnlyProperties: false, isPolymorphicAllOfChild: false,
|
|
267
|
+
var _a = __assign({ addEnumsToDescriptions: false, currentLocation: '', globalDefaults: {}, hideReadOnlyProperties: false, hideWriteOnlyProperties: false, isPolymorphicAllOfChild: false, prevDefaultSchemas: [], prevExampleSchemas: [], refLogger: function () { return true; }, transformer: function (s) { return s; } }, opts), addEnumsToDescriptions = _a.addEnumsToDescriptions, currentLocation = _a.currentLocation, globalDefaults = _a.globalDefaults, hideReadOnlyProperties = _a.hideReadOnlyProperties, hideWriteOnlyProperties = _a.hideWriteOnlyProperties, isPolymorphicAllOfChild = _a.isPolymorphicAllOfChild, prevDefaultSchemas = _a.prevDefaultSchemas, prevExampleSchemas = _a.prevExampleSchemas, refLogger = _a.refLogger, transformer = _a.transformer;
|
|
262
268
|
// If this schema contains a `$ref`, it's circular and we shouldn't try to resolve it. Just
|
|
263
269
|
// return and move along.
|
|
264
270
|
if (RMOAS.isRef(schema)) {
|
|
@@ -337,7 +343,8 @@ function toJSONSchema(data, opts) {
|
|
|
337
343
|
hideReadOnlyProperties: hideReadOnlyProperties,
|
|
338
344
|
hideWriteOnlyProperties: hideWriteOnlyProperties,
|
|
339
345
|
isPolymorphicAllOfChild: false,
|
|
340
|
-
|
|
346
|
+
prevDefaultSchemas: prevDefaultSchemas,
|
|
347
|
+
prevExampleSchemas: prevExampleSchemas,
|
|
341
348
|
refLogger: refLogger,
|
|
342
349
|
transformer: transformer,
|
|
343
350
|
};
|
|
@@ -496,6 +503,9 @@ function toJSONSchema(data, opts) {
|
|
|
496
503
|
}
|
|
497
504
|
}
|
|
498
505
|
if (RMOAS.isSchema(schema, isPolymorphicAllOfChild)) {
|
|
506
|
+
if ('default' in schema && (0, helpers_1.isObject)(schema.default)) {
|
|
507
|
+
prevDefaultSchemas.push({ default: schema.default });
|
|
508
|
+
}
|
|
499
509
|
// JSON Schema doesn't support OpenAPI-style examples so we need to reshape them a bit.
|
|
500
510
|
if ('example' in schema) {
|
|
501
511
|
// Only bother adding primitive examples.
|
|
@@ -509,7 +519,7 @@ function toJSONSchema(data, opts) {
|
|
|
509
519
|
}
|
|
510
520
|
}
|
|
511
521
|
else {
|
|
512
|
-
|
|
522
|
+
prevExampleSchemas.push({ example: schema.example });
|
|
513
523
|
}
|
|
514
524
|
delete schema.example;
|
|
515
525
|
}
|
|
@@ -535,9 +545,9 @@ function toJSONSchema(data, opts) {
|
|
|
535
545
|
}
|
|
536
546
|
else {
|
|
537
547
|
// If this example is neither a primitive or an array we should dump it into the
|
|
538
|
-
// `
|
|
539
|
-
// downstream.
|
|
540
|
-
|
|
548
|
+
// `prevExampleSchemas` array because we might be able to extract an example from it
|
|
549
|
+
// further downstream.
|
|
550
|
+
prevExampleSchemas.push({
|
|
541
551
|
example: example.value,
|
|
542
552
|
});
|
|
543
553
|
}
|
|
@@ -561,7 +571,7 @@ function toJSONSchema(data, opts) {
|
|
|
561
571
|
// find one. But as we're only looking for primitive example, only try to search for one if
|
|
562
572
|
// we're dealing with a primitive schema.
|
|
563
573
|
if (!(0, helpers_1.hasSchemaType)(schema, 'array') && !(0, helpers_1.hasSchemaType)(schema, 'object') && !schema.examples) {
|
|
564
|
-
var foundExample =
|
|
574
|
+
var foundExample = searchForValueByPropAndPointer('example', currentLocation, prevExampleSchemas);
|
|
565
575
|
if (foundExample) {
|
|
566
576
|
// We can only really deal with primitives, so only promote those as the found example if
|
|
567
577
|
// it is.
|
|
@@ -585,7 +595,7 @@ function toJSONSchema(data, opts) {
|
|
|
585
595
|
globalDefaults: globalDefaults,
|
|
586
596
|
hideReadOnlyProperties: hideReadOnlyProperties,
|
|
587
597
|
hideWriteOnlyProperties: hideWriteOnlyProperties,
|
|
588
|
-
|
|
598
|
+
prevExampleSchemas: prevExampleSchemas,
|
|
589
599
|
refLogger: refLogger,
|
|
590
600
|
transformer: transformer,
|
|
591
601
|
});
|
|
@@ -615,7 +625,8 @@ function toJSONSchema(data, opts) {
|
|
|
615
625
|
globalDefaults: globalDefaults,
|
|
616
626
|
hideReadOnlyProperties: hideReadOnlyProperties,
|
|
617
627
|
hideWriteOnlyProperties: hideWriteOnlyProperties,
|
|
618
|
-
|
|
628
|
+
prevDefaultSchemas: prevDefaultSchemas,
|
|
629
|
+
prevExampleSchemas: prevExampleSchemas,
|
|
619
630
|
refLogger: refLogger,
|
|
620
631
|
transformer: transformer,
|
|
621
632
|
});
|
|
@@ -661,7 +672,8 @@ function toJSONSchema(data, opts) {
|
|
|
661
672
|
globalDefaults: globalDefaults,
|
|
662
673
|
hideReadOnlyProperties: hideReadOnlyProperties,
|
|
663
674
|
hideWriteOnlyProperties: hideWriteOnlyProperties,
|
|
664
|
-
|
|
675
|
+
prevDefaultSchemas: prevDefaultSchemas,
|
|
676
|
+
prevExampleSchemas: prevExampleSchemas,
|
|
665
677
|
refLogger: refLogger,
|
|
666
678
|
transformer: transformer,
|
|
667
679
|
});
|
|
@@ -713,21 +725,40 @@ function toJSONSchema(data, opts) {
|
|
|
713
725
|
}
|
|
714
726
|
// Only add a default value if we actually have one.
|
|
715
727
|
if ('default' in schema && typeof schema.default !== 'undefined') {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
? "".concat(schema.description.replace(/\n$/, ''), "\n\nDefault: `").concat(schema.default, "`")
|
|
721
|
-
: "Default: ".concat(schema.default);
|
|
722
|
-
}
|
|
723
|
-
if (('allowEmptyValue' in schema && schema.allowEmptyValue && schema.default === '') || schema.default !== '') {
|
|
724
|
-
// If we have `allowEmptyValue` present, and the default is actually an empty string, let it
|
|
725
|
-
// through as it's allowed.
|
|
728
|
+
if ((0, helpers_1.hasSchemaType)(schema, 'object')) {
|
|
729
|
+
// Defaults for `object` and types have been dereferenced into their children schemas already
|
|
730
|
+
// above so we don't need to preserve this default anymore.
|
|
731
|
+
delete schema.default;
|
|
726
732
|
}
|
|
727
733
|
else {
|
|
728
|
-
// If
|
|
729
|
-
//
|
|
730
|
-
|
|
734
|
+
// If it's an enum and not the response schema, add the default to the description.
|
|
735
|
+
// If there's an existing description, trim trailing new lines so it doesn't look ugly.
|
|
736
|
+
if ('enum' in schema && !addEnumsToDescriptions) {
|
|
737
|
+
schema.description = schema.description
|
|
738
|
+
? "".concat(schema.description.replace(/\n$/, ''), "\n\nDefault: `").concat(schema.default, "`")
|
|
739
|
+
: "Default: ".concat(schema.default);
|
|
740
|
+
}
|
|
741
|
+
if (('allowEmptyValue' in schema && schema.allowEmptyValue && schema.default === '') || schema.default !== '') {
|
|
742
|
+
// If we have `allowEmptyValue` present, and the default is actually an empty string, let it
|
|
743
|
+
// through as it's allowed.
|
|
744
|
+
}
|
|
745
|
+
else {
|
|
746
|
+
// If the default is empty and we don't want to allowEmptyValue, we need to remove the
|
|
747
|
+
// default.
|
|
748
|
+
delete schema.default;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
else if (prevDefaultSchemas.length) {
|
|
753
|
+
var foundDefault = searchForValueByPropAndPointer('default', currentLocation, prevDefaultSchemas);
|
|
754
|
+
// We shouldn't ever set an object default out of the parent lineage tree defaults because
|
|
755
|
+
// the contents of that object will be set on the schema that they're a part of. Setting
|
|
756
|
+
// that object as well would result us in duplicating the defaults for that schema in two
|
|
757
|
+
// places.
|
|
758
|
+
if ((0, helpers_1.isPrimitive)(foundDefault) ||
|
|
759
|
+
foundDefault === null ||
|
|
760
|
+
(Array.isArray(foundDefault) && (0, helpers_1.hasSchemaType)(schema, 'array'))) {
|
|
761
|
+
schema.default = foundDefault;
|
|
731
762
|
}
|
|
732
763
|
}
|
|
733
764
|
if (RMOAS.isSchema(schema, isPolymorphicAllOfChild) && 'enum' in schema && Array.isArray(schema.enum)) {
|
|
@@ -99,7 +99,7 @@ function getParametersAsJSONSchema(operation, api, opts) {
|
|
|
99
99
|
globalDefaults: opts.globalDefaults,
|
|
100
100
|
hideReadOnlyProperties: opts.hideReadOnlyProperties,
|
|
101
101
|
hideWriteOnlyProperties: opts.hideWriteOnlyProperties,
|
|
102
|
-
|
|
102
|
+
prevExampleSchemas: [],
|
|
103
103
|
refLogger: refLogger,
|
|
104
104
|
transformer: opts.transformer,
|
|
105
105
|
});
|
|
@@ -135,12 +135,12 @@ function getParametersAsJSONSchema(operation, api, opts) {
|
|
|
135
135
|
if (!mediaTypeObject.schema || !Object.keys(mediaTypeObject.schema).length) {
|
|
136
136
|
return null;
|
|
137
137
|
}
|
|
138
|
-
var
|
|
138
|
+
var prevExampleSchemas = [];
|
|
139
139
|
if ('example' in mediaTypeObject) {
|
|
140
|
-
|
|
140
|
+
prevExampleSchemas.push({ example: mediaTypeObject.example });
|
|
141
141
|
}
|
|
142
142
|
else if ('examples' in mediaTypeObject) {
|
|
143
|
-
|
|
143
|
+
prevExampleSchemas.push({
|
|
144
144
|
examples: Object.values(mediaTypeObject.examples)
|
|
145
145
|
.map(function (example) { return example.value; })
|
|
146
146
|
.filter(function (val) { return val !== undefined; }),
|
|
@@ -153,7 +153,7 @@ function getParametersAsJSONSchema(operation, api, opts) {
|
|
|
153
153
|
globalDefaults: opts.globalDefaults,
|
|
154
154
|
hideReadOnlyProperties: opts.hideReadOnlyProperties,
|
|
155
155
|
hideWriteOnlyProperties: opts.hideWriteOnlyProperties,
|
|
156
|
-
|
|
156
|
+
prevExampleSchemas: prevExampleSchemas,
|
|
157
157
|
refLogger: refLogger,
|
|
158
158
|
transformer: opts.transformer,
|
|
159
159
|
});
|
package/dist/samples/utils.js
CHANGED
|
@@ -12,9 +12,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.deeplyStripKey = exports.isFunc = exports.normalizeArray = exports.objectify = exports.usesPolymorphism = void 0;
|
|
15
|
-
|
|
16
|
-
return !!obj && typeof obj === 'object';
|
|
17
|
-
}
|
|
15
|
+
var helpers_1 = require("../lib/helpers");
|
|
18
16
|
function usesPolymorphism(schema) {
|
|
19
17
|
if (schema.oneOf) {
|
|
20
18
|
return 'oneOf';
|
|
@@ -29,7 +27,7 @@ function usesPolymorphism(schema) {
|
|
|
29
27
|
}
|
|
30
28
|
exports.usesPolymorphism = usesPolymorphism;
|
|
31
29
|
function objectify(thing) {
|
|
32
|
-
if (!isObject(thing)) {
|
|
30
|
+
if (!(0, helpers_1.isObject)(thing)) {
|
|
33
31
|
return {};
|
|
34
32
|
}
|
|
35
33
|
return thing;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oas",
|
|
3
|
-
"version": "20.
|
|
3
|
+
"version": "20.9.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)",
|
|
@@ -59,16 +59,16 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@commitlint/cli": "^17.6.6",
|
|
61
61
|
"@commitlint/config-conventional": "^17.6.6",
|
|
62
|
-
"@readme/eslint-config": "^10.6.
|
|
62
|
+
"@readme/eslint-config": "^10.6.2",
|
|
63
63
|
"@readme/oas-examples": "^5.11.1",
|
|
64
64
|
"@readme/openapi-parser": "^2.5.0",
|
|
65
|
-
"@types/jest": "^29.5.
|
|
65
|
+
"@types/jest": "^29.5.3",
|
|
66
66
|
"@types/json-schema-merge-allof": "^0.6.1",
|
|
67
67
|
"@types/memoizee": "^0.4.6",
|
|
68
|
-
"@types/node": "^20.
|
|
68
|
+
"@types/node": "^20.4.1",
|
|
69
69
|
"eslint": "^8.44.0",
|
|
70
70
|
"husky": "^8.0.3",
|
|
71
|
-
"jest": "^29.
|
|
71
|
+
"jest": "^29.6.1",
|
|
72
72
|
"prettier": "^2.8.8",
|
|
73
73
|
"ts-jest": "^29.1.1",
|
|
74
74
|
"typescript": "^5.1.6"
|
package/src/lib/helpers.ts
CHANGED
|
@@ -8,6 +8,10 @@ export function hasSchemaType(schema: SchemaObject, discriminator: 'array' | 'ob
|
|
|
8
8
|
return schema.type === discriminator;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export function isObject(val: unknown) {
|
|
12
|
+
return typeof val === 'object' && val !== null && !Array.isArray(val);
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
export function isPrimitive(val: unknown): boolean {
|
|
12
16
|
return typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean';
|
|
13
17
|
}
|
|
@@ -9,7 +9,7 @@ import removeUndefinedObjects from 'remove-undefined-objects';
|
|
|
9
9
|
|
|
10
10
|
import * as RMOAS from '../rmoas.types';
|
|
11
11
|
|
|
12
|
-
import { hasSchemaType, isPrimitive } from './helpers';
|
|
12
|
+
import { hasSchemaType, isObject, isPrimitive } from './helpers';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* This list has been pulled from `openapi-schema-to-json-schema` but been slightly modified to fit
|
|
@@ -25,8 +25,6 @@ const UNSUPPORTED_SCHEMA_PROPS = [
|
|
|
25
25
|
'xml',
|
|
26
26
|
] as const;
|
|
27
27
|
|
|
28
|
-
type PrevSchemasType = RMOAS.SchemaObject[];
|
|
29
|
-
|
|
30
28
|
export interface toJSONSchemaOptions {
|
|
31
29
|
/**
|
|
32
30
|
* Whether or not to extend descriptions with a list of any present enums.
|
|
@@ -59,9 +57,14 @@ export interface toJSONSchemaOptions {
|
|
|
59
57
|
isPolymorphicAllOfChild?: boolean;
|
|
60
58
|
|
|
61
59
|
/**
|
|
62
|
-
* Array of parent schemas to
|
|
60
|
+
* Array of parent `default` schemas to utilzie when attempting to path together schema defaults.
|
|
61
|
+
*/
|
|
62
|
+
prevDefaultSchemas?: RMOAS.SchemaObject[];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Array of parent `example` schemas to utilize when attempting to path together schema examples.
|
|
63
66
|
*/
|
|
64
|
-
|
|
67
|
+
prevExampleSchemas?: RMOAS.SchemaObject[];
|
|
65
68
|
|
|
66
69
|
/**
|
|
67
70
|
* A function that's called anytime a (circular) `$ref` is found.
|
|
@@ -154,8 +157,8 @@ function isRequestBodySchema(schema: unknown): schema is RMOAS.RequestBodyObject
|
|
|
154
157
|
}
|
|
155
158
|
|
|
156
159
|
/**
|
|
157
|
-
* Given a JSON pointer and an array of
|
|
158
|
-
* JSON pointer, or part of it, within the array.
|
|
160
|
+
* Given a JSON pointer, a type of property to look for, and an array of schemas do a reverse
|
|
161
|
+
* search through them until we find the JSON pointer, or part of it, within the array.
|
|
159
162
|
*
|
|
160
163
|
* This function will allow you to take a pointer like `/tags/name` and return back `buster` from
|
|
161
164
|
* the following array:
|
|
@@ -183,11 +186,16 @@ function isRequestBodySchema(schema: unknown): schema is RMOAS.RequestBodyObject
|
|
|
183
186
|
* it shouldn't raise immediate cause for alarm.
|
|
184
187
|
*
|
|
185
188
|
* @see {@link https://tools.ietf.org/html/rfc6901}
|
|
189
|
+
* @param property Specific type of schema property to look for a value for.
|
|
186
190
|
* @param pointer JSON pointer to search for an example for.
|
|
187
|
-
* @param
|
|
191
|
+
* @param schemas Array of previous schemas we've found relating to this pointer.
|
|
188
192
|
*/
|
|
189
|
-
function
|
|
190
|
-
|
|
193
|
+
function searchForValueByPropAndPointer(
|
|
194
|
+
property: 'example' | 'default',
|
|
195
|
+
pointer: string,
|
|
196
|
+
schemas: toJSONSchemaOptions['prevExampleSchemas'] | toJSONSchemaOptions['prevDefaultSchemas'] = []
|
|
197
|
+
) {
|
|
198
|
+
if (!schemas.length || !pointer.length) {
|
|
191
199
|
return undefined;
|
|
192
200
|
}
|
|
193
201
|
|
|
@@ -200,42 +208,47 @@ function searchForExampleByPointer(pointer: string, examples: PrevSchemasType =
|
|
|
200
208
|
pointers.push(point);
|
|
201
209
|
}
|
|
202
210
|
|
|
203
|
-
let
|
|
204
|
-
const rev = [...
|
|
211
|
+
let foundValue;
|
|
212
|
+
const rev = [...schemas].reverse();
|
|
205
213
|
|
|
206
214
|
for (let i = 0; i < pointers.length; i += 1) {
|
|
207
215
|
for (let ii = 0; ii < rev.length; ii += 1) {
|
|
208
216
|
let schema = rev[ii];
|
|
209
|
-
if ('example' in schema) {
|
|
210
|
-
schema = schema.example;
|
|
211
|
-
} else {
|
|
212
|
-
if (!Array.isArray(schema.examples) || !schema.examples.length) {
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
if (property === 'example') {
|
|
219
|
+
if ('example' in schema) {
|
|
220
|
+
schema = schema.example;
|
|
221
|
+
} else {
|
|
222
|
+
if (!Array.isArray(schema.examples) || !schema.examples.length) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Prevent us from crashing if `examples` is a completely empty object.
|
|
227
|
+
schema = [...schema.examples].shift();
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
schema = schema.default;
|
|
218
231
|
}
|
|
219
232
|
|
|
220
233
|
try {
|
|
221
|
-
|
|
234
|
+
foundValue = jsonpointer.get(schema, pointers[i]);
|
|
222
235
|
} catch (err) {
|
|
223
236
|
// If the schema we're looking at is `{obj: null}` and our pointer is `/obj/propertyName`
|
|
224
237
|
// `jsonpointer` will throw an error. If that happens, we should silently catch and toss it
|
|
225
238
|
// and return no example.
|
|
226
239
|
}
|
|
227
240
|
|
|
228
|
-
if (
|
|
241
|
+
if (foundValue !== undefined) {
|
|
229
242
|
break;
|
|
230
243
|
}
|
|
231
244
|
}
|
|
232
245
|
|
|
233
|
-
if (
|
|
246
|
+
if (foundValue !== undefined) {
|
|
234
247
|
break;
|
|
235
248
|
}
|
|
236
249
|
}
|
|
237
250
|
|
|
238
|
-
return
|
|
251
|
+
return foundValue;
|
|
239
252
|
}
|
|
240
253
|
|
|
241
254
|
/**
|
|
@@ -288,7 +301,8 @@ export default function toJSONSchema(
|
|
|
288
301
|
hideReadOnlyProperties,
|
|
289
302
|
hideWriteOnlyProperties,
|
|
290
303
|
isPolymorphicAllOfChild,
|
|
291
|
-
|
|
304
|
+
prevDefaultSchemas,
|
|
305
|
+
prevExampleSchemas,
|
|
292
306
|
refLogger,
|
|
293
307
|
transformer,
|
|
294
308
|
} = {
|
|
@@ -298,7 +312,8 @@ export default function toJSONSchema(
|
|
|
298
312
|
hideReadOnlyProperties: false,
|
|
299
313
|
hideWriteOnlyProperties: false,
|
|
300
314
|
isPolymorphicAllOfChild: false,
|
|
301
|
-
|
|
315
|
+
prevDefaultSchemas: [] as toJSONSchemaOptions['prevDefaultSchemas'],
|
|
316
|
+
prevExampleSchemas: [] as toJSONSchemaOptions['prevExampleSchemas'],
|
|
302
317
|
refLogger: () => true,
|
|
303
318
|
transformer: (s: RMOAS.SchemaObject) => s,
|
|
304
319
|
...opts,
|
|
@@ -391,7 +406,8 @@ export default function toJSONSchema(
|
|
|
391
406
|
hideReadOnlyProperties,
|
|
392
407
|
hideWriteOnlyProperties,
|
|
393
408
|
isPolymorphicAllOfChild: false,
|
|
394
|
-
|
|
409
|
+
prevDefaultSchemas,
|
|
410
|
+
prevExampleSchemas,
|
|
395
411
|
refLogger,
|
|
396
412
|
transformer,
|
|
397
413
|
};
|
|
@@ -564,6 +580,10 @@ export default function toJSONSchema(
|
|
|
564
580
|
}
|
|
565
581
|
|
|
566
582
|
if (RMOAS.isSchema(schema, isPolymorphicAllOfChild)) {
|
|
583
|
+
if ('default' in schema && isObject(schema.default)) {
|
|
584
|
+
prevDefaultSchemas.push({ default: schema.default });
|
|
585
|
+
}
|
|
586
|
+
|
|
567
587
|
// JSON Schema doesn't support OpenAPI-style examples so we need to reshape them a bit.
|
|
568
588
|
if ('example' in schema) {
|
|
569
589
|
// Only bother adding primitive examples.
|
|
@@ -575,7 +595,7 @@ export default function toJSONSchema(
|
|
|
575
595
|
delete schema.examples;
|
|
576
596
|
}
|
|
577
597
|
} else {
|
|
578
|
-
|
|
598
|
+
prevExampleSchemas.push({ example: schema.example });
|
|
579
599
|
}
|
|
580
600
|
|
|
581
601
|
delete schema.example;
|
|
@@ -598,9 +618,9 @@ export default function toJSONSchema(
|
|
|
598
618
|
reshapedExamples = true;
|
|
599
619
|
} else {
|
|
600
620
|
// If this example is neither a primitive or an array we should dump it into the
|
|
601
|
-
// `
|
|
602
|
-
// downstream.
|
|
603
|
-
|
|
621
|
+
// `prevExampleSchemas` array because we might be able to extract an example from it
|
|
622
|
+
// further downstream.
|
|
623
|
+
prevExampleSchemas.push({
|
|
604
624
|
example: example.value,
|
|
605
625
|
});
|
|
606
626
|
}
|
|
@@ -626,7 +646,7 @@ export default function toJSONSchema(
|
|
|
626
646
|
// find one. But as we're only looking for primitive example, only try to search for one if
|
|
627
647
|
// we're dealing with a primitive schema.
|
|
628
648
|
if (!hasSchemaType(schema, 'array') && !hasSchemaType(schema, 'object') && !schema.examples) {
|
|
629
|
-
const foundExample =
|
|
649
|
+
const foundExample = searchForValueByPropAndPointer('example', currentLocation, prevExampleSchemas);
|
|
630
650
|
if (foundExample) {
|
|
631
651
|
// We can only really deal with primitives, so only promote those as the found example if
|
|
632
652
|
// it is.
|
|
@@ -650,7 +670,7 @@ export default function toJSONSchema(
|
|
|
650
670
|
globalDefaults,
|
|
651
671
|
hideReadOnlyProperties,
|
|
652
672
|
hideWriteOnlyProperties,
|
|
653
|
-
|
|
673
|
+
prevExampleSchemas,
|
|
654
674
|
refLogger,
|
|
655
675
|
transformer,
|
|
656
676
|
});
|
|
@@ -679,7 +699,8 @@ export default function toJSONSchema(
|
|
|
679
699
|
globalDefaults,
|
|
680
700
|
hideReadOnlyProperties,
|
|
681
701
|
hideWriteOnlyProperties,
|
|
682
|
-
|
|
702
|
+
prevDefaultSchemas,
|
|
703
|
+
prevExampleSchemas,
|
|
683
704
|
refLogger,
|
|
684
705
|
transformer,
|
|
685
706
|
});
|
|
@@ -727,7 +748,8 @@ export default function toJSONSchema(
|
|
|
727
748
|
globalDefaults,
|
|
728
749
|
hideReadOnlyProperties,
|
|
729
750
|
hideWriteOnlyProperties,
|
|
730
|
-
|
|
751
|
+
prevDefaultSchemas,
|
|
752
|
+
prevExampleSchemas,
|
|
731
753
|
refLogger,
|
|
732
754
|
transformer,
|
|
733
755
|
});
|
|
@@ -786,21 +808,41 @@ export default function toJSONSchema(
|
|
|
786
808
|
|
|
787
809
|
// Only add a default value if we actually have one.
|
|
788
810
|
if ('default' in schema && typeof schema.default !== 'undefined') {
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
schema.description = schema.description
|
|
793
|
-
? `${schema.description.replace(/\n$/, '')}\n\nDefault: \`${schema.default}\``
|
|
794
|
-
: `Default: ${schema.default}`;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
if (('allowEmptyValue' in schema && schema.allowEmptyValue && schema.default === '') || schema.default !== '') {
|
|
798
|
-
// If we have `allowEmptyValue` present, and the default is actually an empty string, let it
|
|
799
|
-
// through as it's allowed.
|
|
800
|
-
} else {
|
|
801
|
-
// If the default is empty and we don't want to allowEmptyValue, we need to remove the
|
|
802
|
-
// default.
|
|
811
|
+
if (hasSchemaType(schema, 'object')) {
|
|
812
|
+
// Defaults for `object` and types have been dereferenced into their children schemas already
|
|
813
|
+
// above so we don't need to preserve this default anymore.
|
|
803
814
|
delete schema.default;
|
|
815
|
+
} else {
|
|
816
|
+
// If it's an enum and not the response schema, add the default to the description.
|
|
817
|
+
// If there's an existing description, trim trailing new lines so it doesn't look ugly.
|
|
818
|
+
if ('enum' in schema && !addEnumsToDescriptions) {
|
|
819
|
+
schema.description = schema.description
|
|
820
|
+
? `${schema.description.replace(/\n$/, '')}\n\nDefault: \`${schema.default}\``
|
|
821
|
+
: `Default: ${schema.default}`;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (('allowEmptyValue' in schema && schema.allowEmptyValue && schema.default === '') || schema.default !== '') {
|
|
825
|
+
// If we have `allowEmptyValue` present, and the default is actually an empty string, let it
|
|
826
|
+
// through as it's allowed.
|
|
827
|
+
} else {
|
|
828
|
+
// If the default is empty and we don't want to allowEmptyValue, we need to remove the
|
|
829
|
+
// default.
|
|
830
|
+
delete schema.default;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
} else if (prevDefaultSchemas.length) {
|
|
834
|
+
const foundDefault = searchForValueByPropAndPointer('default', currentLocation, prevDefaultSchemas);
|
|
835
|
+
|
|
836
|
+
// We shouldn't ever set an object default out of the parent lineage tree defaults because
|
|
837
|
+
// the contents of that object will be set on the schema that they're a part of. Setting
|
|
838
|
+
// that object as well would result us in duplicating the defaults for that schema in two
|
|
839
|
+
// places.
|
|
840
|
+
if (
|
|
841
|
+
isPrimitive(foundDefault) ||
|
|
842
|
+
foundDefault === null ||
|
|
843
|
+
(Array.isArray(foundDefault) && hasSchemaType(schema, 'array'))
|
|
844
|
+
) {
|
|
845
|
+
schema.default = foundDefault;
|
|
804
846
|
}
|
|
805
847
|
}
|
|
806
848
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { toJSONSchemaOptions } from '../lib/openapi-to-json-schema';
|
|
1
2
|
import type Operation from '../operation';
|
|
2
3
|
import type { ComponentsObject, ExampleObject, OASDocument, ParameterObject, SchemaObject } from '../rmoas.types';
|
|
3
4
|
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
@@ -125,7 +126,7 @@ export default function getParametersAsJSONSchema(
|
|
|
125
126
|
globalDefaults: opts.globalDefaults,
|
|
126
127
|
hideReadOnlyProperties: opts.hideReadOnlyProperties,
|
|
127
128
|
hideWriteOnlyProperties: opts.hideWriteOnlyProperties,
|
|
128
|
-
|
|
129
|
+
prevExampleSchemas: [],
|
|
129
130
|
refLogger,
|
|
130
131
|
transformer: opts.transformer,
|
|
131
132
|
});
|
|
@@ -170,11 +171,11 @@ export default function getParametersAsJSONSchema(
|
|
|
170
171
|
return null;
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
const
|
|
174
|
+
const prevExampleSchemas: toJSONSchemaOptions['prevExampleSchemas'] = [];
|
|
174
175
|
if ('example' in mediaTypeObject) {
|
|
175
|
-
|
|
176
|
+
prevExampleSchemas.push({ example: mediaTypeObject.example });
|
|
176
177
|
} else if ('examples' in mediaTypeObject) {
|
|
177
|
-
|
|
178
|
+
prevExampleSchemas.push({
|
|
178
179
|
examples: Object.values(mediaTypeObject.examples)
|
|
179
180
|
.map((example: ExampleObject) => example.value)
|
|
180
181
|
.filter(val => val !== undefined),
|
|
@@ -189,7 +190,7 @@ export default function getParametersAsJSONSchema(
|
|
|
189
190
|
globalDefaults: opts.globalDefaults,
|
|
190
191
|
hideReadOnlyProperties: opts.hideReadOnlyProperties,
|
|
191
192
|
hideWriteOnlyProperties: opts.hideWriteOnlyProperties,
|
|
192
|
-
|
|
193
|
+
prevExampleSchemas,
|
|
193
194
|
refLogger,
|
|
194
195
|
transformer: opts.transformer,
|
|
195
196
|
});
|
package/src/samples/utils.ts
CHANGED
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type * as RMOAS from '../rmoas.types';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
return !!obj && typeof obj === 'object';
|
|
11
|
-
}
|
|
9
|
+
import { isObject } from '../lib/helpers';
|
|
12
10
|
|
|
13
11
|
export function usesPolymorphism(schema: RMOAS.SchemaObject) {
|
|
14
12
|
if (schema.oneOf) {
|