falcor-router
Version:
A router DataSource constructor for falcor that allows you to model all your cloud data sources as a single JSON resource.
86 lines (71 loc) • 2.66 kB
JavaScript
var iterateKeySet = require('falcor-path-utils').iterateKeySet;
var cloneArray = require('./../support/cloneArray');
var catAndSlice = require('./../support/catAndSlice');
var $types = require('./../support/types');
var $ref = $types.$ref;
var followReference = require('./followReference');
/**
* The fastest possible optimize of paths.
*
* What it does:
* - Any atom short-circuit / found value will be removed from the path.
* - All paths will be exploded which means that collapse will need to be
* ran afterwords.
* - Any missing path will be optimized as much as possible.
*/
module.exports = function optimizePathSets(cache, paths, maxRefFollow) {
var optimized = [];
paths.forEach(function(p) {
optimizePathSet(cache, cache, p, 0, optimized, [], maxRefFollow);
});
return optimized;
};
/**
* optimizes one pathSet at a time.
*/
function optimizePathSet(cache, cacheRoot, pathSet,
depth, out, optimizedPath, maxRefFollow) {
// at missing, report optimized path.
if (cache === undefined) {
out[out.length] = catAndSlice(optimizedPath, pathSet, depth);
return;
}
// all other sentinels are short circuited.
// Or we found a primitive (which includes null)
if (cache === null || (cache.$type && cache.$type !== $ref) ||
(typeof cache !== 'object')) {
return;
}
// If the reference is the last item in the path then do not
// continue to search it.
if (cache.$type === $ref && depth === pathSet.length) {
return;
}
var keySet = pathSet[depth];
var nextDepth = depth + 1;
var iteratorNote = {};
var key, next, nextOptimized;
key = iterateKeySet(keySet, iteratorNote);
do {
next = cache[key];
var optimizedPathLength = optimizedPath.length;
if (key !== null) {
optimizedPath[optimizedPathLength] = key;
}
if (next && next.$type === $ref && nextDepth < pathSet.length) {
var refResults =
followReference(cacheRoot, next.value, maxRefFollow);
next = refResults[0];
// must clone to avoid the mutation from above destroying the cache.
nextOptimized = cloneArray(refResults[1]);
} else {
nextOptimized = optimizedPath;
}
optimizePathSet(next, cacheRoot, pathSet, nextDepth,
out, nextOptimized, maxRefFollow);
optimizedPath.length = optimizedPathLength;
if (!iteratorNote.done) {
key = iterateKeySet(keySet, iteratorNote);
}
} while (!iteratorNote.done);
}