UNPKG

3.92 kBJavaScriptView Raw
1/**
2 * @license MIT
3 * Copyright (c) 2016 Craig Monro (cmroanirgo)
4 **/
5"use strict";
6var l = require('ergo-utils').log.module('ergo-api-watch');
7var _ = require('ergo-utils')._;
8var fs = require('ergo-utils').fs.extend(require('fs-extra'));
9var path = require('path')
10var build_api = require('./build');
11var Promise = require('bluebird')
12
13
14var _watcher = null;
15
16function _rebuild(options, context) {
17 l.vlog("Changes detected. Rebuilding...");
18 options = _.extend({working_dir: context.getBasePath()
19 }, options)
20 var execFile = Promise.promisify(require('child_process').execFile);
21
22 var cmd = process.argv.slice(0,1).join(''); // this is the node command that was used to execute us (HOPEFULLY)
23 var args = [
24 process.argv.slice(1, 2).join(''), // this is the location of ergo-cli that was run
25 'build',
26 '--working_dir='+options.working_dir];
27 if (options.clean)
28 args.push('--clean')
29
30 l.vvlog("Running '"+cmd+"' with args: " + l.dump(args))
31 return execFile(cmd, args)
32 .catch(function(err) {
33 l.loge("Error when building:\n" + _.niceStackTrace(err));
34 return false;
35 })
36 .then(function(response) {
37 if (!response) {
38 return false; // from previous catch()
39 }
40
41
42 if (response.stderr && response.stderr.length>0)
43 l.loge("Errors when building: "+ response.stderr); // BUT DONT throw an error & allow continuation
44
45 l.log("Build complete " + response);
46 return true;
47 });
48}
49
50function _watch(options, context) {
51 if (!!_watcher)
52 return _watcher;
53
54 options.watch_dir = options.watch_dir || context.getBasePath(); // undocumented. only a dev might want this... probably
55 options.watch_delay = options.watch_delay || 300;
56 var fswatch_options = {
57 persistent: options.persistent || true // default is: true
58 , recursive: true
59 // default is :, encoding: 'utf8'
60 };
61 var build_options = {
62 working_dir: context.getBasePath()
63 };
64 if (options.clean)
65 build_options.clean = true;
66
67 var _changeTimeout = null;
68 var _changesWaiting = 0;
69 var _buildPromise = null;
70
71 var _rebuildTimerCallback = function() {
72 _changeTimeout = null;
73
74 if (!!_buildPromise) {
75 // too soon! We haven't finished the previous build and these changes may (or may not) be included.
76 // We need to back off for a while...
77 _changesWaiting++;
78 l.vvlog("Still building. Added to delayed build request.")
79 }
80 else
81 {
82 _changesWaiting = 0;
83 _buildPromise = _rebuild(build_options, context)
84 .then(function() {
85 _buildPromise = null;
86 if (_changesWaiting) {
87 l.vlog("Re-invoking delayed build request.")
88 _changeTimeout = setTimeout(_rebuildTimerCallback, options.watch_delay*5);
89 }
90 });
91 }
92 }
93
94 if (options.build)
95 _changeTimeout = setTimeout(_rebuildTimerCallback, options.watch_delay);
96
97
98 options.watch_dir = path.resolve(options.watch_dir);
99 l.log("Starting watch on: " + options.watch_dir);
100 _watcher = fs.watch(options.watch_dir, fswatch_options, function(eventType, filename) {
101 filename = path.resolve(options.watch_dir, filename);
102 // ignore the params themselves, except to log some information about the change:
103 if (fs.isInDir(context.getOutPath(), filename)) {
104 l.vlog("Ignoring changes for '" + filename + "'");
105 return;
106 }
107 l.vlog(eventType + ": '"+ filename + "'");
108
109 //
110 // do a 'lazy' reload. That is, keep delaying a build until 'n' millisecs of silence
111 // from this callback
112 if (_changeTimeout)
113 clearTimeout(_changeTimeout);
114 _changeTimeout = setTimeout(_rebuildTimerCallback, options.watch_delay);
115
116 })
117
118 return _watcher;
119}
120
121 module.exports = function(options) {
122 return Promise.try(function() {
123 options = options || {};
124
125 var context = require('./config').getContextSync(options.working_dir);
126 context.mergeRuntimeOptions(options);
127 return _watch(options, context);
128 });
129};
130
131// add facility to call without generating a new context
132module.exports.watch = _watch;
133module.exports.build = _rebuild;
134
135