1 | ;
|
2 | var task_utils_1 = require("./task.utils");
|
3 | var fs_1 = require("fs");
|
4 | var path_1 = require("path");
|
5 | var fs_2 = require("fs");
|
6 | var path_2 = require("path");
|
7 | var fs_3 = require("fs");
|
8 | var Rx = require("rx");
|
9 | var path_3 = require("path");
|
10 | var fs_4 = require("fs");
|
11 | var crypto_1 = require("crypto");
|
12 | var fs_5 = require("fs");
|
13 | var hd = require("hash-dir");
|
14 | var hashDirAsObservable = Rx.Observable.fromNodeCallback(hd);
|
15 | var hashFileAsObservable = Rx.Observable.fromNodeCallback(hashFile);
|
16 | var lstatAsObservable = Rx.Observable.fromNodeCallback(fs_5.lstat);
|
17 | var _ = require("../lodash.custom");
|
18 | // todo windows support for .bat files etc
|
19 | var supportedTaskFileExtensions = [".js", ".sh"];
|
20 | /**
|
21 | * Try to auto-load configuration files
|
22 | * from the users CWD
|
23 | */
|
24 | function retrieveDefaultInputFiles(config) {
|
25 | var defaultConfigFiles = ["crossbow.yaml", "crossbow.js", "crossbow.yml", "crossbow.json"];
|
26 | return readInputFiles(defaultConfigFiles, config.cwd);
|
27 | }
|
28 | exports.retrieveDefaultInputFiles = retrieveDefaultInputFiles;
|
29 | /**
|
30 | * Try to load cbfiles (like gulp) from the users
|
31 | * working directory
|
32 | * @param config
|
33 | * @returns {InputFiles}
|
34 | */
|
35 | function retrieveCBFiles(config) {
|
36 | var defaultCBFiles = ["cbfile.js", "crossbowfile.js"];
|
37 | var maybes = (function () {
|
38 | if (config.cbfile) {
|
39 | return [config.cbfile];
|
40 | }
|
41 | return defaultCBFiles;
|
42 | })();
|
43 | return readInputFiles(maybes, config.cwd);
|
44 | }
|
45 | exports.retrieveCBFiles = retrieveCBFiles;
|
46 | /**
|
47 | * Try to retrieve input files from disk.
|
48 | * This is different from regular file reading as
|
49 | * we deliver errors with context
|
50 | */
|
51 | function readInputFiles(paths, cwd) {
|
52 | /**
|
53 | * Get files that exist on disk
|
54 | * @type {ExternalFile[]}
|
55 | */
|
56 | var inputFiles = readFilesFromDisk(paths, cwd);
|
57 | /**
|
58 | * Add parsed input keys to them
|
59 | * @type {}
|
60 | */
|
61 | var inputs = inputFiles.map(function (inputFile) {
|
62 | /**
|
63 | * If the file does not exist, change the error to be an InputFileNotFound error
|
64 | * as this will allow more descriptive logging when needed
|
65 | */
|
66 | if (inputFile.errors.length) {
|
67 | return _.assign({}, inputFile, {
|
68 | // here there may be any types of file error,
|
69 | // but we only care that was an error, and normalise it
|
70 | // here for logging. We can added nice per-error messages later.
|
71 | errors: [{ type: task_utils_1.InputErrorTypes.InputFileNotFound }],
|
72 | input: undefined
|
73 | });
|
74 | }
|
75 | /**
|
76 | * If the input file was yaml, load it & translate to JS
|
77 | */
|
78 | if (inputFile.parsed.ext.match(/ya?ml$/i)) {
|
79 | var yml = require("js-yaml");
|
80 | try {
|
81 | return _.assign(inputFile, {
|
82 | input: yml.safeLoad(fs_1.readFileSync(inputFile.resolved, "utf8"))
|
83 | });
|
84 | }
|
85 | catch (e) {
|
86 | return _.assign(inputFile, {
|
87 | input: undefined,
|
88 | errors: [{ type: task_utils_1.InputErrorTypes.InvalidYaml, error: e }]
|
89 | });
|
90 | }
|
91 | }
|
92 | /**
|
93 | * Finally assume a JS/JSON file and 'require' it as normal
|
94 | */
|
95 | try {
|
96 | return _.assign({}, inputFile, {
|
97 | input: require(inputFile.resolved)
|
98 | });
|
99 | }
|
100 | catch (e) {
|
101 | return _.assign(inputFile, {
|
102 | input: undefined,
|
103 | errors: [{ type: task_utils_1.InputErrorTypes.InvalidInput, error: e }]
|
104 | });
|
105 | }
|
106 | });
|
107 | return {
|
108 | all: inputs,
|
109 | valid: inputs.filter(function (x) { return x.errors.length === 0; }),
|
110 | invalid: inputs.filter(function (x) { return x.errors.length > 0; })
|
111 | };
|
112 | }
|
113 | exports.readInputFiles = readInputFiles;
|
114 | function readFileFromDiskWithContent(path, cwd) {
|
115 | var files = readFilesFromDisk([path], cwd);
|
116 | return files
|
117 | .map(function (x) {
|
118 | if (x.errors.length)
|
119 | return x;
|
120 | x.content = fs_1.readFileSync(x.resolved, "utf8");
|
121 | return x;
|
122 | })[0];
|
123 | }
|
124 | exports.readFileFromDiskWithContent = readFileFromDiskWithContent;
|
125 | function readFilesFromDiskWithContent(paths, cwd) {
|
126 | var files = readFilesFromDisk(paths, cwd);
|
127 | return files
|
128 | .map(function (x) {
|
129 | if (x.errors.length)
|
130 | return x;
|
131 | x.content = fs_1.readFileSync(x.resolved, "utf8");
|
132 | return x;
|
133 | });
|
134 | }
|
135 | exports.readFilesFromDiskWithContent = readFilesFromDiskWithContent;
|
136 | function readFileContent(file) {
|
137 | return fs_1.readFileSync(file.resolved, "utf8");
|
138 | }
|
139 | exports.readFileContent = readFileContent;
|
140 | function writeFileToDisk(file, content) {
|
141 | var mkdirp = require("mkdirp").sync;
|
142 | mkdirp(path_3.dirname(file.resolved));
|
143 | fs_1.writeFileSync(file.resolved, content);
|
144 | }
|
145 | exports.writeFileToDisk = writeFileToDisk;
|
146 | function getStubFileWithContent(path, cwd) {
|
147 | var file = getStubFile(path, cwd);
|
148 | file.content = "";
|
149 | return file;
|
150 | }
|
151 | exports.getStubFileWithContent = getStubFileWithContent;
|
152 | function readOrCreateJsonFile(path, cwd) {
|
153 | var existing = readFilesFromDiskWithContent([path], cwd)[0];
|
154 | if (existing.errors.length) {
|
155 | if (existing.errors[0].type === task_utils_1.InputErrorTypes.FileNotFound) {
|
156 | var stub = getStubFileWithContent(path, cwd);
|
157 | stub.content = "{}";
|
158 | stub.data = JSON.parse(stub.content);
|
159 | return stub;
|
160 | }
|
161 | }
|
162 | else {
|
163 | try {
|
164 | existing.data = JSON.parse(existing.content);
|
165 | }
|
166 | catch (e) {
|
167 | existing.data = {};
|
168 | }
|
169 | }
|
170 | return existing;
|
171 | }
|
172 | exports.readOrCreateJsonFile = readOrCreateJsonFile;
|
173 | function getStubFile(path, cwd) {
|
174 | var resolved = path_1.resolve(cwd, path);
|
175 | return {
|
176 | errors: [],
|
177 | rawInput: path,
|
178 | resolved: resolved,
|
179 | parsed: path_1.parse(resolved),
|
180 | relative: path_1.relative(cwd, resolved)
|
181 | };
|
182 | }
|
183 | exports.getStubFile = getStubFile;
|
184 | /**
|
185 | * Take an array of paths and return file info + errors if they don't exist
|
186 | * @param paths
|
187 | * @param cwd
|
188 | * @returns {ExternalFile[]}
|
189 | */
|
190 | function readFilesFromDisk(paths, cwd) {
|
191 | return paths
|
192 | .map(String)
|
193 | .map(function (x) { return getStubFile(x, cwd); })
|
194 | .map(function (incoming) {
|
195 | var resolved = incoming.resolved;
|
196 | /**
|
197 | * If the path does not exist, it's a FileNotFound error
|
198 | */
|
199 | if (!fs_1.existsSync(resolved)) {
|
200 | return _.assign(incoming, {
|
201 | errors: [{ type: task_utils_1.InputErrorTypes.FileNotFound }]
|
202 | });
|
203 | }
|
204 | /**
|
205 | * Not check it's a file & NOT a dir
|
206 | * @type {Stats}
|
207 | */
|
208 | var stat = fs_2.statSync(resolved);
|
209 | if (!stat.isFile()) {
|
210 | return _.assign(incoming, {
|
211 | errors: [{ type: task_utils_1.InputErrorTypes.NotAFile }],
|
212 | });
|
213 | }
|
214 | /**
|
215 | * At this point the file DOES exist
|
216 | */
|
217 | return incoming;
|
218 | });
|
219 | }
|
220 | exports.readFilesFromDisk = readFilesFromDisk;
|
221 | /**
|
222 | * Attempt to use the LOCALLY installed crossbow version
|
223 | * first, this will ensure anything registered with .task etc
|
224 | * can be picked up by global installs too.
|
225 | * @param config
|
226 | * @returns {InputFiles}
|
227 | */
|
228 | function getRequirePaths(config) {
|
229 | var local = path_2.join("node_modules", "crossbow", "dist", "public", "create.js");
|
230 | var global = path_2.join(__dirname, "public", "create.js");
|
231 | return readInputFiles([local, global], config.cwd);
|
232 | }
|
233 | exports.getRequirePaths = getRequirePaths;
|
234 | function getExternalFiles(dirpaths, cwd) {
|
235 | return dirpaths
|
236 | .map(function (dirpath) {
|
237 | return path_1.resolve(cwd, dirpath);
|
238 | })
|
239 | .filter(fs_1.existsSync)
|
240 | .reduce(function (acc, dirPath) {
|
241 | return acc.concat(fs_3.readdirSync(dirPath).map(function (filepath) {
|
242 | var resolved = path_2.join(dirPath, filepath);
|
243 | var parsed = path_1.parse(resolved);
|
244 | var output = {
|
245 | rawInput: filepath,
|
246 | resolved: resolved,
|
247 | relative: path_1.relative(cwd, resolved),
|
248 | parsed: parsed,
|
249 | errors: []
|
250 | };
|
251 | return output;
|
252 | }));
|
253 | }, []);
|
254 | }
|
255 | exports.getExternalFiles = getExternalFiles;
|
256 | function getPossibleTasksFromDirectories(dirpaths, cwd) {
|
257 | return getExternalFiles(dirpaths, cwd)
|
258 | .filter(function (x) { return supportedTaskFileExtensions.indexOf(x.parsed.ext) > -1; })
|
259 | .map(function (x) {
|
260 | return x.relative;
|
261 | });
|
262 | }
|
263 | exports.getPossibleTasksFromDirectories = getPossibleTasksFromDirectories;
|
264 | var HashDirErrorTypes;
|
265 | (function (HashDirErrorTypes) {
|
266 | HashDirErrorTypes[HashDirErrorTypes["HashNotADirectory"] = "HashNotADirectory"] = "HashNotADirectory";
|
267 | HashDirErrorTypes[HashDirErrorTypes["HashPathNotFound"] = "HashPathNotFound"] = "HashPathNotFound";
|
268 | })(HashDirErrorTypes = exports.HashDirErrorTypes || (exports.HashDirErrorTypes = {}));
|
269 | function hashItems(dirs, cwd, existingHashes) {
|
270 | return Rx.Observable
|
271 | .from(dirs)
|
272 | .map(function (x) {
|
273 | return {
|
274 | userInput: x,
|
275 | pathObj: getStubFile(x, cwd)
|
276 | };
|
277 | })
|
278 | .distinct(function (x) { return x.pathObj.resolved; })
|
279 | .flatMap(hashFileOrDir)
|
280 | .toArray()
|
281 | .map(function (x) {
|
282 | return markHashes(x, existingHashes);
|
283 | });
|
284 | }
|
285 | exports.hashItems = hashItems;
|
286 | function hashFile(filepath, fn) {
|
287 | var hash = crypto_1.createHash("sha256");
|
288 | fs_4.createReadStream(filepath)
|
289 | .on("data", function (chunk) {
|
290 | hash.update(chunk);
|
291 | })
|
292 | .on("end", function () {
|
293 | fn(null, hash.digest("hex"));
|
294 | })
|
295 | .on("error", fn);
|
296 | }
|
297 | function hashFileOrDir(input) {
|
298 | return lstatAsObservable(input.pathObj.resolved).flatMap(function (stats) {
|
299 | if (stats.isDirectory()) {
|
300 | return hashDirAsObservable(input.pathObj.resolved).map(function (tree) {
|
301 | return {
|
302 | userInput: input.userInput,
|
303 | resolved: input.pathObj.resolved,
|
304 | hash: tree.hash
|
305 | };
|
306 | });
|
307 | }
|
308 | if (stats.isFile()) {
|
309 | return hashFileAsObservable(input.pathObj.resolved).map(function (hash) {
|
310 | return {
|
311 | userInput: input.userInput,
|
312 | resolved: input.pathObj.resolved,
|
313 | hash: hash
|
314 | };
|
315 | });
|
316 | }
|
317 | return Rx.Observable.empty();
|
318 | });
|
319 | }
|
320 | function markHashes(newHashes, existingHashes) {
|
321 | var newHashPaths = newHashes.map(function (x) { return x.resolved; });
|
322 | var markedHashes = newHashes.map(function (newHash) {
|
323 | var match = existingHashes.filter(function (x) { return x.resolved === newHash.resolved; });
|
324 | newHash.changed = (function () {
|
325 | if (match.length) {
|
326 | return match[0].hash !== newHash.hash;
|
327 | }
|
328 | return true; // return true by default so that new entries always run
|
329 | })();
|
330 | return newHash;
|
331 | });
|
332 | var otherHashes = existingHashes.filter(function (hash) {
|
333 | return newHashPaths.indexOf(hash.resolved) === -1;
|
334 | });
|
335 | var output = otherHashes.concat(newHashes).filter(Boolean);
|
336 | return {
|
337 | output: output,
|
338 | markedHashes: markedHashes
|
339 | };
|
340 | }
|
341 | /**
|
342 | * Thanks to https://github.com/motdotla/dotenv
|
343 | * @param src
|
344 | * @returns {{}}
|
345 | */
|
346 | function parseEnv(src) {
|
347 | var obj = {};
|
348 | // convert Buffers before splitting into lines and processing
|
349 | src.toString().split('\n').forEach(function (line) {
|
350 | // matching "KEY' and 'VAL' in 'KEY=VAL'
|
351 | var keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
|
352 | // matched?
|
353 | if (keyValueArr != null) {
|
354 | var key = keyValueArr[1];
|
355 | // default undefined or missing values to empty string
|
356 | var value = keyValueArr[2] ? keyValueArr[2] : '';
|
357 | // expand newlines in quoted values
|
358 | var len = value ? value.length : 0;
|
359 | if (len > 0 && value.charAt(0) === '"' && value.charAt(len - 1) === '"') {
|
360 | value = value.replace(/\\n/gm, '\n');
|
361 | }
|
362 | // remove any surrounding quotes and extra spaces
|
363 | value = value.replace(/(^['"]|['"]$)/g, '').trim();
|
364 | obj[key] = value;
|
365 | }
|
366 | });
|
367 | return obj;
|
368 | }
|
369 | exports.parseEnv = parseEnv;
|
370 | exports.Right = function (x) { return ({
|
371 | chain: function (f) { return f(x); },
|
372 | map: function (f) { return exports.Right(f(x)); },
|
373 | fold: function (f, g) { return g(x); },
|
374 | inspect: function () { return "Right(" + x + ")"; }
|
375 | }); };
|
376 | exports.Left = function (x) { return ({
|
377 | chain: function (f) { return exports.Left(x); },
|
378 | map: function (f) { return exports.Left(x); },
|
379 | fold: function (f, g) { return f(x); },
|
380 | inspect: function () { return "Left(" + x + ")"; }
|
381 | }); };
|
382 | exports.tryCatch = function (f) {
|
383 | try {
|
384 | return exports.Right(f());
|
385 | }
|
386 | catch (e) {
|
387 | return exports.Left(e);
|
388 | }
|
389 | };
|
390 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9maWxlLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSwyQ0FBcUU7QUFDckUseUJBQTJEO0FBQzNELDZCQUE4QztBQUc5Qyx5QkFBNEI7QUFDNUIsNkJBQTBCO0FBQzFCLHlCQUErQjtBQUMvQix1QkFBMEI7QUFDMUIsNkJBQTZCO0FBQzdCLHlCQUFvQztBQUNwQyxpQ0FBa0M7QUFDbEMseUJBQWdDO0FBRWhDLElBQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUMvQixJQUFNLG1CQUFtQixHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDL0QsSUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3RFLElBQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFLLENBQUMsQ0FBQztBQUVoRSxJQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUV0QywwQ0FBMEM7QUFDMUMsSUFBTSwyQkFBMkIsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQXVCbkQ7OztHQUdHO0FBQ0gsbUNBQTBDLE1BQTZCO0lBQ25FLElBQU0sa0JBQWtCLEdBQUcsQ0FBQyxlQUFlLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUM3RixNQUFNLENBQUMsY0FBYyxDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBSEQsOERBR0M7QUFFRDs7Ozs7R0FLRztBQUNILHlCQUFnQyxNQUE2QjtJQUN6RCxJQUFNLGNBQWMsR0FBRyxDQUFDLFdBQVcsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lB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 |
\ | No newline at end of file |