core-types
Version:
Generic type declarations for e.g. TypeScript, GraphQL and JSON Schema
67 lines (66 loc) • 2.23 kB
JavaScript
class StopError extends Error {
}
export function traverse(node, cb) {
function makeNewArg(arg, parentNode, parentProperty, index, required, newNode) {
const node = newNode !== undefined
? newNode
: index === undefined
? parentNode[parentProperty]
: parentNode[parentProperty][index];
const newPath = [
...arg.path,
parentProperty,
...(index === undefined ? [] : [index]),
];
const newValues = {
node,
path: newPath,
parentNode,
parentProperty: parentProperty,
index,
required,
};
return Object.assign({}, arg, newValues);
}
function recurse(arg, cb) {
cb(arg);
const { node } = arg;
if (node.type === 'array')
recurse(makeNewArg(arg, node, 'elementType'), cb);
else if (node.type === 'tuple') {
node.elementTypes.forEach((_, i) => recurse(makeNewArg(arg, node, 'elementTypes', i), cb));
if (typeof node.additionalItems === 'object')
recurse(makeNewArg(arg, node, 'additionalItems'), cb);
}
else if (node.type === 'object') {
for (const prop of Object.keys(node.properties))
recurse(makeNewArg(arg, node, 'properties', prop, node.properties[prop].required, node.properties[prop].node), cb);
if (typeof node.additionalProperties === 'object')
recurse(makeNewArg(arg, node, 'additionalProperties'), cb);
}
else if (node.type === 'and')
node.and.forEach((_, i) => recurse(makeNewArg(arg, node, 'and', i), cb));
else if (node.type === 'or')
node.or.forEach((_, i) => recurse(makeNewArg(arg, node, 'or', i), cb));
}
const arg = {
node,
rootNode: node,
path: [],
};
recurse(arg, cb);
}
export function some(node, cb) {
try {
traverse(node, arg => {
if (cb(arg))
throw new StopError();
});
}
catch (err) {
if (err instanceof StopError)
return true;
throw err;
}
return false;
}