UNPKG

avifors

Version:

A MDE tool that generates code from a YAML definition of your app domain model.

263 lines (213 loc) 9.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _nunjucks = require('nunjucks'); var _nunjucks2 = _interopRequireDefault(_nunjucks); var _glob = require('glob'); var _glob2 = _interopRequireDefault(_glob); var _checkTypes = require('check-types'); var _checkTypes2 = _interopRequireDefault(_checkTypes); var _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk); var _YamlHelper = require('./tools/YamlHelper'); var _YamlHelper2 = _interopRequireDefault(_YamlHelper); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Avifors = function () { function Avifors() { var _this = this; _classCallCheck(this, Avifors); this.generators = []; this.autoGenerators = []; this.autoGeneratorBuilders = []; this.constructors = {}; this.model = null; // will be defined by the model builder var assertArg = function assertArg(value, cond, fnName, msg) { return _this.assert(cond, 'avifors.' + fnName + '(): ' + msg + ', ' + value + ' provided'); }; var emptyDicts = ['command', 'type', 'validator', 'builder']; emptyDicts.forEach(function (i) { return _this._createProperty(i, function (commandName, value) { return assertArg(value, _checkTypes2.default.function(value), commandName, 'the ' + i + ' must be a function'); }); }); this._createProperty('query', function (commandName, value) { assertArg(value, _checkTypes2.default.nonEmptyObject(value), commandName, 'the query must be an object'); assertArg(value, _checkTypes2.default.maybe.string(value.description), commandName, 'query.description must be a string'); assertArg(value, _checkTypes2.default.maybe.array(value.arguments), commandName, 'query.arguments must be an array'); assertArg(value, _checkTypes2.default.function(value.resolve), commandName, 'query.resolve must be a function'); }, 'queries'); this.nunjucks = _nunjucks2.default.configure({ autoescape: false, trimBlocks: true, lstripBlocks: true }); this.helpers = { printYaml: function printYaml(obj) { return console.log(new _YamlHelper2.default().print(obj)); } }; } /** * Set a generator */ _createClass(Avifors, [{ key: 'setGenerator', value: function setGenerator(name, config) { var _this2 = this; this._checkSetGeneratorArguments(name, config); if (_checkTypes2.default.array(config.outputs)) { var outputs = config.outputs.map(function (i) { return typeof i === 'function' ? i : function (args) { return { path: _this2.nunjucks.renderString(i.path, args), template: i.template }; }; }); config.outputs = function () { return outputs; }; } config.arguments = this.types.map(config.arguments); this.generators.push(_extends({ name: name }, config)); } }, { key: '_checkSetGeneratorArguments', value: function _checkSetGeneratorArguments(name, config) { var _this3 = this; var badCallExceptionMessage = function badCallExceptionMessage(msg) { return _chalk2.default.cyan('Avifors.setGenerator(\'' + name + '\', config):') + ' ' + msg; }; this.assert(_checkTypes2.default.nonEmptyString(name), badCallExceptionMessage('Generator name must be an non empty string')); this.assert(_checkTypes2.default.nonEmptyObject(config), badCallExceptionMessage('config must be an non empty object and contain at least \'arguments\' and \'outputs\'')); this.assert(_checkTypes2.default.maybe.nonEmptyString(config.list), badCallExceptionMessage('config.list must be a non empty string')); this.assert(_checkTypes2.default.maybe.nonEmptyString(config.key), badCallExceptionMessage('config.key must be a non empty string')); this.assert(_checkTypes2.default.object(config.arguments), badCallExceptionMessage('config.key must be a non empty object')); if (_checkTypes2.default.array(config.outputs)) { config.outputs.forEach(function (i, index) { return _this3.assert(_checkTypes2.default.function(i) || _checkTypes2.default.object(i) && _checkTypes2.default.nonEmptyString(i.path) && _checkTypes2.default.nonEmptyString(i.template), badCallExceptionMessage('config.key[' + index + '] must be an object containing non empty strings \'path\' and \'template\' or a function returning the above object')); }); } else { this.assert(_checkTypes2.default.function(config.outputs), badCallExceptionMessage('config.outputs must be an array or a function returning an array of outputs')); } } /** * Get the generator defined with given name, and say if given name refers to a list of items * @return [generator dict, list bool] */ }, { key: 'getGenerator', value: function getGenerator(name) { var isList = false; var generator = this.generators.find(function (gen) { return gen.name === name; }); if (generator !== undefined) { return [generator, isList]; } isList = true; generator = this.generators.find(function (gen) { return gen.list === name; }); if (generator !== undefined) { return [generator, isList]; } throw 'Generator ' + name + ' not found.'; } /** * Add a generator that will be executed without model definition * @param builder: model => [{path: string, template: string, variables: {}}] */ }, { key: 'addAutoGenerator', value: function addAutoGenerator(builder) { this.assert(_checkTypes2.default.function(builder), 'avifors.addAutoGenerator(builder): builder must be a function, ' + builder + ' provided'); this.autoGeneratorBuilders.push(builder); } /** * Set the model once it's built */ }, { key: 'setModel', value: function setModel(model) { this.model = model; this.nunjucks.addGlobal('model', model); this.autoGenerators = this.autoGeneratorBuilders.map(function (i) { return i(model); }); } /** * Quick way to assert a predicate */ }, { key: 'assert', value: function assert(predicate, message) { if (!predicate) { throw message; } } /** * Validate given item using given validators */ }, { key: 'validate', value: function validate(validators, item, path) { validators.forEach(function (v) { return v.validate(item, path); }); } /** * Load plugins at given paths */ }, { key: 'loadPlugins', value: function loadPlugins(paths) { var _this4 = this; this.assert(_checkTypes2.default.array(paths), 'loadPlugins(paths): paths must be an array of strings, ' + paths + ' provided'); paths.forEach(function (i, index) { return _this4.assert(_checkTypes2.default.string(i), 'loadPlugins(paths): every path must be a string, ' + i + ' provided'); }); paths.map(function (path) { return _glob2.default.sync(path, { nodir: true, absolute: true }); }) // get the list of files matching given pattern .reduce(function (a, b) { return a.concat(b); }) // flatten it to one list .forEach(function (pluginPath) { return require(pluginPath).default(_this4); }); } /** * Create an empty dict property with its getter, setter and hasser * Example: _createProperty('command') => this.commands = {}; this.getCommand(name); this.setCommand(name, command); this.hasCommand(name) */ }, { key: '_createProperty', value: function _createProperty(field) { var _this5 = this; var validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var pluralForm = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var uppercased = field.charAt(0).toUpperCase() + field.substr(1); var plural = pluralForm ? pluralForm : field + 's'; this[plural] = {}; this['set' + uppercased] = function (name, value) { validator('set' + uppercased, value); _this5[plural][name] = value; }; this['get' + uppercased] = function (name) { if (!_this5['has' + uppercased](name)) { throw uppercased + ' ' + name + ' does not exist.'; } return _this5[plural][name]; }; this['has' + uppercased] = function (name) { return _this5[plural][name] !== undefined; }; } }]); return Avifors; }(); exports.default = Avifors;