Skip to content

Commit be3d58f

Browse files
committed
Use JSON Schema Walker
1 parent 9155b51 commit be3d58f

File tree

4 files changed

+42
-94
lines changed

4 files changed

+42
-94
lines changed

index.js

Lines changed: 31 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const structs = ['allOf', 'anyOf', 'oneOf', 'not', 'items', 'additionalProperties'];
1+
const schemaWalker = require('@cloudflare/json-schema-walker');
22

33
function InvalidTypeError(message) {
44
this.name = 'InvalidTypeError';
@@ -7,61 +7,27 @@ function InvalidTypeError(message) {
77

88
InvalidTypeError.prototype = new Error();
99

10-
function convert(schema, options) {
11-
options = options || {};
12-
options.cloneSchema = ! (options.cloneSchema === false);
10+
function convert(schema, options = {}) {
11+
const { cloneSchema = true } = options;
1312

14-
if (options.cloneSchema) {
13+
if (cloneSchema) {
1514
schema = JSON.parse(JSON.stringify(schema));
1615
}
1716

18-
schema = removeRootKeywords(schema);
19-
schema = convertSchema(schema);
20-
17+
const vocab = schemaWalker.getVocabulary(schema, schemaWalker.vocabularies.DRAFT_04);
18+
schemaWalker.schemaWalk(schema, convertSchema, null, vocab);
2119
return schema;
2220
}
2321

24-
function removeRootKeywords(schema) {
22+
function stripIllegalKeywords(schema) {
2523
delete schema['$schema'];
24+
delete schema['$id'];
2625
delete schema['id'];
2726
return schema;
2827
}
2928

30-
function convertSchema(schema) {
31-
let i = 0;
32-
let j = 0;
33-
let struct = null;
34-
35-
for (i; i < structs.length; i++) {
36-
struct = structs[i];
37-
38-
if (Array.isArray(schema[struct])) {
39-
for (j; j < schema[struct].length; j++) {
40-
schema[struct][j] = convertSchema(schema[struct][j]);
41-
}
42-
} else if (typeof schema[struct] === 'object') {
43-
schema[struct] = convertSchema(schema[struct]);
44-
}
45-
}
46-
47-
if (typeof schema.properties === 'object') {
48-
schema.properties = convertProperties(schema.properties);
49-
50-
if (Array.isArray(schema.required)) {
51-
schema.required = cleanRequired(schema.required, schema.properties);
52-
53-
if (schema.required.length === 0) {
54-
delete schema.required;
55-
}
56-
}
57-
if (Object.keys(schema.properties).length === 0) {
58-
delete schema.properties;
59-
}
60-
61-
}
62-
63-
validateType(schema.type);
64-
29+
function convertSchema(schema, path, parent, parentPath) {
30+
schema = stripIllegalKeywords(schema);
6531
schema = convertTypes(schema);
6632
schema = convertDependencies(schema);
6733

@@ -81,19 +47,6 @@ function validateType(type) {
8147
});
8248
}
8349

84-
function convertProperties(properties) {
85-
let key = {};
86-
let property = {};
87-
let props = {};
88-
89-
for (key in properties) {
90-
property = properties[key];
91-
props[key] = convertSchema(property);
92-
}
93-
94-
return props;
95-
}
96-
9750
function convertDependencies(schema) {
9851
const deps = schema.dependencies;
9952
if (typeof deps !== 'object') {
@@ -140,38 +93,40 @@ function convertDependencies(schema) {
14093
}
14194

14295
function convertTypes(schema) {
143-
var newType;
144-
14596
if (schema.type === undefined) {
14697
return schema;
14798
}
14899

149-
// type needs to be a string, not an array
150-
if (schema.type instanceof Array && schema.type.includes('null')) {
151-
var numTypes = schema.type.length;
100+
validateType(schema.type);
152101

153-
schema.nullable = true;
102+
if (Array.isArray(schema.type)) {
154103

155-
// if it was just type: ['null'] for some reason
156-
switch (numTypes) {
157-
case 1:
158-
// Didn't know what else to do
159-
newType = 'string';
104+
if (schema.type.length > 2 || !schema.type.includes('null')) {
105+
throw new Error('Type of ' + schema.type.join(',') + ' is too confusing for OpenAPI to understand. Found in ' + JSON.stringify(schema));
106+
}
107+
108+
switch (schema.type.length) {
109+
case 0:
110+
delete schema.type;
160111
break;
161112

162-
case 2:
163-
newType = schema.type.find(function(element) {
164-
return element !== 'null';
165-
});
113+
case 1:
114+
if (schema.type === 'null') {
115+
schema.nullable = true;
116+
}
117+
else {
118+
schema.type = schema.type[0];
119+
}
166120
break;
167121

168122
default:
169-
throw 'type cannot be an array, and you have ' + numTypes + ' types';
123+
schema.type = schema.type.find(type => type !== 'null');
124+
schema.nullable = true;
170125
}
171126
}
172-
173-
if (newType) {
174-
schema.type = newType;
127+
else if (schema.type === 'null') {
128+
delete schema.type;
129+
schema.nullable = true;
175130
}
176131

177132
return schema;
@@ -185,19 +140,4 @@ function convertPatternProperties(schema) {
185140
return schema;
186141
}
187142

188-
function cleanRequired(required, properties) {
189-
var i = 0;
190-
191-
required = required || [];
192-
properties = properties || {};
193-
194-
for (i; i < required.length; i++) {
195-
if (properties[required[i]] === undefined) {
196-
required.splice(i, 1);
197-
}
198-
}
199-
200-
return required;
201-
}
202-
203143
module.exports = convert;

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@
1515
"mocha": "^5.0.0",
1616
"nyc": "^11.6.0",
1717
"should": "^13.2.0"
18+
},
19+
"dependencies": {
20+
"@cloudflare/json-schema-walker": "^0.1.1"
1821
}
1922
}

test/nullable.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ it('adds `nullable: true` for `type: [string, null]`', () => {
2121
it('supports nullables inside sub-schemas', () => {
2222
const schema = {
2323
$schema: 'http://json-schema.org/draft-04/schema#',
24-
$oneOf: [
24+
oneOf: [
2525
{ type: 'string' },
2626
{ type: 'null' }
2727
]
@@ -30,10 +30,10 @@ it('supports nullables inside sub-schemas', () => {
3030
const result = convert(schema);
3131

3232
should(result).deepEqual({
33-
$oneOf: [
33+
oneOf: [
3434
{ type: 'string' },
3535
{ nullable: true }
36-
]
36+
]
3737
});
3838
});
3939

0 commit comments

Comments
 (0)