1/* 2 * Jake JavaScript build tool 3 * Copyright 2112 Matthew Eernisse (mde@fleegix.org) 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17*/ 18 19let path = require('path'); 20let fs = require('fs'); 21let existsSync = fs.existsSync; 22let utils = require('./utils'); 23 24// Files like jakelib/foobar.jake.js 25const JAKELIB_FILE_PAT = /\.jake$|\.js$/; 26const SUPPORTED_EXTENSIONS = { 27 'js': null, 28 'coffee': function () { 29 try { 30 let cs = require('coffeescript'); 31 if (typeof cs.register == 'function') { 32 cs.register(); 33 } 34 } 35 catch(e) { 36 throw new Error('You have a CoffeeScript Jakefile, but have not installed CoffeeScript'); 37 } 38 }, 39 'ls': function () { 40 try { 41 require('livescript'); 42 } 43 catch (e) { 44 throw new Error('You have a LiveScript Jakefile, but have not installed LiveScript'); 45 } 46 }, 47 'ts': function () { 48 try { 49 require('ts-node/register/transpile-only'); 50 } 51 catch (e) { 52 throw new Error('You have a TypeScript Jakefile, but have not installed TypeScript and ts-node'); 53 } 54 } 55}; 56const IMPLICIT_JAKEFILE_NAMES = [ 57 'Jakefile', 58 'Gulpfile' 59]; 60 61let Loader = function () { 62 // Load a Jakefile, running the code inside -- this may result in 63 // tasks getting defined using the original Jake API, e.g., 64 // `task('foo' ['bar', 'baz']);`, or can also auto-create tasks 65 // from any functions exported from the file 66 function loadFile(filePath) { 67 let exported = require(filePath); 68 for (let [key, value] of Object.entries(exported)) { 69 let t; 70 if (typeof value == 'function') { 71 t = jake.task(key, value); 72 t.description = '(Exported function)'; 73 } 74 } 75 } 76 77 function fileExists(name) { 78 let nameWithExt = null; 79 // Support no file extension as well 80 let exts = Object.keys(SUPPORTED_EXTENSIONS).concat(['']); 81 exts.some((ext) => { 82 let fname = ext ? `${name}.${ext}` : name; 83 if (existsSync(fname)) { 84 nameWithExt = fname; 85 return true; 86 } 87 }); 88 return nameWithExt; 89 } 90 91 // Recursive 92 function findImplicitJakefile() { 93 let cwd = process.cwd(); 94 let names = IMPLICIT_JAKEFILE_NAMES; 95 let found = null; 96 names.some((name) => { 97 let n; 98 // Prefer all-lowercase 99 n = name.toLowerCase(); 100 if ((found = fileExists(n))) { 101 return found; 102 } 103 // Check mixed-case as well 104 n = name; 105 if ((found = fileExists(n))) { 106 return found; 107 } 108 }); 109 if (found) { 110 return found; 111 } 112 else { 113 process.chdir(".."); 114 // If we've walked all the way up the directory tree, 115 // bail out with no result 116 if (cwd === process.cwd()) { 117 return null; 118 } 119 return findImplicitJakefile(); 120 } 121 } 122 123 this.loadFile = function (fileSpecified) { 124 let jakefile; 125 let origCwd = process.cwd(); 126 127 if (fileSpecified) { 128 if (existsSync(fileSpecified)) { 129 jakefile = fileSpecified; 130 } 131 } 132 else { 133 jakefile = findImplicitJakefile(); 134 } 135 136 if (jakefile) { 137 let ext = jakefile.split('.')[1]; 138 let loaderFunc = SUPPORTED_EXTENSIONS[ext]; 139 loaderFunc && loaderFunc(); 140 141 loadFile(utils.file.absolutize(jakefile)); 142 return true; 143 } 144 else { 145 if (!fileSpecified) { 146 // Restore the working directory on failure 147 process.chdir(origCwd); 148 } 149 return false; 150 } 151 }; 152 153 this.loadDirectory = function (d) { 154 let dirname = d || 'jakelib'; 155 let dirlist; 156 dirname = utils.file.absolutize(dirname); 157 if (existsSync(dirname)) { 158 dirlist = fs.readdirSync(dirname); 159 dirlist.forEach(function (filePath) { 160 if (JAKELIB_FILE_PAT.test(filePath)) { 161 loadFile(path.join(dirname, filePath)); 162 } 163 }); 164 return true; 165 } 166 return false; 167 }; 168 169}; 170 171module.exports = function () { 172 return new Loader(); 173}; 174