-
Notifications
You must be signed in to change notification settings - Fork 148
/
traverseSchema.js
118 lines (109 loc) · 3.04 KB
/
traverseSchema.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
* Copyright 2019 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
const {
iter, pipe, map, list, flat, enumerate,
} = require('ferrum');
const arrayKeywords = [
'allOf',
'anyOf',
'items',
'oneOf',
];
const propertyKeywords = [
'definitions',
'dependencies',
'patternProperties',
'properties',
];
const ignoreKeywords = [
'const',
'default',
'enum',
'exclusiveMaximum',
'exclusiveMinimum',
'format',
'maximum',
'maxItems',
'maxLength',
'maxProperties',
'meta:license',
'minimum',
'minItems',
'minLength',
'minProperties',
'multipleOf',
'pattern',
'required',
'uniqueItems',
];
/**
* Traverses a Schema node (containing a JSON Schema) to find sub-schemas,
* which are then emitted as asequence.
* @param {Schema} node
*/
function traverse(node) {
const { schema, pointer = '', id } = node;
const items = pipe(
// turn the schema object into a sequence of key value pairs
iter(schema),
map(([key, subschema]) => {
if (Array.isArray(subschema) && arrayKeywords.includes(key)) {
// descend into the array
return pipe(
iter(subschema),
enumerate,
map(([index, subsubschema]) => ({
schema: subsubschema,
direct: false,
pointer: `${pointer}/${key}/${index}`,
id,
root: schema,
// TODO add additional properties for tracking
})),
);
}
if (subschema && typeof subschema === 'object' && propertyKeywords.includes(key)) {
// descend into the object
return pipe(
iter(subschema),
map(([subkey, subsubschema]) => ({
schema: subsubschema,
direct: false,
pointer: `${pointer}/${key}/${subkey}`,
id,
root: schema,
// TODO add additional properties for tracking
})),
);
}
if (subschema && typeof subschema === 'object' && !ignoreKeywords.includes(key)) {
// this could be a schema, too
return [{
schema: subschema,
direct: false,
pointer: `${pointer}/${key}`,
id,
root: schema,
// TODO add additional properties for tracking
}];
}
return [];
}),
flat,
);
const itemsarray = list(items, Array);
const subitems = map(items, traverse);
const subitemsarray = list(subitems, Array);
const allitems = [node, ...itemsarray, ...subitemsarray];
return allitems;
}
module.exports = traverse;