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
JavaScript
'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;
});
}