UNPKG

fakeit-facet

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.

998 lines (762 loc) 39.4 kB
"use strict"; var _typeof = require("@babel/runtime-corejs3/helpers/typeof"); var _forEachInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/for-each"); var _findInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/find"); var _mapInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/map"); var _Reflect$construct = require("@babel/runtime-corejs3/core-js-stable/reflect/construct"); var _sliceInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/slice"); var _Array$from = require("@babel/runtime-corejs3/core-js-stable/array/from"); var _Symbol = require("@babel/runtime-corejs3/core-js-stable/symbol"); var _getIteratorMethod = require("@babel/runtime-corejs3/core-js/get-iterator-method"); var _Array$isArray = require("@babel/runtime-corejs3/core-js-stable/array/is-array"); var _WeakMap = require("@babel/runtime-corejs3/core-js-stable/weak-map"); var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property"); var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"); var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); _Object$defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; exports.parseModelCount = parseModelCount; exports.parseModelDefaults = parseModelDefaults; exports.parseModelFunctions = parseModelFunctions; exports.parseModelInputs = parseModelInputs; exports.parseModelReferences = parseModelReferences; exports.parseModelSeed = parseModelSeed; exports.parseModelTypes = parseModelTypes; exports.resolveDependants = resolveDependants; exports.resolveDependenciesOrder = resolveDependenciesOrder; var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs3/regenerator")); var _reduce = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/reduce")); var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat")); var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes")); var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter")); var _assign = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/assign")); var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each")); var _trim = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/trim")); var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map")); var _sort = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/sort")); var _parseInt2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/parse-int")); var _entries = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/entries")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/asyncToGenerator")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass")); var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/getPrototypeOf")); var _asyncArrayMethods = require("async-array-methods"); var _fsExtraPromisify = _interopRequireDefault(require("fs-extra-promisify")); var _path = _interopRequireDefault(require("path")); var _dependencyResolver = _interopRequireDefault(require("dependency-resolver")); var _lodash = require("lodash"); var _toJs = _interopRequireWildcard(require("to-js")); var _core = require("@babel/core"); var _globby = _interopRequireDefault(require("globby")); var _findRoot = _interopRequireDefault(require("find-root")); var _base = _interopRequireDefault(require("./base")); var utils = _interopRequireWildcard(require("./utils")); function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? _Object$getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { _Object$defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { var _context28; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = _sliceInstanceProperty(_context28 = Object.prototype.toString.call(o)).call(_context28, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /// / /// @name Models /// @page api/models /// / var Models = /*#__PURE__*/function (_Base) { (0, _inherits2["default"])(Models, _Base); var _super = _createSuper(Models); function Models() { var _this; var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; (0, _classCallCheck2["default"])(this, Models); _this = _super.call(this, _toJs["default"].extend({ count: 0, seed: 0, babel_config: '+(.babelrc|package.json)' }, options)); // holds all the inputs that are registerd _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, _createClass2["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 _setup = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { var _this2 = this, _context; var babel_config, file, config; return _regenerator["default"].wrap(function _callee$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: if (!(this.preparing == null)) { _context2.next = 2; break; } return _context2.abrupt("return", this.prepare()); case 2: babel_config = this.options.babel_config; if (_toJs.is.string(babel_config)) { _context2.next = 6; break; } process.nextTick(function () { _this2.prepared = true; }); return _context2.abrupt("return"); case 6: file = (0, _reduce["default"])(_context = [process.cwd(), this.options.root]).call(_context, function (prev, next) { try { return (0, _concat["default"])(prev).call(prev, _path["default"].join((0, _findRoot["default"])(next), babel_config)); } catch (e) { return prev; } }, []); _context2.next = 9; return (0, _globby["default"])(_toJs["default"].unique(file), { dot: true }); case 9: file = _context2.sent; file = file[0]; // eslint-disable-line if (!file) { _context2.next = 17; break; } _context2.next = 14; return _fsExtraPromisify["default"].readJson(file); case 14: config = _context2.sent; if ((0, _includes["default"])(file).call(file, 'package.json')) { config = config.babelConfig || {}; } this.options.babel_config = config; case 17: this.prepared = true; case 18: case "end": return _context2.stop(); } } }, _callee, this); })); function setup() { return _setup.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() { var _context3; this.progress.text = (0, _concat["default"])(_context3 = "Models (".concat(this.models.length, "/")).call(_context3, 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 _context4, _this3 = this; return (0, _filter["default"])(_context4 = _toJs["default"].flatten(files)).call(_context4, function (file) { var _context5; return !!file && /\.(ya?ml)$/i.test(file) && !(0, _includes["default"])(_context5 = _this3.registered_models).call(_context5, file); }); } }, { key: "registerModels", value: function () { var _registerModels = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(models) { var _this4 = this; var dependency, files, _args3 = arguments; return _regenerator["default"].wrap(function _callee3$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: dependency = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : false; this.progress = this.progress || this.spinner('Models').start(); // if models weren't passed in then don't do anything if (models) { _context8.next = 4; break; } return _context8.abrupt("return"); case 4: if (!(this.prepared !== true)) { _context8.next = 8; break; } if (this.preparing == null) { this.prepare(); } _context8.next = 8; return this.preparing; case 8: _context8.t0 = this; _context8.next = 11; return utils.findFiles(this.resolvePaths(models)); case 11: _context8.t1 = _context8.sent; files = _context8.t0.filterModelFiles.call(_context8.t0, _context8.t1); if (files.length) { _context8.next = 17; break; } if (dependency) { _context8.next = 16; break; } throw new Error('No valid model files found.'); case 16: return _context8.abrupt("return"); case 17: _context8.next = 19; return (0, _forEachInstanceProperty2(_asyncArrayMethods))(files, /*#__PURE__*/function () { var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(file) { var _context6; var _model, model; return _regenerator["default"].wrap(function _callee2$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: if (!(0, _includes["default"])(_context6 = _this4.registered_models).call(_context6, file)) { _context7.next = 3; break; } if (!dependency) { _model = (0, _findInstanceProperty(_lodash))(_this4.models, ['file', file]); _model.is_dependency = dependency; } return _context7.abrupt("return"); case 3: // add it to the models _this4.registered_models.push(file); _this4.update(); // read yaml file and convert it to json _context7.t0 = utils.parsers.yaml; _context7.t1 = _toJs["default"]; _context7.next = 9; return _fsExtraPromisify["default"].readFile(file); case 9: _context7.t2 = _context7.sent; _context7.t3 = _context7.t1.string.call(_context7.t1, _context7.t2); _context7.next = 13; return _context7.t0.parse.call(_context7.t0, _context7.t3); case 13: model = _context7.sent; // used for debugging model.file = file; // sets the root of the model so that we can resolve inputs and dependencies later // sets the root of the model so that we can resolve inputs and dependencies later model.root = _path["default"].resolve(_this4.options.root, _path["default"].dirname(model.file)); // used to determine if something is a dependency or not. // 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 */ /* istanbul ignore if : currently hard to test */ if (!model.name) { model.name = _path["default"].basename(file).split('.')[0]; // eslint-disable-line } // validate the model /* istanbul ignore if : currently hard to test */ // validate the model /* istanbul ignore if : currently hard to test */ if (!model.type) { _this4.log('error', new Error("The model ".concat(model.name, " must have a \"type\" property."))); } /* istanbul ignore if : currently hard to test */ /* istanbul ignore if : currently hard to test */ if (!model.key) { _this4.log('error', new Error("The model ".concat(model.name, " must have a \"key\" property."))); } // add the parsed model to the global object should always have a model name _context7.next = 22; return _this4.parseModel(model); case 22: _this4.models.push(model); _this4.update(); case 24: case "end": return _context7.stop(); } } }, _callee2); })); return function (_x2) { return _ref.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 _context8.abrupt("return", this); case 23: case "end": return _context8.stop(); } } }, _callee3, this); })); function registerModels(_x) { return _registerModels.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 _parseModel = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(model) { var inputs, dependencies; return _regenerator["default"].wrap(function _callee4$(_context9) { while (1) { switch (_context9.prev = _context9.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 _context9.t0 = _assign["default"]; _context9.t1 = this.inputs || {}; _context9.next = 14; return inputs; case 14: _context9.t2 = _context9.sent; this.inputs = (0, _context9.t0)(_context9.t1, _context9.t2); _context9.next = 18; return dependencies; case 18: return _context9.abrupt("return", model); case 19: case "end": return _context9.stop(); } } }, _callee4, this); })); function parseModel(_x3) { return _parseModel.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 _parseModelDependencies = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(model) { var files; return _regenerator["default"].wrap(function _callee5$(_context10) { while (1) { switch (_context10.prev = _context10.next) { case 0: if (!(!model.data.dependencies || !model.data.dependencies.length)) { _context10.next = 3; break; } model.data.dependencies = []; return _context10.abrupt("return"); case 3: _context10.t0 = _toJs["default"]; _context10.next = 6; return utils.findFiles(model.data.dependencies); case 6: _context10.t1 = _context10.sent; files = _context10.t0.flatten.call(_context10.t0, _context10.t1); if (files.length) { _context10.next = 11; break; } model.data.dependencies = []; return _context10.abrupt("return"); case 11: _context10.next = 13; return this.registerModels(files, true); case 13: case "end": return _context10.stop(); } } }, _callee5, this); })); function parseModelDependencies(_x4) { return _parseModelDependencies.apply(this, arguments); } return parseModelDependencies; }() }]); return Models; }(_base["default"]); /// @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. exports["default"] = Models; function parseModelInputs(_x5) { return _parseModelInputs.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 function _parseModelInputs() { _parseModelInputs = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(model) { var _context24; var inputs, files; return _regenerator["default"].wrap(function _callee7$(_context27) { while (1) { switch (_context27.prev = _context27.next) { case 0: if (!(!model.data.inputs || !model.data.inputs.length)) { _context27.next = 3; break; } model.data.inputs = []; return _context27.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 _context27.t0 = _filter["default"]; _context27.t1 = _toJs["default"]; _context27.next = 8; return utils.findFiles(model.data.inputs); case 8: _context27.t2 = _context27.sent; _context27.t3 = _context24 = _context27.t1.flatten.call(_context27.t1, _context27.t2); files = (0, _context27.t0)(_context27.t3).call(_context24, function (file) { return !!file && /\.(csv|json|cson|ya?ml|zip)$/i.test(file); }); if (files.length) { _context27.next = 13; break; } throw new Error("No valid input files found for ".concat(model.file)); case 13: _context27.next = 15; return utils.readFiles(files); case 15: files = _context27.sent; _context27.next = 18; return (0, _mapInstanceProperty2(_asyncArrayMethods))(files, /*#__PURE__*/function () { var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(file) { var _context25; var parser; return _regenerator["default"].wrap(function _callee6$(_context26) { while (1) { switch (_context26.prev = _context26.next) { case 0: // get the current parser to use parser = utils.parsers[file.ext.replace(/^\./, '')]; if (parser) { _context26.next = 3; break; } throw new Error((0, _concat["default"])(_context25 = "No valid parser could be found for \"".concat(file.name, ".")).call(_context25, file.type, "\"")); case 3: _context26.next = 5; return parser.parse(file.content); case 5: inputs[file.name] = _context26.sent; return _context26.abrupt("return", file); case 7: case "end": return _context26.stop(); } } }, _callee6); })); return function (_x6) { return _ref2.apply(this, arguments); }; }()); case 18: return _context27.abrupt("return", inputs); case 19: case "end": return _context27.stop(); } } }, _callee7); })); return _parseModelInputs.apply(this, arguments); } 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$/); (0, _forEach["default"])(paths).call(paths, function (function_path) { var _context11, _context12, _context13, _context17, _context18; var name = _toJs["default"].camelCase(function_path); // get the function var fn = (0, _filter["default"])(_context11 = (0, _trim["default"])(_context12 = (0, _lodash.get)(model, function_path)).call(_context12).split('\n')).call(_context11, 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 ".concat(fn[0].replace(/^return\s+/, ''))]; } // indent each line and create a string fn = (0, _filter["default"])(_context13 = (0, _map["default"])(fn).call(fn, function (line) { return " ".concat(line); })).call(_context13, 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".concat(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, _core.transform)(fn, babel_config).code.replace(/^.use strict.;\n+/, ''); } catch (e) { var _context14, _context15, _context16; var file_message = model.file ? " in ".concat(model.file) : ''; e.message = (0, _trim["default"])(_context14 = (0, _concat["default"])(_context15 = (0, _concat["default"])(_context16 = "Failed to transpile ".concat(function_path, " with babel")).call(_context16, file_message, "\n")).call(_context15, e.message)).call(_context14); throw e; } } // create the main function that will be run. /* eslint-disable indent */ fn = ["function ".concat(name, "(_documents, _globals, _inputs, _faker, _chance, _document_index, _require) {"), // indent each line and create a string (0, _filter["default"])(_context17 = (0, _map["default"])(_context18 = fn.split('\n')).call(_context18, function (line) { return " ".concat(line); })).call(_context17, 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 ".concat(fn))(require, process)); // eslint-disable-line no-new-func } catch (e) { var _context19, _context20; throw new Error((0, _concat["default"])(_context19 = (0, _concat["default"])(_context20 = "Function Error in model '".concat(model.name, "', for property: ")).call(_context20, function_path, ", Reason: ")).call(_context19, 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 _context21; var pattern = /\.(schema|items).\$ref$/; // sort the array so definitions come first before properties, this allows definitions to have definitions var paths = (0, _sort["default"])(_context21 = utils.objectSearch(model, pattern)).call(_context21); var _iterator = _createForOfIteratorHelper(paths), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ref = _step.value; var set_location = ref.replace(pattern, ''); if ((0, _includes["default"])(ref).call(ref, '.items.')) { 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 = _toJs["default"].extend(_toJs["default"].clone(original_property), (0, _lodash.get)(model, get_location)); (0, _lodash.set)(model, set_location, updated_property); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } /// @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 _iterator2 = _createForOfIteratorHelper(utils.objectSearch(model, /.*properties\.[^.]+(\.items)?$/)), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { 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) { _iterator2.e(err); } finally { _iterator2.f(); } } /// @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 = _toJs["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 _iterator3 = _createForOfIteratorHelper(utils.objectSearch(model, /^(.*properties\.[^.]+)$/)), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { 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 = _toJs["default"].extend({ data: { min: 0, max: 0, count: 0 } }, property.items); } else { property = _toJs["default"].extend({ data: {} }, property); } (0, _lodash.set)(model, data_path, property); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } /// @name parseModelCount /// @description Determines 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 = _toJs["default"].number(count); var data = model.data; if (!value) { if (data.count > 0) { value = data.count; } else if (!!data.min && !!data.max) { value = _toJs["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 || model.seed; if (typeof model.seed === 'string') { seed = ''; var _iterator4 = _createForOfIteratorHelper(model.seed), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var _char = _step4.value; seed += _char.charCodeAt(0); } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } model.seed = (0, _parseInt2["default"])(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 _context22; var models = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; if (models.length <= 1) { return models; } var resolver = new _dependencyResolver["default"](); var order = {}; function sortByFunction(item) { return item.data.dependencies.length; } models = (0, _lodash.sortBy)(models, [sortByFunction]); var _iterator5 = _createForOfIteratorHelper((0, _entries["default"])(_toJs["default"]).call(_toJs["default"], models)), _step5; try { for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { var _step5$value = (0, _slicedToArray2["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 = _toJs["default"].array(data && data.dependencies); var _iterator6 = _createForOfIteratorHelper(dependencies), _step6; try { for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { var dependency = _step6.value; resolver.setDependency(file, dependency); } } catch (err) { _iterator6.e(err); } finally { _iterator6.f(); } } } catch (err) { _iterator5.e(err); } finally { _iterator5.f(); } return (0, _map["default"])(_context22 = (0, _sort["default"])(resolver).call(resolver)).call(_context22, 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 (0, _map["default"])(models).call(models, function (model) { // loop over each model and find out which other models depend on the current model model.dependants = (0, _reduce["default"])(models).call(models, function (prev, next) { var _context23; 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 && (0, _includes["default"])(_context23 = next.data.dependencies).call(_context23, model.file)) { prev.push(next.file); } return prev; }, []); return model; }); }