UNPKG

fakeit

Version:

Command-line utility that generates fake data which can be output as JSON, YAML, CSON, or CSV formats based on models defined in YAML.

1,015 lines (813 loc) 34.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseModelInputs = undefined; var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _assign = require('babel-runtime/core-js/object/assign'); var _assign2 = _interopRequireDefault(_assign); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); /// @name parseModelInputs /// @description /// This is used to parse files that are used to generate specific data /// @arg {object} model - The model to parse /// @returns {object} /// @async /// @note {5} The `model.data.input` paths must already be resolved to be a absolute path. var parseModelInputs = exports.parseModelInputs = function () { var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(model) { var _this5 = this; var inputs, files; return _regenerator2.default.wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: if (!(!model.data.inputs || !model.data.inputs.length)) { _context7.next = 3; break; } model.data.inputs = []; return _context7.abrupt('return', {}); case 3: inputs = {}; // get list of files, flatten the array of files and filter files for valid input formats: csv, json, cson, yaml and zip _context7.t0 = _toJs2.default; _context7.next = 7; return utils.findFiles(model.data.inputs); case 7: _context7.t1 = _context7.sent; _context7.t2 = function (file) { return !!file && /\.(csv|json|cson|ya?ml|zip)$/i.test(file); }; files = _context7.t0.flatten.call(_context7.t0, _context7.t1).filter(_context7.t2); if (files.length) { _context7.next = 12; break; } throw new Error('No valid input files found for ' + model.file); case 12: _context7.next = 14; return utils.readFiles(files); case 14: files = _context7.sent; _context7.next = 17; return (0, _asyncArrayMethods.map)(files, function () { var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6(file) { var parser; return _regenerator2.default.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: // get the current parser to use parser = utils.parsers[file.ext.replace(/^\./, '')]; if (parser) { _context6.next = 3; break; } throw new Error('No valid parser could be found for "' + file.name + '.' + file.type + '"'); case 3: _context6.next = 5; return parser.parse(file.content); case 5: inputs[file.name] = _context6.sent; return _context6.abrupt('return', file); case 7: case 'end': return _context6.stop(); } } }, _callee6, _this5); })); return function (_x8) { return _ref7.apply(this, arguments); }; }()); case 17: return _context7.abrupt('return', inputs); case 18: case 'end': return _context7.stop(); } } }, _callee7, this); })); return function parseModelInputs(_x7) { return _ref6.apply(this, arguments); }; }(); /// @name parseModelFunctions /// @description /// searches the model for any of the pre / post run and build functions and generates them /// @arg {object} model - The model to update /// @arg {string, object} babel_config [{}] - The configuration to use for babel exports.parseModelFunctions = parseModelFunctions; exports.parseModelReferences = parseModelReferences; exports.parseModelTypes = parseModelTypes; exports.parseModelDefaults = parseModelDefaults; exports.parseModelCount = parseModelCount; exports.parseModelSeed = parseModelSeed; exports.resolveDependenciesOrder = resolveDependenciesOrder; exports.resolveDependants = resolveDependants; var _asyncArrayMethods = require('async-array-methods'); var _fsExtraPromisify = require('fs-extra-promisify'); var _fsExtraPromisify2 = _interopRequireDefault(_fsExtraPromisify); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _dependencyResolver = require('dependency-resolver'); var _dependencyResolver2 = _interopRequireDefault(_dependencyResolver); var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils); var _base = require('./base'); var _base2 = _interopRequireDefault(_base); var _lodash = require('lodash'); var _toJs = require('to-js'); var _toJs2 = _interopRequireDefault(_toJs); var _babelCore = require('babel-core'); var _globby = require('globby'); var _globby2 = _interopRequireDefault(_globby); var _findRoot = require('find-root'); var _findRoot2 = _interopRequireDefault(_findRoot); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } //// /// @name Models /// @page api/models //// var Models = function (_Base) { (0, _inherits3.default)(Models, _Base); function Models() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck3.default)(this, Models); // holds all the inputs that are registerd var _this = (0, _possibleConstructorReturn3.default)(this, (Models.__proto__ || (0, _getPrototypeOf2.default)(Models)).call(this, _toJs2.default.extend({ count: 0, seed: 0, babel_config: '+(.babelrc|package.json)' }, options))); _this.inputs = {}; _this.models = []; // holds the parsed models _this.registered_models = []; // holds the paths that have already been added _this.prepared = false; return _this; } ///# @name prepare ///# @description ///# This is used to prepare the saving functionality that is determined by the ///# options that were passed to the constructor. ///# It sets a variable of `this.preparing` that ultimately calls `this.setup` that returns a promise. ///# This way when you go to save data it, that function will know if the setup is complete or not and ///# wait for it to be done before it starts saving data. ///# @returns {promise} - The setup function that was called ///# @async (0, _createClass3.default)(Models, [{ key: 'prepare', value: function prepare() { this.preparing = true; this.preparing = this.setup(); return this.preparing; } ///# @name setup ///# @description ///# This is used to setup the saving function that will be used. ///# @async }, { key: 'setup', value: function () { var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() { var _this2 = this; var babel_config, file, config; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (!(this.preparing == null)) { _context.next = 2; break; } return _context.abrupt('return', this.prepare()); case 2: babel_config = this.options.babel_config; if (_toJs.is.string(babel_config)) { _context.next = 6; break; } process.nextTick(function () { _this2.prepared = true; }); return _context.abrupt('return'); case 6: file = [process.cwd(), this.options.root].reduce(function (prev, next) { try { return prev.concat(_path2.default.join((0, _findRoot2.default)(next), babel_config)); } catch (e) { return prev; } }, []); _context.next = 9; return (0, _globby2.default)(_toJs2.default.unique(file), { dot: true }); case 9: file = _context.sent; file = file[0]; if (!file) { _context.next = 17; break; } _context.next = 14; return _fsExtraPromisify2.default.readJson(file); case 14: config = _context.sent; if (file.indexOf('package.json') !== -1) { config = config.babelConfig || {}; } this.options.babel_config = config; case 17: this.prepared = true; case 18: case 'end': return _context.stop(); } } }, _callee, this); })); function setup() { return _ref.apply(this, arguments); } return setup; }() ///# @name update ///# @description ///# This updates the progress spinner to show how many models have been parsed and how many are left }, { key: 'update', value: function update() { this.progress.text = 'Models (' + this.models.length + '/' + this.registered_models.length + ')'; } /// @name filterModelFiles /// @description This is used to filter out valid and unregistered model files /// @returns {array} }, { key: 'filterModelFiles', value: function filterModelFiles(files) { var _this3 = this; return _toJs2.default.flatten(files).filter(function (file) { return !!file && /\.(ya?ml)$/i.test(file) && !(_this3.registered_models.indexOf(file) !== -1); }); } }, { key: 'registerModels', value: function () { var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(models) { var _this4 = this; var dependency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var files; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: this.progress = this.progress || this.spinner('Models').start(); // if models weren't passed in then don't do anything if (models) { _context3.next = 3; break; } return _context3.abrupt('return'); case 3: if (!(this.prepared !== true)) { _context3.next = 7; break; } if (this.preparing == null) { this.prepare(); } _context3.next = 7; return this.preparing; case 7: _context3.t0 = this; _context3.next = 10; return utils.findFiles(this.resolvePaths(models)); case 10: _context3.t1 = _context3.sent; files = _context3.t0.filterModelFiles.call(_context3.t0, _context3.t1); if (files.length) { _context3.next = 16; break; } if (dependency) { _context3.next = 15; break; } throw new Error('No valid model files found.'); case 15: return _context3.abrupt('return'); case 16: ; _context3.next = 19; return (0, _asyncArrayMethods.forEach)(files, function () { var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(file) { var _model, model; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: if (!(_this4.registered_models.indexOf(file) !== -1)) { _context2.next = 3; break; } if (!dependency) { _model = (0, _lodash.find)(_this4.models, ['file', file]); _model.is_dependency = dependency; } return _context2.abrupt('return'); case 3: // add it to the models _this4.registered_models.push(file); _this4.update(); // read yaml file and convert it to json _context2.t0 = utils.parsers.yaml; _context2.t1 = _toJs2.default; _context2.next = 9; return _fsExtraPromisify2.default.readFile(file); case 9: _context2.t2 = _context2.sent; _context2.t3 = _context2.t1.string.call(_context2.t1, _context2.t2); _context2.next = 13; return _context2.t0.parse.call(_context2.t0, _context2.t3); case 13: model = _context2.sent; // used for debugging model.file = file; // sets the root of the model so that we can resolve inputs and dependencies later model.root = _path2.default.resolve(_this4.options.root, _path2.default.dirname(model.file)); // used to determine if something is a dependency or not. if (model.is_dependency == null) { model.is_dependency = dependency; } /* istanbul ignore if : currently hard to test */ if (!model.name) { model.name = _path2.default.basename(file).split('.')[0]; } // validate the model /* istanbul ignore if : currently hard to test */ if (!model.type) { _this4.log('error', new Error('The model ' + model.name + ' must have a "type" property.')); } /* istanbul ignore if : currently hard to test */ if (!model.key) { _this4.log('error', new Error('The model ' + model.name + ' must have a "key" property.')); } // add the parsed model to the global object should always have a model name _context2.next = 22; return _this4.parseModel(model); case 22: _this4.models.push(model); _this4.update(); case 24: case 'end': return _context2.stop(); } } }, _callee2, _this4); })); return function (_x4) { return _ref3.apply(this, arguments); }; }()).catch(function (err) { _this4.progress.fail(err); }); case 19: // update the models order this.models = resolveDependenciesOrder(this.models); this.models = resolveDependants(this.models); if (this.models.length === this.registered_models.length) { this.progress.stop(); } return _context3.abrupt('return', this); case 23: case 'end': return _context3.stop(); } } }, _callee3, this); })); function registerModels(_x2) { return _ref2.apply(this, arguments); } return registerModels; }() ///# @name parseModel ///# @description ///# This is used to parse the model that was passed and add the functions, and fix the types, data, and defaults ///# @arg {object} model - The model to parse. ///# @returns {object} - The model that's been updated }, { key: 'parseModel', value: function () { var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(model) { var inputs, dependencies; return _regenerator2.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: // resolve the input paths parseModelDefaults(model); model.data.inputs = this.resolvePaths(model.data.inputs, model.root); // resolve the dependencies paths model.data.dependencies = this.resolvePaths(model.data.dependencies, model.root); inputs = parseModelInputs(model); dependencies = this.parseModelDependencies(model); parseModelFunctions(model, this.options.babel_config); parseModelReferences(model); parseModelTypes(model); parseModelCount(model, this.options.count); parseModelSeed(model, this.options.seed); // add this models inputs to the main inputs object _context4.t0 = _assign2.default; _context4.t1 = this.inputs || {}; _context4.next = 14; return inputs; case 14: _context4.t2 = _context4.sent; this.inputs = (0, _context4.t0)(_context4.t1, _context4.t2); _context4.next = 18; return dependencies; case 18: return _context4.abrupt('return', model); case 19: case 'end': return _context4.stop(); } } }, _callee4, this); })); function parseModel(_x5) { return _ref4.apply(this, arguments); } return parseModel; }() ///# @name parseModel ///# @description ///# This is used to parse model dependencies if they have any ///# @arg {object} model - The model to parse. ///# @async }, { key: 'parseModelDependencies', value: function () { var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(model) { var files; return _regenerator2.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: if (!(!model.data.dependencies || !model.data.dependencies.length)) { _context5.next = 3; break; } model.data.dependencies = []; return _context5.abrupt('return'); case 3: _context5.t0 = _toJs2.default; _context5.next = 6; return utils.findFiles(model.data.dependencies); case 6: _context5.t1 = _context5.sent; files = _context5.t0.flatten.call(_context5.t0, _context5.t1); if (files.length) { _context5.next = 11; break; } model.data.dependencies = []; return _context5.abrupt('return'); case 11: _context5.next = 13; return this.registerModels(files, true); case 13: case 'end': return _context5.stop(); } } }, _callee5, this); })); function parseModelDependencies(_x6) { return _ref5.apply(this, arguments); } return parseModelDependencies; }() }]); return Models; }(_base2.default); exports.default = Models; function parseModelFunctions(model) { var babel_config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var paths = utils.objectSearch(model, /((pre|post)_run)|(pre_|post_)?build$/); paths.forEach(function (function_path) { var name = _toJs2.default.camelCase(function_path); // get the function var fn = (0, _lodash.get)(model, function_path).trim().split('\n').filter(Boolean); // if it's a single line function then ensure that the value is returned // just like normal es6 arrow functions if (fn.length === 1) { fn = ['return ' + fn[0].replace(/^return\s+/, '')]; } // indent each line and create a string fn = fn.map(function (line) { return ' ' + line; }).filter(Boolean).join('\n'); // wrap the users function in the function we're going to use to trigger their function fn = 'function __result(documents, globals, inputs, faker, chance, document_index, require) {\n' + fn + '\n}'; // if a babel config exists then transform the function if (_toJs.is.plainObject(babel_config) && !_toJs.is.empty(babel_config)) { try { // transform the function and remove the `'use strict';\n` part that babel adds if it exists fn = (0, _babelCore.transform)(fn, babel_config).code.replace(/^.use strict.;\n+/, ''); } catch (e) { var file_message = model.file ? ' in ' + model.file : ''; e.message = ('Failed to transpile ' + function_path + ' with babel' + file_message + '\n' + e.message).trim(); throw e; } } // create the main function that will be run. /* eslint-disable indent */ fn = ['function ' + name + '(_documents, _globals, _inputs, _faker, _chance, _document_index, _require) {', // indent each line and create a string fn.split('\n').map(function (line) { return ' ' + line; }).filter(Boolean).join('\n'), ' return __result.apply(this, [].slice.call(arguments));', '}'].join('\n'); /* eslint-enable indent */ try { (0, _lodash.set)(model, function_path, new Function('require', 'process', 'return ' + fn)(require, process)); // eslint-disable-line no-new-func } catch (e) { throw new Error('Function Error in model \'' + model.name + '\', for property: ' + function_path + ', Reason: ' + e.message); } }); } /// @name parseModelReferences /// @description /// searches the model for any '$ref' values that are pointing to definitions, /// sub_models, etc. and copies the reference to the schema /// @arg {object} model - The model to update function parseModelReferences(model) { var pattern = /\.(schema|items).\$ref$/; // sort the array so definitions come first before properties, this allows definitions to have definitions var paths = utils.objectSearch(model, pattern).sort(); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator3.default)(paths), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var ref = _step.value; var set_location = ref.replace(pattern, ''); if (ref.indexOf('.items.') !== -1) { set_location += '.items'; } var original_property = (0, _lodash.get)(model, set_location); var get_location = (0, _lodash.get)(model, ref).replace(/^#\//, '').replace('/', '.'); var updated_property = _toJs2.default.extend(_toJs2.default.clone(original_property), (0, _lodash.get)(model, get_location)); (0, _lodash.set)(model, set_location, updated_property); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } /// @name parseModelTypes /// @description /// Searches the model for any properties or items and makes /// sure the default types exist /// @arg {object} model - The model to update function parseModelTypes(model) { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = (0, _getIterator3.default)(utils.objectSearch(model, /.*properties\.[^.]+(\.items)?$/)), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var type_path = _step2.value; var property = (0, _lodash.get)(model, type_path); // make sure there is a type property set if (property.type == null) { property.type = 'null'; (0, _lodash.set)(model, type_path, property); } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } /// @name parseModelTypes /// @description /// Sets any model defaults that are not defined /// @arg {object} model - The model to update function parseModelDefaults(model) { // make sure it has the defaults for min, max, count model.data = _toJs2.default.extend({ min: 0, max: 0, count: 0 }, model.data); // find properties or items that do not have a data block and assign it var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = (0, _getIterator3.default)(utils.objectSearch(model, /^(.*properties\.[^.]+)$/)), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var data_path = _step3.value; var property = (0, _lodash.get)(model, data_path) || {}; // if it's an array and has items ensure it has defaults if (property.type === 'array' && property.items) { property.items = _toJs2.default.extend({ data: { min: 0, max: 0, count: 0 } }, property.items); } else { property = _toJs2.default.extend({ data: {} }, property); } (0, _lodash.set)(model, data_path, property); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } /// @name parseModelCount /// @description Determins the total number of documents to run /// @arg {object} model - The model to update /// @arg {undefined, null, number} count - The count to override the model settings function parseModelCount(model, count) { var value = _toJs2.default.number(count); var data = model.data; if (!value) { if (data.count > 0) { value = data.count; } else if (!!data.min && !!data.max) { value = _toJs2.default.random(data.min, data.max); } } // if count is null or 0 then set it to 1 if (!value) { value = 1; } model.data.count = value; } /// @name parseModelSeed /// @description Resolves the seed that was passed in /// @arg {object} model - The model to update /// @arg {undefined, null, number, string} seed - The seed to override the model settings /// @note {2} - The resolved seed will either be null or a number since faker requires the seed to be a number function parseModelSeed(model, seed) { model.seed = !!seed ? seed : model.seed; if (typeof model.seed === 'string') { seed = ''; var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = (0, _getIterator3.default)(model.seed), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var char = _step4.value; seed += char.charCodeAt(0); } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } model.seed = parseInt(seed); } } /// @name resolveDependenciesOrder /// @description Resolves the dependency order that file models need to run in. /// @arg {array} models [[]] - The models to prioritize /// @returns {array} - The models are returned in order with all the models that don't have dependencies first function resolveDependenciesOrder() { var models = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; if (models.length <= 1) { return models; } var resolver = new _dependencyResolver2.default(); var order = {}; // mode models that don't have dependencies up to be first models = models.sort(function (a, b) { return !b.data.dependencies.length && !!a.data.dependencies.length ? 1 : 0; }); var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = (0, _getIterator3.default)(_toJs2.default.entries(models)), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var _step5$value = (0, _slicedToArray3.default)(_step5.value, 2), i = _step5$value[0], _step5$value$ = _step5$value[1], file = _step5$value$.file, data = _step5$value$.data; order[file] = i; resolver.add(file); var dependencies = _toJs2.default.array(data && data.dependencies); var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = (0, _getIterator3.default)(dependencies), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var dependency = _step6.value; resolver.setDependency(file, dependency); } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6.return) { _iterator6.return(); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } return resolver.sort().map(function (file) { return models[order[file]]; }); } /// @name resolveDependenciesOf /// @description Figures out which models use the model as a dependency /// @arg {array} models [[]] - The models to loop over /// @returns {array} - The models are returned with the `dependants` function resolveDependants() { var models = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; return models.map(function (model) { // loop over each model and find out which other models depend on the current model model.dependants = models.reduce(function (prev, next) { if ( // the next file in the loop doesn't matche the current models file model.file !== next.file && // the next models dependencies includes the current models files next.data.dependencies.indexOf(model.file) !== -1) { prev.push(next.file); } return prev; }, []); return model; }); }