UNPKG

29.2 kBJavaScriptView Raw
1"use strict";
2var task_utils_1 = require("./task.utils");
3var fs_1 = require("fs");
4var path_1 = require("path");
5var fs_2 = require("fs");
6var path_2 = require("path");
7var fs_3 = require("fs");
8var Rx = require("rx");
9var path_3 = require("path");
10var fs_4 = require("fs");
11var crypto_1 = require("crypto");
12var fs_5 = require("fs");
13var hd = require("hash-dir");
14var hashDirAsObservable = Rx.Observable.fromNodeCallback(hd);
15var hashFileAsObservable = Rx.Observable.fromNodeCallback(hashFile);
16var lstatAsObservable = Rx.Observable.fromNodeCallback(fs_5.lstat);
17var _ = require("../lodash.custom");
18// todo windows support for .bat files etc
19var supportedTaskFileExtensions = [".js", ".sh"];
20/**
21 * Try to auto-load configuration files
22 * from the users CWD
23 */
24function retrieveDefaultInputFiles(config) {
25 var defaultConfigFiles = ["crossbow.yaml", "crossbow.js", "crossbow.yml", "crossbow.json"];
26 return readInputFiles(defaultConfigFiles, config.cwd);
27}
28exports.retrieveDefaultInputFiles = retrieveDefaultInputFiles;
29/**
30 * Try to load cbfiles (like gulp) from the users
31 * working directory
32 * @param config
33 * @returns {InputFiles}
34 */
35function 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}
45exports.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 */
51function 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}
113exports.readInputFiles = readInputFiles;
114function readFilesFromDiskWithContent(paths, cwd) {
115 var files = readFilesFromDisk(paths, 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 });
123}
124exports.readFilesFromDiskWithContent = readFilesFromDiskWithContent;
125function readFileContent(file) {
126 return fs_1.readFileSync(file.resolved, "utf8");
127}
128exports.readFileContent = readFileContent;
129function writeFileToDisk(file, content) {
130 var mkdirp = require("mkdirp").sync;
131 mkdirp(path_3.dirname(file.resolved));
132 fs_1.writeFileSync(file.resolved, content);
133}
134exports.writeFileToDisk = writeFileToDisk;
135function getStubFileWithContent(path, cwd) {
136 var file = getStubFile(path, cwd);
137 file.content = "";
138 return file;
139}
140exports.getStubFileWithContent = getStubFileWithContent;
141function readOrCreateJsonFile(path, cwd) {
142 var existing = readFilesFromDiskWithContent([path], cwd)[0];
143 if (existing.errors.length) {
144 if (existing.errors[0].type === task_utils_1.InputErrorTypes.FileNotFound) {
145 var stub = getStubFileWithContent(path, cwd);
146 stub.content = "{}";
147 stub.data = JSON.parse(stub.content);
148 return stub;
149 }
150 }
151 else {
152 try {
153 existing.data = JSON.parse(existing.content);
154 }
155 catch (e) {
156 existing.data = {};
157 }
158 }
159 return existing;
160}
161exports.readOrCreateJsonFile = readOrCreateJsonFile;
162function getStubFile(path, cwd) {
163 var resolved = path_1.resolve(cwd, path);
164 return {
165 errors: [],
166 rawInput: path,
167 resolved: resolved,
168 parsed: path_1.parse(resolved),
169 relative: path_1.relative(cwd, resolved)
170 };
171}
172exports.getStubFile = getStubFile;
173/**
174 * Take an array of paths and return file info + errors if they don't exist
175 * @param paths
176 * @param cwd
177 * @returns {ExternalFile[]}
178 */
179function readFilesFromDisk(paths, cwd) {
180 return paths
181 .map(String)
182 .map(function (x) { return getStubFile(x, cwd); })
183 .map(function (incoming) {
184 var resolved = incoming.resolved;
185 /**
186 * If the path does not exist, it's a FileNotFound error
187 */
188 if (!fs_1.existsSync(resolved)) {
189 return _.assign(incoming, {
190 errors: [{ type: task_utils_1.InputErrorTypes.FileNotFound }]
191 });
192 }
193 /**
194 * Not check it's a file & NOT a dir
195 * @type {Stats}
196 */
197 var stat = fs_2.statSync(resolved);
198 if (!stat.isFile()) {
199 return _.assign(incoming, {
200 errors: [{ type: task_utils_1.InputErrorTypes.NotAFile }],
201 });
202 }
203 /**
204 * At this point the file DOES exist
205 */
206 return incoming;
207 });
208}
209exports.readFilesFromDisk = readFilesFromDisk;
210/**
211 * Attempt to use the LOCALLY installed crossbow version
212 * first, this will ensure anything registered with .task etc
213 * can be picked up by global installs too.
214 * @param config
215 * @returns {InputFiles}
216 */
217function getRequirePaths(config) {
218 var local = path_2.join("node_modules", "crossbow", "dist", "public", "create.js");
219 var global = path_2.join(__dirname, "public", "create.js");
220 return readInputFiles([local, global], config.cwd);
221}
222exports.getRequirePaths = getRequirePaths;
223function getExternalFiles(dirpaths, cwd) {
224 return dirpaths
225 .map(function (dirpath) {
226 return path_1.resolve(cwd, dirpath);
227 })
228 .filter(fs_1.existsSync)
229 .reduce(function (acc, dirPath) {
230 return acc.concat(fs_3.readdirSync(dirPath).map(function (filepath) {
231 var resolved = path_2.join(dirPath, filepath);
232 var parsed = path_1.parse(resolved);
233 var output = {
234 rawInput: filepath,
235 resolved: resolved,
236 relative: path_1.relative(cwd, resolved),
237 parsed: parsed,
238 errors: []
239 };
240 return output;
241 }));
242 }, []);
243}
244exports.getExternalFiles = getExternalFiles;
245function getPossibleTasksFromDirectories(dirpaths, cwd) {
246 return getExternalFiles(dirpaths, cwd)
247 .filter(function (x) { return supportedTaskFileExtensions.indexOf(x.parsed.ext) > -1; })
248 .map(function (x) {
249 return x.relative;
250 });
251}
252exports.getPossibleTasksFromDirectories = getPossibleTasksFromDirectories;
253(function (HashDirErrorTypes) {
254 HashDirErrorTypes[HashDirErrorTypes["HashNotADirectory"] = "HashNotADirectory"] = "HashNotADirectory";
255 HashDirErrorTypes[HashDirErrorTypes["HashPathNotFound"] = "HashPathNotFound"] = "HashPathNotFound";
256})(exports.HashDirErrorTypes || (exports.HashDirErrorTypes = {}));
257var HashDirErrorTypes = exports.HashDirErrorTypes;
258function hashItems(dirs, cwd, existingHashes) {
259 return Rx.Observable
260 .from(dirs)
261 .map(function (x) {
262 return {
263 userInput: x,
264 pathObj: getStubFile(x, cwd)
265 };
266 })
267 .distinct(function (x) { return x.pathObj.resolved; })
268 .flatMap(hashFileOrDir)
269 .toArray()
270 .map(function (x) {
271 return markHashes(x, existingHashes);
272 });
273}
274exports.hashItems = hashItems;
275function hashFile(filepath, fn) {
276 var hash = crypto_1.createHash("sha256");
277 fs_4.createReadStream(filepath)
278 .on("data", function (chunk) {
279 hash.update(chunk);
280 })
281 .on("end", function () {
282 fn(null, hash.digest("hex"));
283 })
284 .on("error", fn);
285}
286function hashFileOrDir(input) {
287 return lstatAsObservable(input.pathObj.resolved).flatMap(function (stats) {
288 if (stats.isDirectory()) {
289 return hashDirAsObservable(input.pathObj.resolved).map(function (tree) {
290 return {
291 userInput: input.userInput,
292 resolved: input.pathObj.resolved,
293 hash: tree.hash
294 };
295 });
296 }
297 if (stats.isFile()) {
298 return hashFileAsObservable(input.pathObj.resolved).map(function (hash) {
299 return {
300 userInput: input.userInput,
301 resolved: input.pathObj.resolved,
302 hash: hash
303 };
304 });
305 }
306 return Rx.Observable.empty();
307 });
308}
309function markHashes(newHashes, existingHashes) {
310 var newHashPaths = newHashes.map(function (x) { return x.resolved; });
311 var markedHashes = newHashes.map(function (newHash) {
312 var match = existingHashes.filter(function (x) { return x.resolved === newHash.resolved; });
313 newHash.changed = (function () {
314 if (match.length) {
315 return match[0].hash !== newHash.hash;
316 }
317 return true; // return true by default so that new entries always run
318 })();
319 return newHash;
320 });
321 var otherHashes = existingHashes.filter(function (hash) {
322 return newHashPaths.indexOf(hash.resolved) === -1;
323 });
324 var output = otherHashes.concat(newHashes).filter(Boolean);
325 return {
326 output: output,
327 markedHashes: markedHashes
328 };
329}
330var binDirectoryExists = function (path) {
331 return fs_1.existsSync(path)
332 ? exports.Right(path)
333 : exports.Left({ type: task_utils_1.InputErrorTypes.BinDirectoryNotFound });
334};
335var isDirectory = function (path) {
336 return fs_2.statSync(path).isDirectory()
337 ? exports.Right(path)
338 : exports.Left({ type: task_utils_1.InputErrorTypes.BinPathNotADirectory });
339};
340var joinPath = function (path, cwd) { return exports.Right(path_2.join(cwd, path)); };
341exports.getBinLookup = function (path, cwd) {
342 return joinPath(String(path), cwd)
343 .chain(function (resolved) { return exports.Right(resolved)
344 .chain(function (resolved) { return binDirectoryExists(resolved); })
345 .chain(function (resolved) { return isDirectory(resolved); })
346 .fold(function (error) {
347 return {
348 errors: [error],
349 resolved: resolved,
350 input: path
351 };
352 }, function (resolved) {
353 return {
354 errors: [],
355 resolved: resolved,
356 input: path
357 };
358 }); });
359};
360exports.getBinLookups = function (paths, cwd) {
361 return exports.Right([].concat(paths).map(function (path) { return exports.getBinLookup(path, cwd); }))
362 .chain(function (xs) {
363 return {
364 all: xs,
365 valid: xs.filter(function (x) { return x.errors.length === 0; }),
366 invalid: xs.filter(function (x) { return x.errors.length > 0; })
367 };
368 });
369};
370exports.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}); };
376exports.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}); };
382exports.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9maWxlLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSwyQkFBc0QsY0FBYyxDQUFDLENBQUE7QUFDckUsbUJBQXNELElBQUksQ0FBQyxDQUFBO0FBQzNELHFCQUF1QyxNQUFNLENBQUMsQ0FBQTtBQUc5QyxtQkFBdUIsSUFBSSxDQUFDLENBQUE7QUFDNUIscUJBQW1CLE1BQU0sQ0FBQyxDQUFBO0FBQzFCLG1CQUEwQixJQUFJLENBQUMsQ0FBQTtBQUMvQixJQUFPLEVBQUUsV0FBVyxJQUFJLENBQUMsQ0FBQztBQUMxQixxQkFBc0IsTUFBTSxDQUFDLENBQUE7QUFDN0IsbUJBQStCLElBQUksQ0FBQyxDQUFBO0FBQ3BDLHVCQUF5QixRQUFRLENBQUMsQ0FBQTtBQUNsQyxtQkFBMkIsSUFBSSxDQUFDLENBQUE7QUFFaEMsSUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQy9CLElBQU0sbUJBQW1CLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUMvRCxJQUFNLG9CQUFvQixHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDdEUsSUFBTSxpQkFBaUIsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLFVBQUssQ0FBQyxDQUFDO0FBRWhFLElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRXRDLDBDQUEwQztBQUMxQyxJQUFNLDJCQUEyQixHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBdUJuRDs7O0dBR0c7QUFDSCxtQ0FBMEMsTUFBNkI7SUFDbkUsSUFBTSxrQkFBa0IsR0FBRyxDQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLGVBQWUsQ0FBQyxDQUFD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
\No newline at end of file