1'use strict'; 2 3const _ = require('lodash'); 4const async = require('async'); 5const glob = require('glob'); 6const path = require('path'); 7 8const file = require('../common/file'); 9const mapping = require('../common/mapping'); 10const util = require('../common/util'); 11 12const templatePath = path.join(__dirname, 'template/modules'); 13const template = file.globTemplate(path.join(templatePath, '*.jst')); 14 15const aryMethods = _.union( 16 mapping.aryMethod[1], 17 mapping.aryMethod[2], 18 mapping.aryMethod[3], 19 mapping.aryMethod[4] 20); 21 22const categories = [ 23 'array', 24 'collection', 25 'date', 26 'function', 27 'lang', 28 'math', 29 'number', 30 'object', 31 'seq', 32 'string', 33 'util' 34]; 35 36const ignored = [ 37 '_*.js', 38 'core.js', 39 'core.min.js', 40 'fp.js', 41 'index.js', 42 'lodash.js', 43 'lodash.min.js' 44]; 45 46/** 47 * Checks if `name` is a method alias. 48 * 49 * @private 50 * @param {string} name The name to check. 51 * @returns {boolean} Returns `true` if `name` is a method alias, else `false`. 52 */ 53function isAlias(name) { 54 return _.has(mapping.aliasToReal, name); 55} 56 57/** 58 * Checks if `name` is a category name. 59 * 60 * @private 61 * @param {string} name The name to check. 62 * @returns {boolean} Returns `true` if `name` is a category name, else `false`. 63 */ 64function isCategory(name) { 65 return _.includes(categories, name); 66} 67 68/** 69 * Checks if `name` belongs to a method that's passed thru and not wrapped. 70 * 71 * @private 72 * @param {string} name The name to check. 73 * @returns {boolean} Returns `true` if `name` is of a pass thru method, 74 * else `false`. 75 */ 76function isThru(name) { 77 return !_.includes(aryMethods, name); 78} 79 80/** 81 * Gets metadata for `func`. 82 * 83 * @private 84 * @param {Function} func The function to query. 85 * @returns {*} Returns the metadata for `func`. 86 */ 87function getTemplate(moduleName) { 88 const data = { 89 'name': _.get(mapping.aliasToReal, moduleName, moduleName), 90 'mapping': mapping 91 }; 92 93 if (isAlias(moduleName)) { 94 return template.alias(data); 95 } 96 if (isCategory(moduleName)) { 97 return template.category(data); 98 } 99 if (isThru(moduleName)) { 100 return template.thru(data); 101 } 102 return template.module(data); 103} 104 105/*----------------------------------------------------------------------------*/ 106 107/** 108 * Creates FP modules at the `target` path. 109 * 110 * @private 111 * @param {string} target The output directory path. 112 */ 113function build(target) { 114 target = path.resolve(target); 115 116 const fpPath = path.join(target, 'fp'); 117 118 // Glob existing lodash module paths. 119 const modulePaths = glob.sync(path.join(target, '*.js'), { 120 'nodir': true, 121 'ignore': ignored.map(filename => { 122 return path.join(target, filename); 123 }) 124 }); 125 126 // Add FP alias and remapped module paths. 127 _.each([mapping.aliasToReal, mapping.remap], data => { 128 _.forOwn(data, (realName, alias) => { 129 const modulePath = path.join(target, alias + '.js'); 130 if (!_.includes(modulePaths, modulePath)) { 131 modulePaths.push(modulePath); 132 } 133 }); 134 }); 135 136 const actions = modulePaths.map(modulePath => { 137 const moduleName = path.basename(modulePath, '.js'); 138 return file.write(path.join(fpPath, moduleName + '.js'), getTemplate(moduleName)); 139 }); 140 141 actions.unshift(file.copy(path.join(__dirname, '../../fp'), fpPath)); 142 actions.push(file.write(path.join(fpPath, '_falseOptions.js'), template._falseOptions())); 143 actions.push(file.write(path.join(fpPath, '_util.js'), template._util())); 144 actions.push(file.write(path.join(target, 'fp.js'), template.fp())); 145 actions.push(file.write(path.join(fpPath, 'convert.js'), template.convert())); 146 147 async.series(actions, util.pitch); 148} 149 150build(_.last(process.argv)); 151